def _Create(self):
        """Create a Rackspace instance."""
        with tempfile.NamedTemporaryFile(dir=vm_util.GetTempDir(),
                                         prefix='user-data') as tf:
            with open(self.ssh_public_key) as f:
                public_key = f.read().rstrip('\n')

            script = CLOUD_CONFIG_TEMPLATE.format(self.user_name, public_key)
            tf.write(script)
            tf.flush()

            env = os.environ.copy()
            env.update(util.GetDefaultRackspaceNovaEnv(self.zone))
            create_cmd = self._GetCreateCommand()
            create_cmd.extend(
                ['--config-drive', 'true', '--user-data', tf.name, self.name])
            stdout, _, _ = vm_util.IssueCommand(create_cmd, env=env)
            instance = util.ParseNovaTable(stdout)
            if 'id' in instance:
                self.id = instance['id']
            else:
                raise errors.Resource.RetryableCreationError(
                    'There was a problem trying to create instance %s' %
                    self.name)

        if not self._WaitForInstanceUntilActive():
            raise errors.Resource.RetryableCreationError(
                'Failed to create instance')
 def AddMetadata(self, **kwargs):
     """Adds metadata to the Rackspace VM"""
     if not kwargs:
         return
     env = os.environ.copy()
     env.update(util.GetDefaultRackspaceNovaEnv(self.zone))
     cmd = [FLAGS.nova_path, 'meta', self.id, 'set']
     for key, value in kwargs.iteritems():
         cmd.append('{0}={1}'.format(key, value))
     vm_util.IssueCommand(cmd, env=env)
 def _Exists(self):
   """Returns true if the volume exists."""
   nova_env = os.environ.copy()
   nova_env.update(util.GetDefaultRackspaceNovaEnv(self.zone))
   getdisk_cmd = [FLAGS.nova_path, 'volume-show', self.name]
   stdout, _, _ = vm_util.IssueCommand(getdisk_cmd, env=nova_env)
   if stdout.strip() == '':
     return False
   volume = util.ParseNovaTable(stdout)
   return 'status' in volume and volume['status'] == 'available'
 def _Exists(self):
     """Returns true if the VM exists."""
     env = os.environ.copy()
     env.update(util.GetDefaultRackspaceNovaEnv(self.zone))
     getinstance_cmd = [FLAGS.nova_path, 'show', self.id]
     stdout, stderr, _ = vm_util.IssueCommand(getinstance_cmd, env=env)
     if stdout.strip() == '':
         return False
     instance = util.ParseNovaTable(stdout)
     return (instance.get('OS-EXT-STS:task_state') == 'deleting'
             or instance.get('status') == 'ACTIVE')
 def Detach(self):
     """Detaches the disk from a VM."""
     nova_env = os.environ.copy()
     nova_env.update(util.GetDefaultRackspaceNovaEnv(self.zone))
     detach_cmd = [
         FLAGS.nova_path,
         'volume-detach',
         self.attached_vm_name,
         self.id]
     vm_util.IssueRetryableCommand(detach_cmd, env=nova_env)
     self.attached_vm_name = None
    def _GetFlavorDetails(self):
        """Retrieves details about the flavor used to build the instance.

    Returns:
      A dict of properties of the flavor used to build the instance.
    """
        env = os.environ.copy()
        env.update(util.GetDefaultRackspaceNovaEnv(self.zone))
        flavor_show_cmd = [FLAGS.nova_path, 'flavor-show', self.machine_type]
        stdout, _, _ = vm_util.IssueCommand(flavor_show_cmd, env=env)
        flavor_properties = util.ParseNovaTable(stdout)
        return flavor_properties
 def _PostCreate(self):
     """Get the instance's data."""
     env = os.environ.copy()
     env.update(util.GetDefaultRackspaceNovaEnv(self.zone))
     getinstance_cmd = [FLAGS.nova_path, 'show', self.id]
     stdout, _, _ = vm_util.IssueCommand(getinstance_cmd, env=env)
     instance = util.ParseNovaTable(stdout)
     if 'status' in instance and instance['status'] == 'ACTIVE':
         self.ip_address = instance['accessIPv4']
         self.ip_address6 = instance['accessIPv6']
         self.internal_ip = instance['private network']
     else:
         raise errors.Error('Unexpected failure.')
  def _WaitForDiskUntilAttached(self, vm, max_retries=30, poll_interval_secs=5):
    """Wait until volume is attached to the instance."""
    env = os.environ.copy()
    env.update(util.GetDefaultRackspaceNovaEnv(self.zone))
    volume_show_cmd = [FLAGS.nova_path, 'volume-show', self.id]

    for _ in xrange(max_retries):
      stdout, _, _ = vm_util.IssueCommand(volume_show_cmd, env=env)
      volume = util.ParseNovaTable(stdout)
      if 'attachments' in volume and vm.id in volume['attachments']:
        return True
      time.sleep(poll_interval_secs)

    return False
  def _WaitForInstanceUntilActive(self, max_retries=720, poll_interval_secs=5):
    """Wait until instance achieves non-transient state."""
    env = os.environ.copy()
    env.update(util.GetDefaultRackspaceNovaEnv(self.zone))
    getinstance_cmd = [FLAGS.nova_path, 'show', self.id]

    for _ in xrange(max_retries):
      time.sleep(poll_interval_secs)
      stdout, _, _ = vm_util.IssueCommand(getinstance_cmd, env=env)
      instance = util.ParseNovaTable(stdout)
      if 'status' in instance and instance['status'] != 'BUILD':
        return instance['status'] == 'ACTIVE'

    return False
 def _Create(self):
   """Creates the volume."""
   nova_env = os.environ.copy()
   nova_env.update(util.GetDefaultRackspaceNovaEnv(self.zone))
   create_cmd = [
       FLAGS.nova_path,
       'volume-create',
       '--display-name', self.name,
       '--volume-type', DISK_TYPE[self.disk_type],
       str(self.disk_size)]
   stdout, _, _ = vm_util.IssueCommand(create_cmd, env=nova_env)
   volume = util.ParseNovaTable(stdout)
   if 'id' in volume and volume['id']:
     self.id = volume['id']
   else:
     raise errors.Error('There was a problem when creating a volume.')
  def Attach(self, vm):
    """Attaches the volume to a VM.

    Args:
      vm: The RackspaceVirtualMachine instance to which the volume will be
          attached.
    """
    self.attached_vm_name = vm.name
    nova_env = os.environ.copy()
    nova_env.update(util.GetDefaultRackspaceNovaEnv(self.zone))
    attach_cmd = [
        FLAGS.nova_path,
        'volume-attach',
        self.attached_vm_name,
        self.id, ""]
    vm_util.IssueRetryableCommand(attach_cmd, env=nova_env)

    if not self._WaitForDiskUntilAttached(vm):
      raise errors.Resource.RetryableCreationError(
          'Failed to attach all scratch disks to vms. Exiting...')
  def GetDevicePath(self):
    """Returns the path to the device inside the VM."""
    nova_env = os.environ.copy()
    nova_env.update(util.GetDefaultRackspaceNovaEnv(self.zone))
    getdisk_cmd = [FLAGS.nova_path, 'volume-show', self.name]
    stdout, _, _ = vm_util.IssueCommand(getdisk_cmd, env=nova_env)
    volume = util.ParseNovaTable(stdout)

    attachment_list = []
    if 'attachments' in volume and volume['attachments']:
      attachment_list = json.loads(volume['attachments'])

    if not attachment_list:
      raise errors.Error('Cannot determine volume %s attachments' % self.name)

    for attachment in attachment_list:
      if 'volume_id' in attachment and attachment['volume_id'] == self.id:
        return attachment['device']
    else:
      raise errors.Error(
          'Could not find device path in the volume %s attachments')
 def _Delete(self):
     """Delete a Rackspace VM instance."""
     env = os.environ.copy()
     env.update(util.GetDefaultRackspaceNovaEnv(self.zone))
     delete_cmd = [FLAGS.nova_path, 'delete', self.id]
     vm_util.IssueCommand(delete_cmd, env=env)
 def _Delete(self):
   """Deletes the volume."""
   nova_env = os.environ.copy()
   nova_env.update(util.GetDefaultRackspaceNovaEnv(self.zone))
   delete_cmd = [FLAGS.nova_path, 'volume-delete', self.name]
   vm_util.IssueCommand(delete_cmd, env=nova_env)