예제 #1
0
    def take_action(self, parsed_args):
        compute_client = self.app.client_manager.sdk_connection.compute
        identity_client = self.app.client_manager.identity

        if parsed_args.project:
            if not sdk_utils.supports_microversion(compute_client, '2.10'):
                msg = _(
                    '--os-compute-api-version 2.10 or greater is required to '
                    'support the --project option')
                raise exceptions.CommandError(msg)

            # NOTE(stephenfin): This is done client side because nova doesn't
            # currently support doing so server-side. If this is slow, we can
            # think about spinning up a threadpool or similar.
            project = identity_common.find_project(
                identity_client,
                parsed_args.project,
                parsed_args.project_domain,
            ).id
            users = identity_client.users.list(tenant_id=project)

            data = []
            for user in users:
                data.extend(compute_client.keypairs(user_id=user.id))
        elif parsed_args.user:
            if not sdk_utils.supports_microversion(compute_client, '2.10'):
                msg = _(
                    '--os-compute-api-version 2.10 or greater is required to '
                    'support the --user option')
                raise exceptions.CommandError(msg)

            user = identity_common.find_user(
                identity_client,
                parsed_args.user,
                parsed_args.user_domain,
            )

            data = compute_client.keypairs(user_id=user.id)
        else:
            data = compute_client.keypairs()

        columns = ("Name", "Fingerprint")

        if sdk_utils.supports_microversion(compute_client, '2.2'):
            columns += ("Type", )

        return (
            columns,
            (utils.get_item_properties(s, columns) for s in data),
        )
예제 #2
0
    def take_action(self, parsed_args):
        compute_client = self.app.client_manager.sdk_connection.compute
        columns = (
            "id",
            "binary",
            "host",
            "availability_zone",
            "status",
            "state",
            "updated_at",
        )
        column_headers = (
            "ID",
            "Binary",
            "Host",
            "Zone",
            "Status",
            "State",
            "Updated At",
        )
        if parsed_args.long:
            columns += ("disabled_reason", )
            column_headers += ("Disabled Reason", )
            if sdk_utils.supports_microversion(compute_client, '2.11'):
                columns += ("is_forced_down", )
                column_headers += ("Forced Down", )

        data = compute_client.services(host=parsed_args.host,
                                       binary=parsed_args.service)
        return (column_headers, (utils.get_item_properties(s, columns)
                                 for s in data))
예제 #3
0
    def take_action(self, parsed_args):
        compute_client = self.app.client_manager.sdk_connection.compute
        identity_client = self.app.client_manager.identity

        kwargs = {}

        if parsed_args.user:
            if not sdk_utils.supports_microversion(compute_client, '2.10'):
                msg = _(
                    '--os-compute-api-version 2.10 or greater is required to '
                    'support the --user option')
                raise exceptions.CommandError(msg)

            kwargs['user_id'] = identity_common.find_user(
                identity_client,
                parsed_args.user,
                parsed_args.user_domain,
            ).id

        keypair = compute_client.find_keypair(parsed_args.name,
                                              **kwargs,
                                              ignore_missing=False)

        if not parsed_args.public_key:
            display_columns, columns = _get_keypair_columns(keypair,
                                                            hide_pub_key=True)
            data = utils.get_item_properties(keypair, columns)
            return (display_columns, data)
        else:
            sys.stdout.write(keypair.public_key)
            return ({}, {})
예제 #4
0
    def _get_microversion_for(self, session, action):
        """Get microversion to use for the given action.

        The base version uses :meth:`_get_microversion_for_list`.
        Subclasses can override this method if more complex logic is needed.

        :param session: :class`keystoneauth1.adapter.Adapter`
        :param action: One of "fetch", "commit", "create", "delete", "patch".
            Unused in the base implementation.
        :return: microversion as string or ``None``
        """
        if action not in ('fetch', 'commit', 'create', 'delete', 'patch'):
            raise ValueError('Invalid action: %s' % action)

        microversion = self._get_microversion_for_list(session)
        if action == 'create':
            # `policy` and `rules` are added with mv=2.64. In it also
            # `policies` are removed.
            if utils.supports_microversion(session, '2.64'):
                if self.policies:
                    if not self.policy and isinstance(self.policies, list):
                        self.policy = self.policies[0]
                    self._body.clean(only={'policies'})
                microversion = self._max_microversion
            else:
                if self.rules:
                    message = ("API version %s is required to set rules, but "
                               "it is not available.") % 2.64
                    raise exceptions.NotSupported(message)
                if self.policy:
                    if not self.policies:
                        self.policies = [self.policy]
                    self._body.clean(only={'policy'})

        return microversion
예제 #5
0
    def take_action(self, parsed_args):
        compute_client = self.app.client_manager.sdk_connection.compute
        identity_client = self.app.client_manager.identity

        try:
            flavor = compute_client.find_flavor(parsed_args.flavor,
                                                get_extra_specs=True,
                                                ignore_missing=False)
        except sdk_exceptions.ResourceNotFound as e:
            raise exceptions.CommandError(e.message)

        if parsed_args.description:
            if not sdk_utils.supports_microversion(compute_client, '2.55'):
                msg = _(
                    'The --description parameter requires server support for '
                    'API microversion 2.55')
                raise exceptions.CommandError(msg)

            compute_client.update_flavor(flavor=flavor.id,
                                         description=parsed_args.description)

        result = 0
        if parsed_args.no_property:
            try:
                for key in flavor.extra_specs.keys():
                    compute_client.delete_flavor_extra_specs_property(
                        flavor.id, key)
            except Exception as e:
                LOG.error(_("Failed to clear flavor properties: %s"), e)
                result += 1

        if parsed_args.properties:
            try:
                compute_client.create_flavor_extra_specs(
                    flavor.id, parsed_args.properties)
            except Exception as e:
                LOG.error(_("Failed to set flavor properties: %s"), e)
                result += 1

        if parsed_args.project:
            try:
                if flavor.is_public:
                    msg = _("Cannot set access for a public flavor")
                    raise exceptions.CommandError(msg)
                else:
                    project_id = identity_common.find_project(
                        identity_client,
                        parsed_args.project,
                        parsed_args.project_domain,
                    ).id
                    compute_client.flavor_add_tenant_access(
                        flavor.id, project_id)
            except Exception as e:
                LOG.error(_("Failed to set flavor access to project: %s"), e)
                result += 1

        if result > 0:
            raise exceptions.CommandError(
                _("Command Failed: One or more of"
                  " the operations failed"))
예제 #6
0
 def live_migrate(self, session, host, force, block_migration):
     if utils.supports_microversion(session, '2.30'):
         return self._live_migrate_30(session,
                                      host,
                                      force=force,
                                      block_migration=block_migration)
     elif utils.supports_microversion(session, '2.25'):
         return self._live_migrate_25(session,
                                      host,
                                      force=force,
                                      block_migration=block_migration)
     else:
         return self._live_migrate(session,
                                   host,
                                   force=force,
                                   block_migration=block_migration)
예제 #7
0
 def live_migrate(self, session, host, force, block_migration,
                  disk_over_commit=False):
     if utils.supports_microversion(session, '2.30'):
         return self._live_migrate_30(
             session, host,
             force=force,
             block_migration=block_migration)
     elif utils.supports_microversion(session, '2.25'):
         return self._live_migrate_25(
             session, host,
             force=force,
             block_migration=block_migration)
     else:
         return self._live_migrate(
             session, host,
             force=force,
             block_migration=block_migration,
             disk_over_commit=disk_over_commit)
예제 #8
0
    def take_action(self, parsed_args):
        compute_client = self.app.client_manager.sdk_connection.compute
        identity_client = self.app.client_manager.identity

        if parsed_args.project and parsed_args.public:
            msg = _("--project is only allowed with --private")
            raise exceptions.CommandError(msg)

        args = {
            'name': parsed_args.name,
            'ram': parsed_args.ram,
            'vcpus': parsed_args.vcpus,
            'disk': parsed_args.disk,
            'id': parsed_args.id,
            'ephemeral': parsed_args.ephemeral,
            'swap': parsed_args.swap,
            'rxtx_factor': parsed_args.rxtx_factor,
            'is_public': parsed_args.public,
        }

        if parsed_args.description:
            if not sdk_utils.supports_microversion(compute_client, '2.55'):
                msg = _(
                    'The --description parameter requires server support for '
                    'API microversion 2.55')
                raise exceptions.CommandError(msg)

            args['description'] = parsed_args.description

        flavor = compute_client.create_flavor(**args)

        if parsed_args.project:
            try:
                project_id = identity_common.find_project(
                    identity_client,
                    parsed_args.project,
                    parsed_args.project_domain,
                ).id
                compute_client.flavor_add_tenant_access(flavor.id, project_id)
            except Exception as e:
                msg = _("Failed to add project %(project)s access to "
                        "flavor: %(e)s")
                LOG.error(msg, {'project': parsed_args.project, 'e': e})
        if parsed_args.properties:
            try:
                flavor = compute_client.create_flavor_extra_specs(
                    flavor, parsed_args.properties)
            except Exception as e:
                LOG.error(_("Failed to set flavor properties: %s"), e)

        display_columns, columns = _get_flavor_columns(flavor)
        data = utils.get_dict_properties(flavor,
                                         columns,
                                         formatters=_formatters)

        return (display_columns, data)
 def create(self, session, prepend_key=True, base_path=None, **params):
     if not self.protocol:
         self.protocol = \
             CONSOLE_TYPE_PROTOCOL_MAPPING.get(self.type)
     if (not utils.supports_microversion(session, '2.8')
             and self.type == 'webmks'):
         raise ValueError('Console type webmks is not supported on '
                          'server side')
     return super(ServerRemoteConsole, self).create(session,
                                                    prepend_key=prepend_key,
                                                    base_path=base_path,
                                                    **params)
예제 #10
0
    def get_uptime(self, session):
        """Get uptime information for the hypervisor

        Updates uptime attribute of the hypervisor object
        """
        warnings.warn(
            "This call is deprecated and is only available until Nova 2.88")
        if utils.supports_microversion(session, '2.88'):
            raise exceptions.SDKException(
                'Hypervisor.get_uptime is not supported anymore')
        url = utils.urljoin(self.base_path, self.id, 'uptime')
        microversion = self._get_microversion_for(session, 'fetch')
        response = session.get(
            url, microversion=microversion)
        self._translate_response(response)
        return self
예제 #11
0
    def take_action(self, parsed_args):
        compute_client = self.app.client_manager.sdk_connection.compute
        identity_client = self.app.client_manager.identity

        kwargs = {}
        result = 0

        if parsed_args.user:
            if not sdk_utils.supports_microversion(compute_client, '2.10'):
                msg = _(
                    '--os-compute-api-version 2.10 or greater is required to '
                    'support the --user option')
                raise exceptions.CommandError(msg)

            kwargs['user_id'] = identity_common.find_user(
                identity_client,
                parsed_args.user,
                parsed_args.user_domain,
            ).id

        for n in parsed_args.name:
            try:
                compute_client.delete_keypair(n,
                                              **kwargs,
                                              ignore_missing=False)
            except Exception as e:
                result += 1
                LOG.error(
                    _("Failed to delete key with name "
                      "'%(name)s': %(e)s"), {
                          'name': n,
                          'e': e
                      })

        if result > 0:
            total = len(parsed_args.name)
            msg = (_("%(result)s of %(total)s keys failed "
                     "to delete.") % {
                         'result': result,
                         'total': total
                     })
            raise exceptions.CommandError(msg)
예제 #12
0
    def create_image(self, session, name, metadata=None):
        """Create image from server."""
        action = {'name': name}
        if metadata is not None:
            action['metadata'] = metadata
        body = {'createImage': action}

        # You won't believe it - wait, who am I kidding - of course you will!
        # Nova returns the URL of the image created in the Location
        # header of the response. (what?) But, even better, the URL it responds
        # with has a very good chance of being wrong (it is built from
        # nova.conf values that point to internal API servers in any cloud
        # large enough to have both public and internal endpoints.
        # However, nobody has ever noticed this because novaclient doesn't
        # actually use that URL - it extracts the id from the end of
        # the url, then returns the id. This leads us to question:
        #   a) why Nova is going to return a value in a header
        #   b) why it's going to return data that probably broken
        #   c) indeed the very nature of the fabric of reality
        # Although it fills us with existential dread, we have no choice but
        # to follow suit like a lemming being forced over a cliff by evil
        # producers from Disney.
        microversion = None
        if utils.supports_microversion(session, '2.45'):
            microversion = '2.45'
        response = self._action(session, body, microversion)

        body = None
        try:
            # There might be body, might be not
            body = response.json()
        except Exception:
            pass
        if body and 'image_id' in body:
            image_id = body['image_id']
        else:
            image_id = response.headers['Location'].rsplit('/', 1)[1]

        return image_id
예제 #13
0
    def set_forced_down(
        self, session, host=None, binary=None, forced=False
    ):
        """Update forced_down information of a service."""
        microversion = session.default_microversion
        body = {}
        if not host:
            host = self.host
        if not binary:
            binary = self.binary
        body = {
            'host': host,
            'binary': binary,
        }
        if utils.supports_microversion(session, '2.11'):
            body['forced_down'] = forced
            # Using forced_down works only 2.11-2.52, therefore pin it
            microversion = '2.11'

        # This will not work with newest microversions
        return self._action(
            session, 'force-down', body,
            microversion=microversion)
예제 #14
0
    def take_action(self, parsed_args):
        compute_client = self.app.client_manager.sdk_connection.compute

        if (parsed_args.enable or not parsed_args.disable) and \
                parsed_args.disable_reason:
            msg = _("Cannot specify option --disable-reason without "
                    "--disable specified.")
            raise exceptions.CommandError(msg)

        # Starting with microversion 2.53, there is a single
        # PUT /os-services/{service_id} API for updating nova-compute
        # services. If 2.53+ is used we need to find the nova-compute
        # service using the --host and --service (binary) values.
        requires_service_id = (sdk_utils.supports_microversion(
            compute_client, '2.53'))
        service_id = None
        if requires_service_id:
            # TODO(mriedem): Add an --id option so users can pass the service
            # id (as a uuid) directly rather than make us look it up using
            # host/binary.
            service_id = SetService._find_service_by_host_and_binary(
                compute_client, parsed_args.host, parsed_args.service).id

        result = 0
        enabled = None
        try:
            if parsed_args.enable:
                enabled = True
            if parsed_args.disable:
                enabled = False

            if enabled is not None:
                if enabled:
                    compute_client.enable_service(service_id, parsed_args.host,
                                                  parsed_args.service)
                else:
                    compute_client.disable_service(service_id,
                                                   parsed_args.host,
                                                   parsed_args.service,
                                                   parsed_args.disable_reason)
        except Exception:
            status = "enabled" if enabled else "disabled"
            LOG.error("Failed to set service status to %s", status)
            result += 1

        force_down = None
        if parsed_args.down:
            force_down = True
        if parsed_args.up:
            force_down = False
        if force_down is not None:
            if not sdk_utils.supports_microversion(compute_client, '2.11'):
                msg = _('--os-compute-api-version 2.11 or later is '
                        'required')
                raise exceptions.CommandError(msg)
            try:
                compute_client.update_service_forced_down(
                    service_id, parsed_args.host, parsed_args.service,
                    force_down)
            except Exception:
                state = "down" if force_down else "up"
                LOG.error("Failed to set service state to %s", state)
                result += 1

        if result > 0:
            msg = _("Compute service %(service)s of host %(host)s failed to "
                    "set.") % {
                        "service": parsed_args.service,
                        "host": parsed_args.host
                    }
            raise exceptions.CommandError(msg)
예제 #15
0
    def take_action(self, parsed_args):
        compute_client = self.app.client_manager.sdk_connection.compute
        identity_client = self.app.client_manager.identity

        kwargs = {'name': parsed_args.name}

        public_key = parsed_args.public_key
        if public_key:
            try:
                with io.open(os.path.expanduser(parsed_args.public_key)) as p:
                    public_key = p.read()
            except IOError as e:
                msg = _("Key file %(public_key)s not found: %(exception)s")
                raise exceptions.CommandError(msg % {
                    "public_key": parsed_args.public_key,
                    "exception": e
                })

            kwargs['public_key'] = public_key

        if parsed_args.type:
            if not sdk_utils.supports_microversion(compute_client, '2.2'):
                msg = _(
                    '--os-compute-api-version 2.2 or greater is required to '
                    'support the --type option')
                raise exceptions.CommandError(msg)

            kwargs['key_type'] = parsed_args.type

        if parsed_args.user:
            if not sdk_utils.supports_microversion(compute_client, '2.10'):
                msg = _(
                    '--os-compute-api-version 2.10 or greater is required to '
                    'support the --user option')
                raise exceptions.CommandError(msg)

            kwargs['user_id'] = identity_common.find_user(
                identity_client,
                parsed_args.user,
                parsed_args.user_domain,
            ).id

        keypair = compute_client.create_keypair(**kwargs)

        private_key = parsed_args.private_key
        # Save private key into specified file
        if private_key:
            try:
                with io.open(os.path.expanduser(parsed_args.private_key),
                             'w+') as p:
                    p.write(keypair.private_key)
            except IOError as e:
                msg = _("Key file %(private_key)s can not be saved: "
                        "%(exception)s")
                raise exceptions.CommandError(msg % {
                    "private_key": parsed_args.private_key,
                    "exception": e
                })
        # NOTE(dtroyer): how do we want to handle the display of the private
        #                key when it needs to be communicated back to the user
        #                For now, duplicate nova keypair-add command output
        if public_key or private_key:
            display_columns, columns = _get_keypair_columns(keypair,
                                                            hide_pub_key=True,
                                                            hide_priv_key=True)
            data = utils.get_item_properties(keypair, columns)

            return (display_columns, data)
        else:
            sys.stdout.write(keypair.private_key)
            return ({}, {})
예제 #16
0
    def take_action(self, parsed_args):
        compute_client = self.app.client_manager.sdk_connection.compute
        identity_client = self.app.client_manager.identity

        kwargs = {}

        if parsed_args.marker:
            if not sdk_utils.supports_microversion(compute_client, '2.35'):
                msg = _('--os-compute-api-version 2.35 or greater is required '
                        'to support the --marker option')
                raise exceptions.CommandError(msg)

            kwargs['marker'] = parsed_args.marker

        if parsed_args.limit:
            if not sdk_utils.supports_microversion(compute_client, '2.35'):
                msg = _('--os-compute-api-version 2.35 or greater is required '
                        'to support the --limit option')
                raise exceptions.CommandError(msg)

            kwargs['limit'] = parsed_args.limit

        if parsed_args.project:
            if not sdk_utils.supports_microversion(compute_client, '2.10'):
                msg = _(
                    '--os-compute-api-version 2.10 or greater is required to '
                    'support the --project option')
                raise exceptions.CommandError(msg)

            if parsed_args.marker:
                # NOTE(stephenfin): Because we're doing this client-side, we
                # can't really rely on the marker, because we don't know what
                # user the marker is associated with
                msg = _('--project is not compatible with --marker')

            # NOTE(stephenfin): This is done client side because nova doesn't
            # currently support doing so server-side. If this is slow, we can
            # think about spinning up a threadpool or similar.
            project = identity_common.find_project(
                identity_client,
                parsed_args.project,
                parsed_args.project_domain,
            ).id
            users = identity_client.users.list(tenant_id=project)

            data = []
            for user in users:
                kwargs['user_id'] = user.id
                data.extend(compute_client.keypairs(**kwargs))
        elif parsed_args.user:
            if not sdk_utils.supports_microversion(compute_client, '2.10'):
                msg = _(
                    '--os-compute-api-version 2.10 or greater is required to '
                    'support the --user option')
                raise exceptions.CommandError(msg)

            user = identity_common.find_user(
                identity_client,
                parsed_args.user,
                parsed_args.user_domain,
            )
            kwargs['user_id'] = user.id

            data = compute_client.keypairs(**kwargs)
        else:
            data = compute_client.keypairs(**kwargs)

        columns = ("Name", "Fingerprint")

        if sdk_utils.supports_microversion(compute_client, '2.2'):
            columns += ("Type", )

        return (
            columns,
            (utils.get_item_properties(s, columns) for s in data),
        )
예제 #17
0
 def test_requested_not_supported_no_default(self):
     self.adapter.default_microversion = None
     self.assertFalse(utils.supports_microversion(self.adapter, '2.2'))
예제 #18
0
 def test_requested_supported_equal_default(self):
     self.adapter.default_microversion = '1.8'
     self.assertTrue(utils.supports_microversion(self.adapter, '1.8'))
예제 #19
0
 def test_requested_supported_lower_default(self):
     self.adapter.default_microversion = '1.2'
     self.assertFalse(utils.supports_microversion(self.adapter, '1.8'))