def ImportKeyfile(cls, region): """Imports the public keyfile to AWS.""" with cls._lock: if _GetKeyfileSetKey(region) in cls.imported_keyfile_set: return cat_cmd = ['cat', vm_util.GetPublicKeyPath()] keyfile, _ = vm_util.IssueRetryableCommand(cat_cmd) formatted_tags = util.FormatTagSpecifications('key-pair', util.MakeDefaultTags()) import_cmd = util.AWS_PREFIX + [ 'ec2', '--region=%s' % region, 'import-key-pair', '--key-name=%s' % cls.GetKeyNameForRun(), '--public-key-material=%s' % keyfile, '--tag-specifications=%s' % formatted_tags, ] _, stderr, retcode = vm_util.IssueCommand( import_cmd, raise_on_failure=False) if retcode: if 'KeyPairLimitExceeded' in stderr: raise errors.Benchmarks.QuotaFailure( 'KeyPairLimitExceeded in %s: %s' % (region, stderr)) else: raise errors.Benchmarks.PrepareException(stderr) cls.imported_keyfile_set.add(_GetKeyfileSetKey(region)) if _GetKeyfileSetKey(region) in cls.deleted_keyfile_set: cls.deleted_keyfile_set.remove(_GetKeyfileSetKey(region))
def _Create(self): """Creates the Placement Group.""" formatted_tags = util.FormatTagSpecifications('placement-group', util.MakeDefaultTags()) create_cmd = util.AWS_PREFIX + [ 'ec2', 'create-placement-group', '--region=%s' % self.region, '--group-name=%s' % self.name, '--strategy=%s' % self.strategy, '--tag-specifications=%s' % formatted_tags ] vm_util.IssueCommand(create_cmd)
def _Create(self): """Create a VM instance.""" placement = [] if not util.IsRegion(self.zone): placement.append('AvailabilityZone=%s' % self.zone) if self.use_dedicated_host: placement.append('Tenancy=host,HostId=%s' % self.host.id) num_hosts = len(self.host_list) elif self.placement_group: if IsPlacementGroupCompatible(self.machine_type): placement.append('GroupName=%s' % self.placement_group.name) else: logging.warn( 'VM not placed in Placement Group. VM Type %s not supported', self.machine_type) placement = ','.join(placement) block_device_map = GetBlockDeviceMap(self.machine_type, self.boot_disk_size, self.image, self.region) tags = {} tags.update(self.vm_metadata) tags.update(util.MakeDefaultTags()) create_cmd = util.AWS_PREFIX + [ 'ec2', 'run-instances', '--region=%s' % self.region, '--subnet-id=%s' % self.network.subnet.id, '--client-token=%s' % self.client_token, '--image-id=%s' % self.image, '--instance-type=%s' % self.machine_type, '--key-name=%s' % AwsKeyFileManager.GetKeyNameForRun(), '--tag-specifications=%s' % util.FormatTagSpecifications('instance', tags)] if FLAGS.aws_efa: create_cmd.extend([ '--network-interfaces', ','.join(['%s=%s' % item for item in sorted(_EFA_PARAMS.items())]) ]) else: create_cmd.append('--associate-public-ip-address') if block_device_map: create_cmd.append('--block-device-mappings=%s' % block_device_map) if placement: create_cmd.append('--placement=%s' % placement) if FLAGS.aws_credit_specification: create_cmd.append('--credit-specification=%s' % FLAGS.aws_credit_specification) if self.user_data: create_cmd.append('--user-data=%s' % self.user_data) if self.capacity_reservation_id: create_cmd.append( '--capacity-reservation-specification=CapacityReservationTarget=' '{CapacityReservationId=%s}' % self.capacity_reservation_id) if self.use_spot_instance: instance_market_options = collections.OrderedDict() spot_options = collections.OrderedDict() spot_options['SpotInstanceType'] = 'one-time' spot_options['InstanceInterruptionBehavior'] = 'terminate' if self.spot_price: spot_options['MaxPrice'] = str(self.spot_price) instance_market_options['MarketType'] = 'spot' instance_market_options['SpotOptions'] = spot_options create_cmd.append( '--instance-market-options=%s' % json.dumps(instance_market_options)) _, stderr, retcode = vm_util.IssueCommand(create_cmd, raise_on_failure=False) machine_type_prefix = self.machine_type.split('.')[0] host_arch = _MACHINE_TYPE_PREFIX_TO_HOST_ARCH.get(machine_type_prefix) if host_arch: self.host_arch = host_arch if self.use_dedicated_host and 'InsufficientCapacityOnHost' in stderr: if self.num_vms_per_host: raise errors.Resource.CreationError( 'Failed to create host: %d vms of type %s per host exceeds ' 'memory capacity limits of the host' % (self.num_vms_per_host, self.machine_type)) else: logging.warning( 'Creation failed due to insufficient host capacity. A new host will ' 'be created and instance creation will be retried.') with self._lock: if num_hosts == len(self.host_list): host = AwsDedicatedHost(self.machine_type, self.zone) self.host_list.append(host) host.Create() self.host = self.host_list[-1] self.client_token = str(uuid.uuid4()) raise errors.Resource.RetryableCreationError() if 'InsufficientInstanceCapacity' in stderr: if self.use_spot_instance: self.spot_status_code = 'InsufficientSpotInstanceCapacity' self.early_termination = True raise errors.Benchmarks.InsufficientCapacityCloudFailure(stderr) if 'SpotMaxPriceTooLow' in stderr: self.spot_status_code = 'SpotMaxPriceTooLow' self.early_termination = True raise errors.Resource.CreationError(stderr) if 'InstanceLimitExceeded' in stderr: raise errors.Benchmarks.QuotaFailure(stderr) if retcode: raise errors.Resource.CreationError( 'Failed to create VM: %s return code: %s' % (retcode, stderr))
def _BuildContext(launcher_vm, booter_template_vm): """Returns the context variables for Jinja2 template during rendering.""" context = { 'boot_machine_type': booter_template_vm.machine_type, 'cloud': FLAGS.cloud, 'contact_launcher': FLAGS.vms_contact_launcher, 'launcher_vm_name': launcher_vm.name, 'os_type': 'linux' if _IsLinux() else 'windows', 'server_ip': launcher_vm.internal_ip, 'server_port': _PORT, 'start_time_file': _START_TIME_FILE_PATH, 'timeout': _TIMEOUT_SECONDS, 'vm_count': FLAGS.boots_per_launcher, 'zone': launcher_vm.zone, 'use_public_ip': '' if FLAGS.use_public_ip else 'no-', } cloud = FLAGS.cloud if cloud == 'GCP': context.update({ 'boot_disk_size': booter_template_vm.boot_disk_size, 'boot_vm_name_prefix': _BOOT_VM_NAME_PREFIX.format(launcher_name=launcher_vm.name), 'image_family': booter_template_vm.image_family, 'image_project': booter_template_vm.image_project, 'gcloud_path': FLAGS.gcloud_path, 'project': FLAGS.project, 'tags': gcp_util.MakeFormattedDefaultTags(), }) elif cloud == 'AWS': tags = aws_util.MakeDefaultTags() tags.update({'launcher_id': launcher_vm.name}) context.update({ 'group_name': booter_template_vm.placement_group.name, 'image': booter_template_vm.image, 'key_name': 'perfkit-key-{0}'.format(FLAGS.run_uri), 'region': aws_util.GetRegionFromZone(launcher_vm.zone), 'subnet_id': booter_template_vm.network.subnet.id, 'tags': aws_util.FormatTagSpecifications('instance', tags), }) elif cloud == 'Azure': context.update({ 'boot_vm_name_prefix': launcher_vm.name.split('-', 1)[1], 'location': launcher_vm.region, 'image': booter_template_vm.image, 'storage_sku': booter_template_vm.os_disk.disk_type, 'resource_group': launcher_vm.resource_group.name, 'nic': _BOOT_NIC_NAME_PREFIX.format(run_uri=FLAGS.run_uri), 'password': booter_template_vm.password, 'start_id': GetAzBootVMStartIdByLauncher(launcher_vm.name), }) return context