def run(self, connection, state, *pargs, **kwargs):
        """
        Send an HTTP POST request to the nova cluster to destroy
        a random ACTIVE server. Update `state` to indicate TERMINATING.

        `connection` : object returned by kong.nova.API
        `state`      : `State` object describing our view of state of cluster
        `pargs`      : positional arguments
        `kwargs`     : keyword arguments, which include:
                       `timeout` : how long to wait before issuing Exception
        """
        # check for active machines
        vms = state.get_machines()
        active_vms = [v for k, v in vms.iteritems() if v and v[1] == 'ACTIVE']
        # no active vms, so return null
        if not active_vms:
            self._logger.info('no ACTIVE machines to delete')
            return

        _timeout = kwargs.get('timeout', 600)

        target = random.choice(active_vms)
        kill_target = target[0]
        connection.delete_server(kill_target['id'])
        self._logger.info('machine %s: ACTIVE -> TERMINATING' %
                          kill_target['id'])
        state.set_machine_state(kill_target['id'],
                                (kill_target, 'TERMINATING'))
        return VerifyKillActiveVM(connection, state, kill_target, timeout=_timeout)
    def run(self, connection, state, *pargs, **kwargs):
        """
        Send an HTTP POST request to the nova cluster to resize a random
        server. Update `state` to indicate server is rebooting.

        `connection` : object returned by kong.nova.API
        `state`      : `State` object describing our view of state of cluster
        `pargs`      : positional arguments
        `kwargs`     : keyword arguments, which include:
                       `timeout` : how long to wait before issuing Exception
        """

        vms = state.get_machines()
        active_vms = [v for k, v in vms.iteritems() if v and v[1] == 'ACTIVE']
        # no active vms, so return null
        if not active_vms:
            self._logger.debug('no ACTIVE machines to resize')
            return

        target = random.choice(active_vms)
        resize_target = target[0]
        print resize_target

        _timeout = kwargs.get('timeout', 600)

        # determine current flavor type, and resize to a different type
        # m1.tiny -> m1.small, m1.small -> m1.tiny
        curr_size = int(resize_target['flavor']['id'])
        if curr_size == 1:
            new_size = 2
        else:
            new_size = 1
        flavor_type = { 'flavorRef': new_size } # resize to m1.small

        post_body = json.dumps({'resize' : flavor_type})
        url = '/servers/%s/action' % resize_target['id']
        (response, body) = connection.request('POST',
                                              url,
                                              body=post_body)

        if (response.status != 202):
            self._logger.error("response: %s" % response)
            raise Exception

        state_name = check_for_status(connection, resize_target, 'RESIZE')

        if state_name == 'RESIZE':
            self._logger.info('machine %s: ACTIVE -> RESIZE' %
                              resize_target['id'])
            state.set_machine_state(resize_target['id'],
                                    (resize_target, 'RESIZE'))

        return VerifyResizeVM(connection,
                              state,
                              resize_target,
                              state_name=state_name,
                              timeout=_timeout)
    def run(self, connection, state, *pargs, **kwargs):
        """
        Issue HTTP POST request to change the name of active server.
        Update state of server to reflect name changing.

        `connection` : object returned by kong.nova.API
        `state`      : `State` object describing our view of state of cluster
        `pargs`      : positional arguments
        `kwargs`     : keyword arguments, which include:
                       `timeout`   : how long to wait before issuing Exception
        """

        # select one machine from active ones
        vms = state.get_machines()
        active_vms = [v for k, v in vms.iteritems() if v and v[1] == 'ACTIVE']
        # no active vms, so return null
        if not active_vms:
            self._logger.info('no active machines to update')
            return

        _timeout = kwargs.get('timeout', 600)

        target = random.choice(active_vms)
        update_target = target[0]

        # Update name by appending '_updated' to the name
        new_server = {'name': update_target['name'] + '_updated'}
        put_body = json.dumps({
                'server': new_server,
                })
        url = '/servers/%s' % update_target['id']
        (response, body) = connection.request('PUT',
                                              url,
                                              body=put_body)
        if (response.status != 200):
            self._logger.error("response: %s " % response)
            self._logger.error("body: %s " % body)
            raise Exception

        data = json.loads(body)
        assert(data.keys() == ['server'])
        _assert_server_entity(data['server'], connection)
        assert(update_target['name'] + '_updated' == data['server']['name'])

        self._logger.info('machine %s: ACTIVE -> UPDATING_NAME' %
                          data['server']['id'])
        state.set_machine_state(data['server']['id'],
                                (data['server'], 'UPDATING_NAME'))

        return VerifyUpdateVMName(connection,
                                  state,
                                  data['server'],
                                  timeout=_timeout)
    def run(self, connection, state, *pargs, **kwargs):
        """
        Send an HTTP POST request to the nova cluster to reboot a random
        server. Update state of object in `state` variable to indicate that
        it is rebooting.
        `connection` : object returned by kong.nova.API
        `state`      : `State` object describing our view of state of cluster
        `pargs`      : positional arguments
        `kwargs`     : keyword arguments, which include:
                       `timeout` : how long to wait before issuing Exception
                       `type`    : reboot type [SOFT or HARD] (default is SOFT)
        """

        vms = state.get_machines()
        active_vms = [v for k, v in vms.iteritems() if v and v[1] == 'ACTIVE']
        # no active vms, so return null
        if not active_vms:
            self._logger.info('no ACTIVE machines to reboot')
            return

        _reboot_type = kwargs.get('type', 'SOFT')
        _timeout = kwargs.get('timeout', 600)

        # select active vm to reboot and then send request to nova controller
        target = random.choice(active_vms)
        reboot_target = target[0]

        # allocate public address to this vm
        _ip_addr = allocate_ip(connection, reboot_target)

        reboot_body = { 'type': _reboot_type }
        post_body = json.dumps({'reboot' : reboot_body})
        url = '/servers/%s/action' % reboot_target['id']
        (response, body) = connection.request('POST',
                                              url,
                                              body=post_body)

        if (response.status != 202):
            self._logger.error("response: %s" % response)
            raise Exception

        if _reboot_type == 'SOFT':
            state_name = 'REBOOT'
        else:
            state_name = 'REBOOT' ### this is a bug, should be HARD_REBOOT

        self._logger.info('waiting for machine %s to change to %s' %
                          (reboot_target['id'], state_name))

        # check for state transition
        try:
            state_string = state_name
            connection.wait_for_server_status(
                reboot_target['id'], state_name, timeout=0
                )
        except AssertionError:
            # grab the actual state as we think it is
            temp_obj = state.get_machines()[self._target['id']]
            self._logger.debug(
                "machine %s in state %s" %
                (reboot_target['id'], temp_obj[1])
                )
            state_string = temp_obj[1]

        if state_string == state_name:
            self._logger.info('machine %s ACTIVE -> %s' %
                              (reboot_target['id'], state_name))
            state.set_machine_state(reboot_target['id'],
                                    (reboot_target, state_name))

        return VerifyRebootVM(connection,
                              state,
                              reboot_target,
                              timeout=_timeout,
                              reboot_type=_reboot_type,
                              state_name=state_string,
                              ip_addr=_ip_addr)
    def retry(self):
        """
        Check to see that the server was actually resized. And change `state`
        of server to running again.
        """
        # don't run resize if target machine has been deleted
        # or is going to be deleted
        if (self._target['id'] not in self._state.get_machines().keys() or
            self._state.get_machines()[self._target['id']][1] == 'TERMINATING'):
            self._logger.debug('machine %s is deleted or TERMINATING' %
                               self._target['id'])
            return True

        if time.time() - self._start_time > self._timeout:
            raise TimeoutException

        if self._retry_state == self.States.VERIFY_RESIZE_CHECK:
            if self._check_for_status('VERIFY_RESIZE') == 'VERIFY_RESIZE':
                # now issue command to CONFIRM RESIZE
                post_body = json.dumps({'confirmResize' : null})
                url = '/servers/%s/action' % self._target['id']
                (response, body) = connection.request('POST',
                                                      url,
                                                      body=post_body)
                if (response.status != 204):
                    self._logger.error("response: %s" % response)
                    raise Exception

                self._logger.info(
                    'CONFIRMING RESIZE of machine %s [%.1f secs elapsed]' %
                    (self._target['id'], time.time() - self._start_time)
                    )
                state.set_machine_state(self._target['id'],
                                        (self._target, 'CONFIRM_RESIZE'))

                # change states
                self._retry_state = self.States.ACTIVE_CHECK

            return False

        elif self._retry_state == self.States.ACTIVE_CHECK:
            if not self._check_connection("ACTIVE"):
                return False
            else:
                server = self._connection.get_server(self._target['id'])

                # Find private IP of server?
                try:
                    (_, network) = server['addresses'].popitem()
                    ip = network[0]['addr']
                except KeyError:
                    self._logger.error(
                        'could not get ip address for machine %s' %
                        self._target['id']
                        )
                    raise Exception

                self._logger.info(
                    'machine %s: VERIFY_RESIZE -> ACTIVE [%.1f secs elapsed]' %
                    (self._target['id'], time.time() - self._start_time)
                    )
                self._state.set_machine_state(self._target['id'],
                                              (self._target, 'ACTIVE'))

                return True

        else:
            # should never get here
            self._logger.error('Unexpected state')
            raise Exception
    def run(self, connection, state, *pargs, **kwargs):
        """
        Send an HTTP POST request to the nova cluster to build a
        server. Update the state variable to track state of new server
        and set to PENDING state.

        `connection` : object returned by kong.nova.API
        `state`      : `State` object describing our view of state of cluster
        `pargs`      : positional arguments
        `kwargs`     : keyword arguments, which include:
                       `key_name`  : name of keypair
                       `timeout`   : how long to wait before issuing Exception
                       `image_ref` : index to image types availablexs
                       `flavor_ref`: index to flavor types available
                                     (default = 1, which is tiny)
        """

        # restrict number of instances we can launch
        if len(state.get_machines()) >= state.get_max_machines():
            self._logger.debug("maximum number of machines created: %d" % 
                               state.get_max_machines())
            return None

        _key_name = kwargs.get('key_name', '')
        _timeout = int(kwargs.get('timeout', 60))
        _image_ref = int(kwargs.get('image_ref', 2))
        _flavor_ref = int(kwargs.get('flavor_ref', 1))

        expected_server = {
            'name': 'server' + str(TestCreateVM._vm_id),
            'metadata': {
                'key1': 'value1',
                'key2': 'value2',
                },
            'imageRef': _image_ref,
            'flavorRef': _flavor_ref,
            'adminPass': '******',
            'key_name' : _key_name
            }
        TestCreateVM._vm_id = TestCreateVM._vm_id + 1

        post_body = json.dumps({'server': expected_server})
        (response, body) = connection.request('POST',
                                              '/servers',
                                              body=post_body)
        if (response.status != 202):
            self._logger.error("response: %s" % response)
            self._logger.error("body: %s" % body)
            raise Exception

        _body = json.loads(body)
        assert(_body.keys() == ['server'])
        created_server = _body['server']

        self._logger.info('setting machine %s to BUILD' %
                          created_server['id'])
        state.set_machine_state(created_server['id'],
                                (created_server, 'BUILD'))

        return VerifyCreateVM(connection,
                              state,
                              created_server,
                              expected_server,
                              timeout=_timeout)