Пример #1
0
    def post_init(self):
        """Initialize EC2 cloud framework class."""

        self.service_account_file = (
            self.custom_args.get('service_account_file') or
            self.ipa_config['service_account_file']
        )
        if not self.service_account_file:
            raise GCECloudException(
                'Service account file is required to connect to GCE.'
            )
        else:
            self.service_account_file = os.path.expanduser(
                self.service_account_file
            )

        if not self.ssh_private_key_file:
            raise GCECloudException(
                'SSH private key file is required to connect to instance.'
            )

        self.ssh_user = self.ssh_user or GCE_DEFAULT_USER
        self.ssh_public_key = self._get_ssh_public_key()
        self.image_project = self.custom_args.get('image_project')
        self.sev_capable = self.custom_args.get('sev_capable')
        self.use_gvnic = self.custom_args.get('use_gvnic')

        self.credentials = self._get_credentials()
        self.compute_driver = self._get_driver()

        self._validate_region()
Пример #2
0
    def __init__(self,
                 cleanup=None,
                 config=None,
                 description=None,
                 distro_name=None,
                 early_exit=None,
                 history_log=None,
                 image_id=None,
                 inject=None,
                 instance_type=None,
                 log_level=None,
                 no_default_test_dirs=False,
                 cloud_config=None,
                 region=None,
                 results_dir=None,
                 running_instance_id=None,
                 service_account_file=None,
                 ssh_private_key_file=None,
                 ssh_user=None,
                 subnet_id=None,
                 test_dirs=None,
                 test_files=None,
                 timeout=None,
                 collect_vm_info=None,
                 image_project=None,
                 enable_secure_boot=None,
                 enable_uefi=None,
                 log_callback=None):
        super(GCECloud,
              self).__init__('gce', cleanup, config, description, distro_name,
                             early_exit, history_log, image_id, inject,
                             instance_type, log_level, no_default_test_dirs,
                             cloud_config, region, results_dir,
                             running_instance_id, test_dirs, test_files,
                             timeout, collect_vm_info, ssh_private_key_file,
                             ssh_user, subnet_id, enable_secure_boot,
                             enable_uefi, log_callback)

        self.service_account_file = (service_account_file or
                                     self.ipa_config['service_account_file'])
        if not self.service_account_file:
            raise GCECloudException(
                'Service account file is required to connect to GCE.')
        else:
            self.service_account_file = os.path.expanduser(
                self.service_account_file)

        if not self.ssh_private_key_file:
            raise GCECloudException(
                'SSH private key file is required to connect to instance.')

        self.ssh_user = self.ssh_user or GCE_DEFAULT_USER
        self.ssh_public_key = self._get_ssh_public_key()
        self.image_project = image_project

        self.credentials = self._get_credentials()
        self.compute_driver = self._get_driver()

        self._validate_region()
Пример #3
0
    def _validate_region(self):
        """Validate region was passed in and is a valid GCE zone."""
        if not self.region:
            raise GCECloudException(
                'Zone is required for GCE cloud framework: '
                'Example: us-west1-a')

        try:
            zone = self.compute_driver.zones().get(
                project=self.service_account_project,
                zone=self.region).execute()
        except Exception:
            zone = None

        if not zone:
            raise GCECloudException(
                '{region} is not a valid GCE zone. '
                'Example: us-west1-a'.format(region=self.region))
Пример #4
0
def handle_gce_http_errors(type_name, resource_name):
    """
    Context manager to handle GCE HTTP Errors.
    """
    try:
        yield
    except Exception as error:
        message = get_message_from_http_error(error, resource_name)

        raise GCECloudException(
            'Unable to retrieve {type_name}: {error}'.format(
                type_name=type_name, error=message)) from error
Пример #5
0
    def _get_credentials(self):
        """Retrieve credentials object using service account file."""
        with open(self.service_account_file, 'r') as f:
            info = json.load(f)

        self.service_account_email = info.get('client_email')
        if not self.service_account_email:
            raise GCECloudException(
                'Service account JSON file is invalid for GCE. '
                'client_email key is expected. See getting started '
                'docs for information on GCE configuration.')

        self.service_account_project = info.get('project_id')
        if not self.service_account_project:
            raise GCECloudException(
                'Service account JSON file is invalid for GCE. '
                'project_id key is expected. See getting started '
                'docs for information on GCE configuration.')

        return service_account.Credentials.from_service_account_file(
            self.service_account_file)
Пример #6
0
    def _set_instance_ip(self):
        """Retrieve and set the instance ip address."""
        instance = self._get_instance()

        interface = instance['networkInterfaces'][0]
        try:
            self.instance_ip = interface['accessConfigs'][0]['natIP']
        except (KeyError, IndexError):
            try:
                self.instance_ip = interface['networkIP']
            except KeyError:
                raise GCECloudException(
                    'IP address for instance: %s cannot be found.' %
                    self.running_instance_id)
Пример #7
0
    def _launch_instance(self):
        """Launch an instance of the given image."""
        self.running_instance_id = self._generate_instance_name()
        self.logger.debug('ID of instance: %s' % self.running_instance_id)

        machine_type = self._get_instance_type(
            self.instance_type or GCE_DEFAULT_TYPE
        )['selfLink']
        source_image = self._get_image(self.image_id)['selfLink']
        network_interfaces = [
            self._get_network_config(self.subnet_id, self.use_gvnic)
        ]

        kwargs = {
            'instance_name': self.running_instance_id,
            'machine_type': machine_type,
            'service_account_email': self.service_account_email,
            'source_image': source_image,
            'ssh_key': self.ssh_public_key,
            'network_interfaces': network_interfaces,
            'sev_capable': self.sev_capable,
            'use_gvnic': self.use_gvnic,
        }

        if self.enable_uefi:
            kwargs['shielded_instance_config'] = \
                self.get_shielded_instance_config(
                    enable_secure_boot=self.enable_secure_boot
                )

        try:
            response = self.compute_driver.instances().insert(
                project=self.service_account_project,
                zone=self.region,
                body=self.get_instance_config(**kwargs)
            ).execute()
        except HttpError as error:
            with suppress(AttributeError):
                # In python 3.5 content is bytes
                error.content = error.content.decode()

            error_obj = json.loads(error.content)['error']

            try:
                message = error_obj['message']
            except (AttributeError, KeyError):
                message = 'Unknown exception.'

            if error_obj['code'] == 412:
                # 412 is conditionNotmet
                error_class = IpaRetryableError
            else:
                error_class = GCECloudException

            raise error_class(
                'Failed to launch instance: {message}'.format(
                    message=message
                )
            ) from error
        except Exception as error:
            raise GCECloudException(
                'Failed to launch instance: {message}'.format(
                    message=str(error)
                )
            ) from error

        operation = self._wait_on_operation(response['name'])

        if 'error' in operation and operation['error'].get('errors'):
            error = operation['error']['errors'][0]

            if error['code'] in ('QUOTA_EXCEEDED', 'PRECONDITION_FAILED'):
                error_class = IpaRetryableError
            else:
                error_class = GCECloudException

            raise error_class(
                'Failed to launch instance: {message}'.format(
                    message=error['message']
                )
            )

        self._wait_on_instance(
            'RUNNING',
            timeout=self.timeout
        )