   # `save` argument is true (the default) then the VM state is saved. Otherwise,
   # the VM is powered off immediately which may result in data loss.
   stop: (save=true) -> @ensureNotMissing().then => @ensureRunning().then =>
+    @debug "stop: #{if save then 'save' else 'poweroff'}"
     deferred = Q.defer()
     cmd = if save then 'savestate' else 'poweroff'
     @vbm 'controlvm', [cmd], (err, stdout, stderr) =>

  _waitForStatus: (statuses, deferred, delay=1000) ->
    statuses = [].concat statuses
    statusNames = (@constructor.statusName s for s in statuses).join ', '
    @debug "waitForStatus: #{statusNames}"
    return null if deferred.promise.isRejected()
    @status().then (status) =>
      return deferred.resolve status if status in statuses
      Q.delay(delay).then => @_waitForStatus statuses, deferred, delay

  waitForRunning: (timeout=60000, delay) ->
    @debug "waitForRunning"
    deferred = Q.defer()
    @_waitForStatus(@constructor.status.RUNNING, deferred, delay).fail (err) ->
      deferred.reject err
    deferred.promise.timeout timeout

  waitForNotRunning: (timeout=60000, delay) ->
    @debug "waitForNotRunning"
    deferred = Q.defer()
    @_waitForStatus([
      @constructor.status.POWEROFF

    deferred.promise.timeout timeout

  _waitForGuestControl: (deferred, delay=1000) ->
    @debug '_waitForGuestControl'
    return null if deferred.promise.isRejected()
    @info().then (info) =>
      runlevel = info.GuestAdditionsRunLevel
      @debug "_waitForGuestControl: runlevel #{runlevel}"
      return deferred.resolve true if runlevel? and parseInt(runlevel) > 2
      Q.delay(delay).then => @_waitForGuestControl deferred, delay

