def _Delete(self): """Delete a VM instance.""" stop_cmd = util.ALI_PREFIX + [ 'ecs', 'StopInstance', '--InstanceId %s' % self.id] stop_cmd = util.GetEncodedCmd(stop_cmd) vm_util.IssueRetryableCommand(stop_cmd) self._WaitForInstanceStatus(['Stopped']) delete_cmd = util.ALI_PREFIX + [ 'ecs', 'DeleteInstance', '--InstanceId %s' % self.id] delete_cmd = util.GetEncodedCmd(delete_cmd) vm_util.IssueRetryableCommand(delete_cmd) if FLAGS.ali_use_vpc: self._WaitForEipStatus(['Available']) release_eip_cmd = util.ALI_PREFIX + [ 'ecs', 'ReleaseEipAddress', '--RegionId %s' % self.region, '--AllocationId %s' % self.eip_id] release_eip_cmd = util.GetEncodedCmd(release_eip_cmd) vm_util.IssueRetryableCommand(release_eip_cmd)
def _AllocatePubIp(self, region, instance_id): """Allocate a public ip address and associate it to the instance""" if FLAGS.ali_use_vpc: allocatip_cmd = util.ALI_PREFIX + [ 'ecs', 'AllocateEipAddress', '--RegionId %s' % region, '--InternetChargeType PayByTraffic' ] allocatip_cmd = util.GetEncodedCmd(allocatip_cmd) stdout, _ = vm_util.IssueRetryableCommand(allocatip_cmd) response = json.loads(stdout) self.ip_address = response['EipAddress'] self.eip_id = response['AllocationId'] self._WaitForInstanceStatus(['Stopped', 'Running']) associate_cmd = util.ALI_PREFIX + [ 'ecs', 'AssociateEipAddress', '--RegionId %s' % region, '--AllocationId %s' % self.eip_id, '--InstanceId %s' % instance_id, '--InstanceType EcsInstance' ] associate_cmd = util.GetEncodedCmd(associate_cmd) vm_util.IssueRetryableCommand(associate_cmd) else: allocatip_cmd = util.ALI_PREFIX + [ 'ecs', 'AllocatePublicIpAddress', '--RegionId %s' % region, '--InstanceId %s' % instance_id ] allocatip_cmd = util.GetEncodedCmd(allocatip_cmd) stdout, _ = vm_util.IssueRetryableCommand(allocatip_cmd) response = json.loads(stdout) self.ip_address = response['IpAddress']
def _Create(self): """Create a VM instance.""" if self.image is None: # This is here and not in the __init__ method bceauese _GetDefaultImage # does a nontrivial amount of work (it calls the aliyuncli). self.image = self._GetDefaultImage(self.region) self.password = util.GeneratePassword() create_cmd = util.ALI_PREFIX + [ 'ecs', 'CreateInstance', '--InstanceName perfkit-%s' % FLAGS.run_uri, '--RegionId %s' % self.region, '--ZoneId %s' % self.zone, '--ImageId %s' % self.image, '--InstanceType %s' % self.machine_type, '--SecurityGroupId %s' % self.network.security_group.group_id, '--Password %s' % self.password] if FLAGS.scratch_disk_type == disk.LOCAL: disk_cmd = [ '--SystemDiskCategory ephemeral_ssd', '--DataDisk1Category ephemeral_ssd', '--DataDisk1Size %s' % self.scratch_disk_size, '--DataDisk1Device %s%s' % (util.GetDrivePathPrefix(), DRIVE_START_LETTER)] create_cmd.extend(disk_cmd) if FLAGS.ali_io_optimized is not None: create_cmd.extend(['--IoOptimized optimized', '--SystemDiskCategory %s' % self.system_disk_type]) if FLAGS.ali_use_vpc: create_cmd.extend(['--VpcId %s' % self.network.vpc.id, '--VSwitchId %s' % self.network.vswitch.id]) else: create_cmd.extend([ '--InternetChargeType PayByTraffic', '--InternetMaxBandwidthIn %s' % self.bandwidth_in, '--InternetMaxBandwidthOut %s' % self.bandwidth_out]) create_cmd = util.GetEncodedCmd(create_cmd) stdout, _ = vm_util.IssueRetryableCommand(create_cmd) response = json.loads(stdout) self.id = response['InstanceId'] self._AllocatePubIp(self.region, self.id) start_cmd = util.ALI_PREFIX + [ 'ecs', 'StartInstance', '--RegionId %s' % self.region, '--InstanceId %s' % self.id] start_cmd = util.GetEncodedCmd(start_cmd) vm_util.IssueRetryableCommand(start_cmd)
def _PostCreate(self): """Get the instance's data and tag it.""" describe_cmd = util.ALI_PREFIX + [ 'ecs', 'DescribeInstances', '--RegionId %s' % self.region, '--InstanceIds \'["%s"]\'' % self.id] logging.info('Getting instance %s public IP. This will fail until ' 'a public IP is available, but will be retried.', self.id) describe_cmd = util.GetEncodedCmd(describe_cmd) stdout, _ = vm_util.IssueRetryableCommand(describe_cmd) response = json.loads(stdout) instance = response['Instances']['Instance'][0] if self.network.use_vpc: pub_ip_address = instance['EipAddress']['IpAddress'] self.internal_ip = \ instance['VpcAttributes']['PrivateIpAddress']['IpAddress'][0] else: pub_ip_address = instance['PublicIpAddress']['IpAddress'][0] self.internal_ip = instance['InnerIpAddress']['IpAddress'][0] assert self.ip_address == pub_ip_address self.group_id = instance['SecurityGroupIds']['SecurityGroupId'][0] self._WaitForInstanceStatus(['Running']) self.firewall.AllowPort(self, SSH_PORT) tags = {} tags.update(self.vm_metadata) util.AddTags(self.id, RESOURCE_TYPE[INSTANCE], self.region, **tags) util.AddDefaultTags(self.id, RESOURCE_TYPE[INSTANCE], self.region)
def AllowPort(self, vm, port): """Opens a port on the firewall. Args: vm: The BaseVirtualMachine object to open the port for. port: The local port to open. """ if vm.is_static: return entry = (port, vm.group_id) if entry in self.firewall_set: return with self._lock: if entry in self.firewall_set: return for protocol in ('tcp', 'udp'): authorize_cmd = util.ALI_PREFIX + [ 'ecs', 'AuthorizeSecurityGroup', '--IpProtocol %s' % protocol, '--PortRange %s/%s' % (port, port), '--SourceCidrIp 0.0.0.0/0', '--RegionId %s' % vm.region, '--SecurityGroupId %s' % vm.group_id ] if FLAGS.ali_use_vpc: authorize_cmd.append('--NicType intranet') authorize_cmd = util.GetEncodedCmd(authorize_cmd) vm_util.IssueRetryableCommand(authorize_cmd) self.firewall_set.add(entry)
def _Delete(self): """Delete's the VPC.""" delete_cmd = util.ALI_PREFIX + [ 'ecs', 'DeleteVpc', '--RegionId %s' % self.region, '--VpcId %s' % self.id ] delete_cmd = util.GetEncodedCmd(delete_cmd) vm_util.IssueCommand(delete_cmd)
def _Delete(self): """Deletes the security group.""" delete_cmd = util.ALI_PREFIX + [ 'ecs', 'DeleteSecurityGroup', '--RegionId %s' % self.region, '--SecurityGroupId %s' % self.group_id ] delete_cmd = util.GetEncodedCmd(delete_cmd) vm_util.IssueRetryableCommand(delete_cmd)
def _Delete(self): """Deletes the VSwitch.""" delete_cmd = util.ALI_PREFIX + [ 'ecs', 'DeleteVSwitch', '--RegionId %s' % self.region, '--VSwitchId %s' % self.id ] delete_cmd = util.GetEncodedCmd(delete_cmd) vm_util.IssueCommand(delete_cmd, raise_on_failure=False)
def _Exists(self): """Returns true if the security group exists.""" show_cmd = util.ALI_PREFIX + [ 'ecs', 'DescribeSecurityGroupAttribute', '--RegionId %s' % self.region, '--SecurityGroupId %s' % self.group_id ] show_cmd = util.GetEncodedCmd(show_cmd) stdout, _ = vm_util.IssueRetryableCommand(show_cmd) return 'SecurityGroupId' in json.loads(stdout)
def _Delete(self): """Deletes the disk.""" delete_cmd = util.ALI_PREFIX + [ 'ecs', 'DeleteDisk', '--DiskId %s' % self.id ] logging.info( 'Deleting AliCloud disk %s. This may fail if the disk is not ' 'yet detached, but will be retried.', self.id) delete_cmd = util.GetEncodedCmd(delete_cmd) vm_util.IssueRetryableCommand(delete_cmd)
def _Create(self): """Creates the VPC.""" create_cmd = util.ALI_PREFIX + [ 'ecs', 'CreateVpc', '--VpcName %s' % self.name, '--RegionId %s' % self.region, '--CidrBlock 10.0.0.0/16' ] create_cmd = util.GetEncodedCmd(create_cmd) stdout, _, _ = vm_util.IssueCommand(create_cmd) response = json.loads(stdout) self.id = response['VpcId']
def _Create(self): """Creates the security group.""" create_cmd = util.ALI_PREFIX + [ 'ecs', 'CreateSecurityGroup', '--SecurityGroupName %s' % self.name, '--RegionId %s' % self.region ] if self.use_vpc: create_cmd.append('--VpcId %s' % self.vpc_id) create_cmd = util.GetEncodedCmd(create_cmd) stdout, _ = vm_util.IssueRetryableCommand(create_cmd) self.group_id = json.loads(stdout)['SecurityGroupId']
def _Create(self): """Creates the disk.""" create_cmd = util.ALI_PREFIX + [ 'ecs', 'CreateDisk', '--RegionId %s' % self.region, '--ZoneId %s' % self.zone, '--Size %s' % self.disk_size, '--DiskCategory %s' % DISK_TYPE[self.disk_type] ] create_cmd = util.GetEncodedCmd(create_cmd) stdout, _, _ = vm_util.IssueCommand(create_cmd) response = json.loads(stdout) self.id = response['DiskId']
def _Exists(self): """Returns true if the VPC exists.""" describe_cmd = util.ALI_PREFIX + [ 'ecs', 'DescribeVpcs', '--RegionId %s' % self.region, '--VpcId %s' % self.id ] describe_cmd = util.GetEncodedCmd(describe_cmd) stdout, _ = vm_util.IssueRetryableCommand(describe_cmd) response = json.loads(stdout) vpcs = response['Vpcs']['Vpc'] assert len(vpcs) < 2, 'Too many VPCs.' return len(vpcs) > 0
def _Exists(self): """Returns true if the VSwitch exists.""" describe_cmd = util.ALI_PREFIX + [ 'ecs', 'DescribeVSwitches', '--RegionId %s' % self.region, '--VpcId %s' % self.vpc_id, '--ZoneId %s' % self.zone ] describe_cmd = util.GetEncodedCmd(describe_cmd) stdout, _ = vm_util.IssueRetryableCommand(describe_cmd) response = json.loads(stdout) vswitches = response['VSwitches']['VSwitch'] assert len(vswitches) < 2, 'Too many VSwitches.' return len(vswitches) > 0
def _Create(self): """Creates the VSwitch.""" create_cmd = util.ALI_PREFIX + [ 'ecs', 'CreateVSwitch', '--VSwitchName %s' % self.name, '--ZoneId %s' % self.zone, '--CidrBlock 10.0.0.0/24', '--VpcId %s' % self.vpc_id, ] create_cmd = util.GetEncodedCmd(create_cmd) stdout, _, _ = vm_util.IssueCommand(create_cmd) response = json.loads(stdout) self.id = response['VSwitchId']
def _Exists(self): """Returns true if the security group exists.""" show_cmd = util.ALI_PREFIX + [ 'ecs', 'DescribeSecurityGroups', '--RegionId %s' % self.region, '--SecurityGroupId %s' % self.group_id ] show_cmd = util.GetEncodedCmd(show_cmd) stdout, _ = vm_util.IssueRetryableCommand(show_cmd) response = json.loads(stdout) securityGroups = response['SecurityGroups']['SecurityGroup'] assert len(securityGroups) < 2, 'Too many securityGroups.' if not securityGroups: return False return True
def Detach(self): """Detaches the disk from a VM.""" detach_cmd = util.ALI_PREFIX + [ 'ecs', 'DetachDisk', '--InstanceId %s' % self.attached_vm_id, '--DiskId %s' % self.id ] detach_cmd = util.GetEncodedCmd(detach_cmd) vm_util.IssueRetryableCommand(detach_cmd) with self._lock: assert self.attached_vm_id in AliDisk.vm_devices AliDisk.vm_devices[self.attached_vm_id].add(self.device_letter) self.attached_vm_id = None self.device_letter = None
def _WaitForEipStatus(self, status_list): """Waits until the instance's status is in status_list""" logging.info('Waits until the eip\'s status is one of statuses: %s', status_list) describe_cmd = util.ALI_PREFIX + [ 'ecs', 'DescribeEipAddresses', '--RegionId %s' % self.region, '--AllocationId %s' % self.eip_id] describe_cmd = util.GetEncodedCmd(describe_cmd) stdout, _ = vm_util.IssueRetryableCommand(describe_cmd) response = json.loads(stdout) EipAddresses = response['EipAddresses']['EipAddress'] assert len(EipAddresses) == 1 status = EipAddresses[0]['Status'] assert status in status_list
def _WaitForInstanceStatus(self, status_list): """Waits until the instance's status is in status_list""" logging.info('Waits until the instance\'s status is one of statuses: %s', status_list) describe_cmd = util.ALI_PREFIX + [ 'ecs', 'DescribeInstances', '--RegionId %s' % self.region, '--InstanceIds \'["%s"]\'' % self.id] describe_cmd = util.GetEncodedCmd(describe_cmd) stdout, _ = vm_util.IssueRetryableCommand(describe_cmd) response = json.loads(stdout) instances = response['Instances']['Instance'] assert len(instances) == 1 status = instances[0]['Status'] assert status in status_list
def _WaitForVpcStatus(self, status_list): """Waits until VPC's status is in status_list""" logging.info('Waits until the status of VPC is in status_list: %s', status_list) describe_cmd = util.ALI_PREFIX + [ 'ecs', 'DescribeVpcs', '--RegionId %s' % self.region, '--VpcId %s' % self.id ] describe_cmd = util.GetEncodedCmd(describe_cmd) stdout, _ = vm_util.IssueRetryableCommand(describe_cmd) response = json.loads(stdout) vpcs = response['Vpcs']['Vpc'] assert len(vpcs) == 1 vpc_status = response['Vpcs']['Vpc'][0]['Status'] assert vpc_status in status_list
def WaitForDiskStatus(self, status_list): """Waits until disk is attach to the instance""" logging.info('Waits until the disk\'s status is one of statuses: %s', status_list) describe_cmd = util.ALI_PREFIX + [ 'ecs', 'DescribeDisks', '--RegionId %s' % self.region, '--ZoneId %s' % self.zone, '--DiskIds \'["%s"]\'' % self.id ] attach_cmd = util.GetEncodedCmd(describe_cmd) stdout, _ = vm_util.IssueRetryableCommand(attach_cmd) response = json.loads(stdout) disk = response['Disks']['Disk'] assert len(disk) == 1 status = disk[0]['Status'] assert status in status_list
def _Exists(self): """Returns true if the VM exists.""" describe_cmd = util.ALI_PREFIX + [ 'ecs', 'DescribeInstances', '--RegionId %s' % self.region, '--InstanceIds \'["%s"]\'' % str(self.id)] describe_cmd = util.GetEncodedCmd(describe_cmd) stdout, _ = vm_util.IssueRetryableCommand(describe_cmd) response = json.loads(stdout) instances = response['Instances']['Instance'] assert len(instances) < 2, 'Too many instances.' if not instances: return False assert len(instances) == 1, 'Wrong number of instances.' status = instances[0]['Status'] assert status in INSTANCE_KNOWN_STATUSES, status return status in INSTANCE_EXISTS_STATUSES
def AllowIcmp(self, vm): """Opens the ICMP protocol on the firewall. Args: vm: The BaseVirtualMachine object to open the ICMP protocol for. """ if vm.is_static: return with self._lock: authorize_cmd = util.ALI_PREFIX + [ 'ecs', 'AuthorizeSecurityGroup', '--IpProtocol ICMP', '--PortRange -1/-1', '--SourceCidrIp 0.0.0.0/0', '--RegionId %s' % vm.region, '--SecurityGroupId %s' % vm.group_id ] if FLAGS.ali_use_vpc: authorize_cmd.append('--NicType intranet') authorize_cmd = util.GetEncodedCmd(authorize_cmd) vm_util.IssueRetryableCommand(authorize_cmd)
def Attach(self, vm): """Attaches the disk to a VM. Args: vm: The AliVirtualMachine instance to which the disk will be attached. """ with self._lock: self.attached_vm_id = vm.id if self.attached_vm_id not in AliDisk.vm_devices: AliDisk.vm_devices[self.attached_vm_id] = set( string.ascii_lowercase[1:]) self.device_letter = min(AliDisk.vm_devices[self.attached_vm_id]) AliDisk.vm_devices[self.attached_vm_id].remove(self.device_letter) attach_cmd = util.ALI_PREFIX + [ 'ecs', 'AttachDisk', '--InstanceId %s' % self.attached_vm_id, '--DiskId %s' % self.id, '--Device %s' % self.GetVirtualDevicePath() ] attach_cmd = util.GetEncodedCmd(attach_cmd) vm_util.IssueRetryableCommand(attach_cmd)
def _GetDefaultImage(cls, region): """Returns the default image given the machine type and region. If no default is configured, this will return None. """ if cls.IMAGE_NAME_FILTER is None: return None describe_cmd = util.ALI_PREFIX + [ 'ecs', 'DescribeImages', '--RegionId %s' % region, '--ImageName \'%s\'' % cls.IMAGE_NAME_FILTER] describe_cmd = util.GetEncodedCmd(describe_cmd) stdout, _ = vm_util.IssueRetryableCommand(describe_cmd) if not stdout: return None images = json.loads(stdout)['Images']['Image'] # We want to return the latest version of the image, and since the wildcard # portion of the image name is the image's creation date, we can just take # the image with the 'largest' name. return max(images, key=lambda image: image['ImageName'])['ImageId']
def _Create(self): """Create a VM instance.""" if self.image is None: # This is here and not in the __init__ method bceauese _GetDefaultImage # does a nontrivial amount of work (it calls the aliyuncli). self.image = self._GetDefaultImage(self.region) create_cmd = util.ALI_PREFIX + [ 'ecs', 'CreateInstance', '--InstanceName perfkit-%s' % FLAGS.run_uri, '--RegionId %s' % self.region, '--ZoneId %s' % self.zone, '--ImageId %s' % self.image, '--InstanceType %s' % self.machine_type, '--SecurityGroupId %s' % self.network.security_group.group_id, '--KeyPairName %s' % self.key_pair_name, '--SystemDisk.Category %s' % self.system_disk_type, '--SystemDisk.Size %s' % self.system_disk_size] if FLAGS.scratch_disk_type == disk.LOCAL: disk_cmd = [ '--DataDisk1Category ephemeral_ssd', '--DataDisk1Size %s' % self.scratch_disk_size, '--DataDisk1Device %s%s' % (util.GetDrivePathPrefix(), DRIVE_START_LETTER)] create_cmd.extend(disk_cmd) if FLAGS.ali_io_optimized is not None: create_cmd.extend(['--IoOptimized optimized']) if FLAGS.ali_use_vpc: create_cmd.extend(['--VSwitchId %s' % self.network.vswitch.id]) else: create_cmd.extend([ '--InternetChargeType PayByTraffic', '--InternetMaxBandwidthIn %s' % self.bandwidth_in, '--InternetMaxBandwidthOut %s' % self.bandwidth_out]) # Create user and add SSH key public_key = AliCloudKeyFileManager.GetPublicKey() user_data = util.ADD_USER_TEMPLATE.format(user_name=self.user_name, public_key=public_key) logging.debug('encoding startup script: %s', user_data) create_cmd.extend(['--UserData', six.ensure_str( base64.b64encode(user_data.encode('utf-8')))]) create_cmd = util.GetEncodedCmd(create_cmd) stdout, _ = vm_util.IssueRetryableCommand(create_cmd) response = json.loads(stdout) self.id = response['InstanceId'] self._AllocatePubIp(self.region, self.id) start_cmd = util.ALI_PREFIX + [ 'ecs', 'StartInstance', '--InstanceId %s' % self.id] start_cmd = util.GetEncodedCmd(start_cmd) vm_util.IssueRetryableCommand(start_cmd)