Пример #1
0
 def _CreateInstance(self):
   """Creates IBM Cloud VM instance."""
   cmd = ibm.IbmAPICommand(self)
   cmd.flags.update({
       'name': self.name,
       'imageid': self.imageid,
       'profile': self.profile,
       'vpcid': self.vpcid,
       'subnet': self.subnet,
       'key': self.key,
       'zone': self.zone
   })
   cmd.user_data = self.user_data
   if self.boot_volume_size > 0:
     cmd.flags['capacity'] = self.boot_volume_size
   cmd.flags['iops'] = self.boot_volume_iops
   if self.boot_encryption_key:
     cmd.flags['encryption_key'] = self.boot_encryption_key
   logging.info('Creating instance, flags: %s', cmd.flags)
   resp = json.loads(cmd.CreateInstance())
   if 'id' not in resp:
     raise errors.Error(f'IBM Cloud ERROR: Failed to create instance: {resp}')
   self.vmid = resp['id']
   self.vm_created = True
   logging.info('Instance created, id: %s', self.vmid)
   logging.info('Waiting for instance to start, id: %s', self.vmid)
   cmd.flags['instanceid'] = self.vmid
   status = cmd.InstanceStatus()
   assert status == ibm.States.RUNNING
   if status != ibm.States.RUNNING:
     logging.error('Instance start failed, status: %s', status)
   logging.info('Instance %s status %s', self.vmid, status)
Пример #2
0
 def _DeleteInstance(self):
   """Deletes a IBM Cloud VM instance."""
   cmd = ibm.IbmAPICommand(self)
   cmd.flags['instanceid'] = self.vmid
   cmd.InstanceDelete()
   self.vm_deleted = True
   logging.info('Instance deleted: %s', cmd.flags['instanceid'])
Пример #3
0
  def _Create(self):
    """Creates and starts a IBM Cloud VM instance."""
    self._CreateInstance()
    if self.subnet:  # this is for the primary vnic and fip
      self.fip_address, self.fip_id = self.network.CreateFip(
          self.name + 'fip', self.vmid)
      self.ip_address = self.fip_address
      self.internal_ip = self._WaitForIPAssignment(self.subnet)
      logging.info('Fip: %s, ip: %s', self.ip_address, self.internal_ip)

    if self.subnets:
      # create the extra vnics
      cmd = ibm.IbmAPICommand(self)
      cmd.flags['instanceid'] = self.vmid
      for subnet_name in self.subnets.keys():
        cmd.flags['name'] = subnet_name
        cmd.flags['subnet'] = self.subnets[subnet_name]['id']  # subnet id
        logging.info('Creating extra vnic for vmid: %s, subnet: %s', \
                     self.vmid, cmd.flags['subnet'])
        vnicid, ip_addr = cmd.InstanceVnicCreate()
        logging.info('Extra vnic created for vmid: %s, vnicid: %s, ip_addr: %s',
                     self.vmid, vnicid, ip_addr)
        self.subnets[subnet_name]['vnicid'] = vnicid
        self.subnets[subnet_name]['ip_addr'] = ip_addr
      logging.info('Extra vnics created for vmid: %s, subnets: %s',
                   self.vmid, self.subnets)
Пример #4
0
 def _WaitForVolumeAttachment(self, vm):
     """Waits and checks until the volume status is attached."""
     if self.vol_id is None:
         return
     volcmd = ibm.IbmAPICommand(self)
     volcmd.flags.update({
         'instanceid': self.attached_vm.vmid,
         'volume': self.vol_id
     })
     logging.info('Checking volume on instance %s, volume: %s', vm.vmid,
                  self.vol_id)
     status = None
     endtime = time.time() + _MAX_DISK_ATTACH_SECONDS
     while time.time() < endtime:
         resp = volcmd.InstanceShowVolume()
         if resp:
             resp = json.loads(resp)
             status = resp.get('status', 'unknown')
             logging.info('Checking instance volume status: %s', status)
             if status == ibm.States.ATTACHED:
                 logging.info('Remote volume %s has been attached to %s',
                              self.name, vm.name)
                 break
         time.sleep(2)
     if status != ibm.States.ATTACHED:
         logging.error('Failed to attach the volume')
         raise errors.Error('IBMCLOUD ERROR: failed to attach a volume.')
 def DeleteFip(self, vmid: str, fip_address: str, fipid: str):
     """Deletes fip in a IBM Cloud VM instance."""
     logging.info(
         'Deleting FIP, instanceid: %s, fip address: %s, fip id: %s', vmid,
         fip_address, fipid)
     cmd = ibm.IbmAPICommand(self)
     cmd.flags['fipid'] = fipid
     cmd.InstanceFipDelete()
Пример #6
0
 def _StopInstance(self):
   """Stops a IBM Cloud VM instance."""
   cmd = ibm.IbmAPICommand(self)
   cmd.flags['instanceid'] = self.vmid
   status = cmd.InstanceStop()
   logging.info('stop_instance_poll: last status is %s', status)
   if status != ibm.States.STOPPED:
     logging.error('Instance stop failed, status: %s', status)
Пример #7
0
 def _StartInstance(self):
   """Starts a IBM Cloud VM instance."""
   cmd = ibm.IbmAPICommand(self)
   cmd.flags['instanceid'] = self.vmid
   status = cmd.InstanceStart()
   logging.info('start_instance_poll: last status is %s', status)
   assert status == ibm.States.RUNNING
   if status != ibm.States.RUNNING:
     logging.error('Instance start failed, status: %s', status)
    def _Delete(self):
        """Deletes the vpc and subnets."""
        with self._lock:
            if (ibmcloud_virtual_machine.IbmCloudVirtualMachine.
                    validated_subnets > 0 and self.subnet):
                cmd = ibm.IbmAPICommand(self)
                cmd.flags.update({
                    'prefix': self.prefix,
                    'zone': self.zone,
                    'id': self.subnet,
                    'items': 'subnets'
                })
                logging.info('Deleting subnet: %s', self.subnet)
                cmd.DeleteResource()
                time_to_end = time.time() + _DEFAULT_TIMEOUT
                while cmd.GetResource(
                ) is not None and time_to_end < time.time():
                    logging.info(
                        'Subnet still exists, waiting to delete subnet: %s',
                        self.subnet)
                    time.sleep(5)
                    cmd.DeleteResource()
                ibmcloud_virtual_machine.IbmCloudVirtualMachine.validated_subnets -= 1

        # different lock so all threads get a chance to delete its subnet first
        with self._lock_vpc:
            if (self.subnet and self.vpcid not in ibmcloud_virtual_machine.
                    IbmCloudVirtualMachine.validated_resources_set):
                cmd = ibm.IbmAPICommand(self)
                # check till all subnets are gone
                time_to_end = time.time() + _DEFAULT_TIMEOUT
                while ibmcloud_virtual_machine.IbmCloudVirtualMachine.validated_subnets > 0:
                    logging.info('Subnets not empty yet')
                    if time_to_end < time.time():
                        break
                    time.sleep(10)
                cmd.flags['items'] = 'vpcs'
                cmd.flags['id'] = self.vpcid
                logging.info('Waiting to delete vpc')
                time.sleep(10)
                (ibmcloud_virtual_machine.IbmCloudVirtualMachine.
                 validated_resources_set.add(self.vpcid))
                cmd.DeleteResource()
                self.vpcid = None
 def _Delete(self):
   """Deletes an external block volume."""
   if self.vol_id is None:
     logging.info('Volume %s was not created. Skipping deletion.', self.name)
     return
   volcmd = ibm.IbmAPICommand(self)
   volcmd.flags['volume'] = self.vol_id
   logging.info('Volume delete, volcmd.flags %s', volcmd.flags)
   volcmd.DeleteVolume()
   logging.info('Volume deleted: %s', self.vol_id)
   self.vol_id = None
Пример #10
0
 def _CreateRiasKey(self):
   """Creates a ibmcloud key from the generated ssh key."""
   logging.info('Creating rias key')
   with open(vm_util.GetPublicKeyPath(), 'r') as keyfile:
     pubkey = keyfile.read()
   logging.info('ssh private key file: %s, public key file: %s', \
                vm_util.GetPrivateKeyPath(), vm_util.GetPublicKeyPath())
   cmd = ibm.IbmAPICommand(self)
   cmd.flags['name'] = self.prefix + str(flags.FLAGS.run_uri) + 'key'
   cmd.flags['pubkey'] = pubkey
   return cmd.CreateKey()
Пример #11
0
 def _DeleteKey(self):
   """Deletes the rias key."""
   with self._lock:
     # key is not dependent on vpc, one key is used
     if self.key not in IbmCloudVirtualMachine.validated_resources_set:
       time.sleep(5)
       cmd = ibm.IbmAPICommand(self)
       cmd.flags['items'] = 'keys'
       cmd.flags['id'] = self.key
       cmd.DeleteResource()
       IbmCloudVirtualMachine.validated_resources_set.add(self.key)
Пример #12
0
 def _CheckImage(self):
   """Verifies we have an imageid to use."""
   cmd = ibm.IbmAPICommand(self)
   cmd.flags['image_name'] = self.image or self._GetDefaultImageName()
   logging.info('Looking up image: %s', cmd.flags['image_name'])
   self.imageid = cmd.GetImageId()
   if self.imageid is None:
     logging.info('Failed to find valid image id')
     sys.exit(1)
   else:
     logging.info('Image id found: %s', self.imageid)
Пример #13
0
 def _GetDecodedPasswordData(self):
   # Retrieve a base64 encoded, encrypted password for the VM.
   cmd = ibm.IbmAPICommand(self)
   cmd.flags['instanceid'] = self.vmid
   resp = cmd.InstanceInitializationShow()
   logging.info('Instance %s, resp %s', self.vmid, resp)
   encrypted = None
   if resp and 'password' in resp and 'encrypted_password' in resp['password']:
     encrypted = resp['password']['encrypted_password']
   if encrypted is None:
     raise ValueError('Failed to retrieve encrypted password')
   return base64.b64decode(encrypted)
 def _Exists(self):
     """Returns true if the VPC exists."""
     cmd = ibm.IbmAPICommand(self)
     cmd.flags.update({
         'prefix': self.prefix,
         'zone': self.zone,
         'items': 'vpcs'
     })
     self.vpcid = cmd.GetResource()
     if self.vpcid:
         return True
     return False
    def _SetupResources(self):
        """Looks up the resources needed, if not found, creates new."""
        logging.info('Checking resources')
        cmd = ibm.IbmAPICommand(self)
        cmd.flags.update({
            'prefix': self.prefix,
            'zone': self.zone,
            'items': 'vpcs'
        })
        self.vpcid = cmd.GetResource()
        logging.info('Vpc found: %s', self.vpcid)
        cmd.flags['items'] = 'subnets'
        self.subnet = cmd.GetResource()
        logging.info('Subnet found: %s', self.subnet)

        if not self.vpcid:
            logging.info('Creating a vpc')
            self.network.Create()
            self.vpcid = self.network.vpcid

        if not self.subnet:
            logging.info('Creating a subnet')
            self.network.CreateSubnet(self.vpcid)
            self.subnet = self.network.subnet

        if FLAGS.ibmcloud_subnets_extra > 0:
            # these are always created outside perfkit
            cmd.flags['prefix'] = ibmcloud_network.SUBNET_SUFFIX_EXTRA
            self.subnets = cmd.ListSubnetsExtra()
            logging.info('Extra subnets found: %s', self.subnets)

        # look up for existing key that matches this run uri
        cmd.flags['items'] = 'keys'
        cmd.flags['prefix'] = self.prefix + FLAGS.run_uri
        self.key = cmd.GetResource()
        logging.info('Key found: %s', self.key)
        if self.key is None:
            cmd.flags['items'] = 'keys'
            cmd.flags['prefix'] = self.prefix + FLAGS.run_uri
            self.key = self._CreateRiasKey()
            if self.key is None:
                raise errors.Error(
                    'IBM Cloud ERROR: Failed to create a rias key')
            logging.info('Created a new key: %s', self.key)

        logging.info('Looking up the image: %s', self.imageid)
        cmd.flags['imageid'] = self.imageid
        self.os_data = util.GetOsInfo(cmd.ImageShow())
        logging.info('Image os: %s', self.os_data)
        logging.info('Checking resources finished')
 def Detach(self):
   """Deletes the volume from instance."""
   if self.attached_vm is None:
     logging.warning('Cannot detach remote volume from a non-existing VM.')
     return
   if self.attached_vdisk_uri is None:
     logging.warning('Cannot detach remote volume from a non-existing VDisk.')
     return
   volcmd = ibm.IbmAPICommand(self)
   volcmd.flags['volume'] = self.attached_vdisk_uri
   resp = volcmd.InstanceDeleteVolume()
   logging.info('Deleted volume: %s', resp)
   self.attached_vdisk_uri = None
   self.device_path = None
 def CreateFip(self, name: str, vmid: str):
     """Creates a VNIC in a IBM Cloud VM instance."""
     cmd = ibm.IbmAPICommand(self)
     cmd.flags['instanceid'] = vmid
     vnicid = cmd.InstanceGetPrimaryVnic()
     cmd.flags['name'] = name
     cmd.flags['target'] = vnicid
     logging.info('Creating FIP for instanceid: %s', vmid)
     resp = json.loads(cmd.InstanceFipCreate())
     if resp:
         logging.info('FIP create resp: %s', resp)
         assert resp['address'] is not None
         return resp['address'], resp['id']
     else:
         raise errors.Error(
             f'IBM Cloud ERROR: Failed to create fip for instance {vmid}')
Пример #18
0
 def setUp(self):
     super(IbmCloudVirtualMachineTest, self).setUp()
     self.mock_create_instance = self.enter_context(
         mock.patch.object(ibm_api.IbmAPICommand, 'CreateInstance'))
     self.mock_instance_status = self.enter_context(
         mock.patch.object(ibm_api.IbmAPICommand, 'InstanceStatus'))
     self.mock_get_resource = self.enter_context(
         mock.patch.object(ibm_api.IbmAPICommand, 'GetResource'))
     self.mock_create_vpc = self.enter_context(
         mock.patch.object(ibm_api.IbmAPICommand, 'CreateVpc'))
     self.mock_create_subnet = self.enter_context(
         mock.patch.object(ibm_api.IbmAPICommand, 'CreateSubnet'))
     self.mock_check_environment = self.enter_context(
         mock.patch.object(ibm_api.IbmAPICommand, '_CheckEnvironment'))
     with mock.patch.object(ibm_api.IbmAPICommand, '__init__',
                            lambda self: None):
         self.cmd = ibm_api.IbmAPICommand()
     self.vm = self._CreateTestIbmCloudVirtualMachine()
Пример #19
0
 def _Create(self):
     """Creates an external block volume."""
     volcmd = ibm.IbmAPICommand(self)
     volcmd.flags.update({
         'name': self.name,
         'zone': self.zone,
         'iops': FLAGS.ibmcloud_volume_iops,
         'profile': FLAGS.ibmcloud_volume_profile,
         'capacity': self.disk_size
     })
     if self.encryption_key is not None:
         volcmd.flags['encryption_key'] = self.encryption_key
     if FLAGS.ibmcloud_rgid:
         volcmd.flags['resource_group'] = FLAGS.ibmcloud_rgid
     logging.info('Volume create, volcmd.flags %s', volcmd.flags)
     resp = json.loads(volcmd.CreateVolume())
     self.vol_id = resp['id']
     logging.info('Volume id: %s', self.vol_id)
Пример #20
0
    def Attach(self, vm):
        """Attaches the disk to a VM.

    Args:
      vm: instance of the vm to which the disk will be attached.
    """
        if self.vol_id is None:
            raise errors.Error(f'Cannot attach remote volume {self.name}')
        if vm.vmid is None:
            raise errors.Error(f'Cannot attach remote volume {self.name} '
                               'to non-existing {vm.name} VM')

        volcmd = ibm.IbmAPICommand(self)
        volcmd.flags.update({
            'name': self.name,
            'instanceid': vm.vmid,
            'volume': self.vol_id,
            'delete': True
        })

        # wait till volume is PROVISIONED before attach
        status = None
        endtime = time.time() + _MAX_DISK_ATTACH_SECONDS
        while time.time() < endtime:
            status = json.loads(volcmd.ShowVolume())['status']
            logging.info('Checking volume status: %s', status)
            if status == ibm.States.AVAILABLE:
                logging.info('Volume is available')
                break
            time.sleep(2)

        if status != ibm.States.AVAILABLE:
            logging.error('Failed to create a volume')
            raise errors.Error('IBMCLOUD ERROR: failed to provision a volume.')

        resp = json.loads(volcmd.InstanceCreateVolume())
        logging.info('Attached volume, volcmd.flags %s', volcmd.flags)
        volume = resp['id']
        logging.info('VDISK ID: %s, vdiskname: %s, instanceid: %s', volume,
                     self.name, vm.vmid)
        self.attached_vdisk_uri = volume
        self.attached_vm = vm
        self._WaitForVolumeAttachment(vm)
        self._GetDeviceFromVDisk(vm)
 def _Create(self):
     """Creates a IBM Cloud VPC with address prefixes for all zones."""
     cmd = ibm.IbmAPICommand(self)
     cmd.flags['name'] = self.name
     logging.info('Creating vpc: %s', cmd.flags)
     self.vpcid = cmd.CreateVpc()
     if self.vpcid:
         for zone in FLAGS.zones:
             cmd.flags.update({'vpcid': self.vpcid, 'zone': zone})
             index = int(zone[len(zone) - 1])  # get the ending -1
             cmd.flags['cidr'] = VPC_PREFIX_RANGES[index - 1]
             cmd.flags[
                 'name'] = self.prefix + VPC_NAME + util.DELIMITER + zone
             resp = cmd.CreatePrefix()
             if resp:
                 logging.info('Created vpc prefix range: %s',
                              resp.get('id'))
             else:
                 raise errors.Error('IBM Cloud ERROR: Failed to create '
                                    'vpc address prefix')
     else:
         raise errors.Error('IBM Cloud ERROR: Failed to create vpc')
Пример #22
0
  def _WaitForIPAssignment(self, networkid: str):
    """Finds the IP address assigned to the vm."""
    ip_v4_address = '0.0.0.0'
    count = 0
    while (ip_v4_address == '0.0.0.0' and
           count * FLAGS.ibmcloud_polling_delay < 240):
      time.sleep(FLAGS.ibmcloud_polling_delay)
      count += 1
      cmd = ibm.IbmAPICommand(self)
      cmd.flags['instanceid'] = self.vmid
      logging.info('Looking for IP for instance %s, networkid: %s',
                   self.vmid, networkid)

      resp = cmd.InstanceShow()
      for network in resp['network_interfaces']:
        if network['subnet']['id'] == networkid:
          ip_v4_address = network['primary_ipv4_address']
          break
      logging.info('Waiting on ip assignment: %s', ip_v4_address)
    if ip_v4_address == '0.0.0.0':
      raise ValueError('Failed to retrieve ip address')
    return ip_v4_address
 def CreateSubnet(self, vpcid: str):
     """Creates a IBM Cloud subnet on the given vpc."""
     self.vpcid = vpcid
     subnet_index = int(self.zone[len(self.zone) - 1])  # get the ending -1
     cmd = ibm.IbmAPICommand(self)
     cmd.flags.update({
         'vpcid':
         self.vpcid,
         'zone':
         self.zone,
         'name': (self.prefix + VPC_NAME + util.SUBNET_SUFFIX +
                  str(subnet_index) + util.DELIMITER + self.zone),
         'cidr':
         VPC_SUBNETS[subnet_index - 1]
     })
     logging.info('Creating subnet: %s', cmd.flags)
     resp = cmd.CreateSubnet()
     if resp:
         self.subnet = resp.get('id')
         ibmcloud_virtual_machine.IbmCloudVirtualMachine.validated_subnets += 1
         logging.info('Created subnet: %s, zone %s', self.subnet, self.zone)
     else:
         raise errors.Error('IBM Cloud ERROR: Failed to create subnet')