def create(self, req, body):
        """Creates an aggregate, given its name and
        optional availability zone.
        """
        context = _get_context(req)
        authorize(context, action="create")
        host_aggregate = body["aggregate"]
        name = common.normalize_name(host_aggregate["name"])
        avail_zone = host_aggregate.get("availability_zone")
        if avail_zone:
            avail_zone = common.normalize_name(avail_zone)

        try:
            aggregate = self.api.create_aggregate(context, name, avail_zone)
        except exception.AggregateNameExists as e:
            raise exc.HTTPConflict(explanation=e.format_message())
        except exception.InvalidAggregateAction as e:
            raise exc.HTTPBadRequest(explanation=e.format_message())

        agg = self._marshall_aggregate(aggregate)

        # To maintain the same API result as before the changes for returning
        # nova objects were made.
        del agg["aggregate"]["hosts"]
        del agg["aggregate"]["metadata"]

        return agg
Example #2
0
    def create(self, req, body):
        """Creates an aggregate, given its name and
        optional availability zone.
        """
        context = _get_context(req)
        context.can(aggr_policies.POLICY_ROOT % 'create')
        host_aggregate = body["aggregate"]
        name = common.normalize_name(host_aggregate["name"])
        avail_zone = host_aggregate.get("availability_zone")
        if avail_zone:
            avail_zone = common.normalize_name(avail_zone)

        try:
            aggregate = self.api.create_aggregate(context, name, avail_zone)
        except exception.AggregateNameExists as e:
            raise exc.HTTPConflict(explanation=e.format_message())
        except exception.ObjectActionError:
            raise exc.HTTPConflict(explanation=_(
                'Not all aggregates have been migrated to the API database'))
        except exception.InvalidAggregateAction as e:
            raise exc.HTTPBadRequest(explanation=e.format_message())

        agg = self._marshall_aggregate(req, aggregate)

        # To maintain the same API result as before the changes for returning
        # nova objects were made.
        del agg['aggregate']['hosts']
        del agg['aggregate']['metadata']

        return agg
    def create(self, req, body):
        """Creates an aggregate, given its name and
        optional availability zone.
        """
        context = _get_context(req)
        context.can(aggr_policies.POLICY_ROOT % 'create')
        host_aggregate = body["aggregate"]
        name = common.normalize_name(host_aggregate["name"])
        avail_zone = host_aggregate.get("availability_zone")
        if avail_zone:
            avail_zone = common.normalize_name(avail_zone)

        try:
            aggregate = self.api.create_aggregate(context, name, avail_zone)
        except exception.AggregateNameExists as e:
            raise exc.HTTPConflict(explanation=e.format_message())
        except exception.ObjectActionError:
            raise exc.HTTPConflict(explanation=_(
                'Not all aggregates have been migrated to the API database'))
        except exception.InvalidAggregateAction as e:
            raise exc.HTTPBadRequest(explanation=e.format_message())

        agg = self._marshall_aggregate(req, aggregate)

        # To maintain the same API result as before the changes for returning
        # nova objects were made.
        del agg['aggregate']['hosts']
        del agg['aggregate']['metadata']

        return agg
Example #4
0
    def _create_backup(self, req, id, body):
        """Backup a server instance.

        Images now have an `image_type` associated with them, which can be
        'snapshot' or the backup type, like 'daily' or 'weekly'.

        If the image_type is backup-like, then the rotation factor can be
        included and that will cause the oldest backups that exceed the
        rotation factor to be deleted.

        """
        context = req.environ["nova.context"]
        context.can(cb_policies.BASE_POLICY_NAME)
        entity = body["createBackup"]

        image_name = common.normalize_name(entity["name"])
        backup_type = entity["backup_type"]
        rotation = int(entity["rotation"])

        props = {}
        metadata = entity.get('metadata', {})
        # Starting from microversion 2.39 we don't check quotas on createBackup
        if api_version_request.is_supported(req,
                                            max_version=api_version_request.
                                            MAX_IMAGE_META_PROXY_API_VERSION):
            common.check_img_metadata_properties_quota(context, metadata)
        props.update(metadata)

        instance = common.get_instance(self.compute_api, context, id)

        try:
            image = self.compute_api.backup(context,
                                            instance,
                                            image_name,
                                            backup_type,
                                            rotation,
                                            extra_properties=props)
        except exception.InstanceUnknownCell as e:
            raise webob.exc.HTTPNotFound(explanation=e.format_message())
        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(
                state_error, 'createBackup', id)
        except exception.InvalidRequest as e:
            raise webob.exc.HTTPBadRequest(explanation=e.format_message())

        # Starting with microversion 2.45 we return a response body containing
        # the snapshot image id without the Location header.
        if api_version_request.is_supported(req, '2.45'):
            return {'image_id': image['id']}

        resp = webob.Response(status_int=202)

        # build location of newly-created image entity if rotation is not zero
        if rotation > 0:
            image_id = str(image['id'])
            image_ref = common.url_join(req.application_url, 'images',
                                        image_id)
            resp.headers['Location'] = image_ref

        return resp
Example #5
0
    def update(self, req, id, body):
        """Update server then pass on to version-specific controller."""

        ctxt = req.environ['nova.context']
        update_dict = {}
        ctxt.can(server_policies.SERVERS % 'update')

        server = body['server']

        if 'name' in server:
            update_dict['display_name'] = common.normalize_name(
                server['name'])

        if 'description' in server:
            # This is allowed to be None (remove description)
            update_dict['display_description'] = server['description']

        helpers.translate_attributes(helpers.UPDATE, server, update_dict)

        instance = self._get_server(ctxt, req, id, is_detail=True)
        try:
            # NOTE(mikal): this try block needs to stay because save() still
            # might throw an exception.
            instance.update(update_dict)
            instance.save()
            return self._view_builder.show(req, instance,
                                           extend_address=False)
        except exception.InstanceNotFound:
            msg = _("Instance could not be found")
            raise exc.HTTPNotFound(explanation=msg)
Example #6
0
    def _create(self, req, body, user_id=None, **keypair_filters):
        context = req.environ['nova.context']
        params = body['keypair']
        name = common.normalize_name(params['name'])
        key_type = params.get('type', keypair_obj.KEYPAIR_TYPE_SSH)
        user_id = user_id or context.user_id
        context.can(kp_policies.POLICY_ROOT % 'create',
                    target={'user_id': user_id,
                            'project_id': context.project_id})

        try:
            if 'public_key' in params:
                keypair = self.api.import_key_pair(context,
                                              user_id, name,
                                              params['public_key'], key_type)
                keypair = self._filter_keypair(keypair, user_id=True,
                                               **keypair_filters)
            else:
                keypair, private_key = self.api.create_key_pair(
                    context, user_id, name, key_type)
                keypair = self._filter_keypair(keypair, user_id=True,
                                               **keypair_filters)
                keypair['private_key'] = private_key

            return {'keypair': keypair}

        except exception.KeypairLimitExceeded:
            msg = _("Quota exceeded, too many key pairs.")
            raise webob.exc.HTTPForbidden(explanation=msg)
        except exception.InvalidKeypair as exc:
            raise webob.exc.HTTPBadRequest(explanation=exc.format_message())
        except exception.KeyPairExists as exc:
            raise webob.exc.HTTPConflict(explanation=exc.format_message())
Example #7
0
    def _create_backup(self, req, id, body):
        """Backup a server instance.

        Images now have an `image_type` associated with them, which can be
        'snapshot' or the backup type, like 'daily' or 'weekly'.

        If the image_type is backup-like, then the rotation factor can be
        included and that will cause the oldest backups that exceed the
        rotation factor to be deleted.

        """
        context = req.environ["nova.context"]
        context.can(cb_policies.BASE_POLICY_NAME)
        entity = body["createBackup"]

        image_name = common.normalize_name(entity["name"])
        backup_type = entity["backup_type"]
        rotation = int(entity["rotation"])

        props = {}
        metadata = entity.get('metadata', {})
        # Starting from microversion 2.39 we don't check quotas on createBackup
        if api_version_request.is_supported(
                req, max_version=
                api_version_request.MAX_IMAGE_META_PROXY_API_VERSION):
            common.check_img_metadata_properties_quota(context, metadata)
        props.update(metadata)

        instance = common.get_instance(self.compute_api, context, id)

        try:
            image = self.compute_api.backup(context, instance, image_name,
                    backup_type, rotation, extra_properties=props)
        except exception.InstanceUnknownCell as e:
            raise webob.exc.HTTPNotFound(explanation=e.format_message())
        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(state_error,
                    'createBackup', id)
        except exception.InvalidRequest as e:
            raise webob.exc.HTTPBadRequest(explanation=e.format_message())

        # Starting with microversion 2.45 we return a response body containing
        # the snapshot image id without the Location header.
        if api_version_request.is_supported(req, '2.45'):
            return {'image_id': image['id']}

        resp = webob.Response(status_int=202)

        # build location of newly-created image entity if rotation is not zero
        if rotation > 0:
            image_id = str(image['id'])
            image_ref = common.url_join(req.application_url, 'images',
                                        image_id)
            resp.headers['Location'] = image_ref

        return resp
Example #8
0
    def create(self, req, id, body):
        """Create memory snapshots for a server instance.
        """

        context = req.environ["nova.context"]
        context.can(ms_policies.BASE_POLICY_NAME)

        instance = common.get_instance(self.compute_api, context, id)

        #check if instance is active
        if instance.vm_state != vm_states.ACTIVE:
            resp = {
                'err_status': 'error',
                'err_msg': 'The instance should be active.'
            }

            return resp

        #paramter process
        snapshot_name = common.normalize_name(body["snapshot_name"])
        description = body['description'] if body.get('description') else None
        memory = True

        #set instance task_state with IMAGE_BACKUP
        instance.task_state = task_states.MEMORY_SNAPSHOTS
        instance.save(expected_task_state=[None])

        try:
            # call ics sdk
            LOG.info('Start create memory snapshot')
            #ics_resp = self.ics_manager.create_mem_snapshots(id, snapshot_name, description, memory)
            time.sleep(30)
            #raise Exception('call ics sdk error')
        except Exception as e:
            resp = {'err_status': 'error', 'err_msg': e.message}

            # reset instance state
            instance.task_state = None
            instance.save(expected_task_state=task_states.MEMORY_SNAPSHOTS)

            # return result
            return resp

        #reset instance state
        instance.task_state = None
        instance.save(expected_task_state=task_states.MEMORY_SNAPSHOTS)

        #return result
        resp = {
            'err_status': 'ok',
            'result': {
                'snapshot_id': 'xxxxxx-yyyyyy-zzzzzz'
            }
        }

        return resp
Example #9
0
    def _create_backup(self, req, id, body):
        """Backup a server instance.

        Images now have an `image_type` associated with them, which can be
        'snapshot' or the backup type, like 'daily' or 'weekly'.

        If the image_type is backup-like, then the rotation factor can be
        included and that will cause the oldest backups that exceed the
        rotation factor to be deleted.

        """
        context = req.environ["nova.context"]
        authorize(context)
        entity = body["createBackup"]

        image_name = common.normalize_name(entity["name"])
        backup_type = entity["backup_type"]
        rotation = int(entity["rotation"])

        props = {}
        metadata = entity.get('metadata', {})
        common.check_img_metadata_properties_quota(context, metadata)
        props.update(metadata)

        instance = common.get_instance(self.compute_api, context, id)

        try:
            image = self.compute_api.backup(context,
                                            instance,
                                            image_name,
                                            backup_type,
                                            rotation,
                                            extra_properties=props)
        except exception.InstanceUnknownCell as e:
            raise webob.exc.HTTPNotFound(explanation=e.format_message())
        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(
                state_error, 'createBackup', id)
        except exception.InvalidRequest as e:
            raise webob.exc.HTTPBadRequest(explanation=e.format_message())

        resp = webob.Response(status_int=202)

        # build location of newly-created image entity if rotation is not zero
        if rotation > 0:
            image_id = str(image['id'])
            image_ref = common.url_join(req.application_url, 'images',
                                        image_id)
            resp.headers['Location'] = image_ref

        return resp
Example #10
0
    def _action_create_image(self, req, id, body):
        """Snapshot a server instance."""
        context = req.environ['nova.context']
        context.can(server_policies.SERVERS % 'create_image')

        entity = body["createImage"]
        image_name = common.normalize_name(entity["name"])
        metadata = entity.get('metadata', {})

        common.check_img_metadata_properties_quota(context, metadata)

        instance = self._get_server(context, req, id)

        bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
                    context, instance.uuid)

        try:
            if compute_utils.is_volume_backed_instance(context, instance,
                                                          bdms):
                context.can(server_policies.SERVERS %
                    'create_image:allow_volume_backed')
                image = self.compute_api.snapshot_volume_backed(
                                                       context,
                                                       instance,
                                                       image_name,
                                                       extra_properties=
                                                       metadata)
            else:
                image = self.compute_api.snapshot(context,
                                                  instance,
                                                  image_name,
                                                  extra_properties=metadata)
        except exception.InstanceUnknownCell as e:
            raise exc.HTTPNotFound(explanation=e.format_message())
        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(state_error,
                        'createImage', id)
        except exception.Invalid as err:
            raise exc.HTTPBadRequest(explanation=err.format_message())

        # build location of newly-created image entity
        image_id = str(image['id'])
        image_ref = glance.generate_image_url(image_id)

        resp = webob.Response(status_int=202)
        resp.headers['Location'] = image_ref
        return resp
Example #11
0
    def _create_backup(self, req, id, body):
        """Backup a server instance.

        Images now have an `image_type` associated with them, which can be
        'snapshot' or the backup type, like 'daily' or 'weekly'.

        If the image_type is backup-like, then the rotation factor can be
        included and that will cause the oldest backups that exceed the
        rotation factor to be deleted.

        """
        context = req.environ["nova.context"]
        authorize(context)
        entity = body["createBackup"]

        image_name = common.normalize_name(entity["name"])
        backup_type = entity["backup_type"]
        rotation = int(entity["rotation"])

        props = {}
        metadata = entity.get('metadata', {})
        common.check_img_metadata_properties_quota(context, metadata)
        props.update(metadata)

        instance = common.get_instance(self.compute_api, context, id)

        try:
            image = self.compute_api.backup(context, instance, image_name,
                    backup_type, rotation, extra_properties=props)
        except exception.InstanceUnknownCell as e:
            raise webob.exc.HTTPNotFound(explanation=e.format_message())
        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(state_error,
                    'createBackup', id)
        except exception.InvalidRequest as e:
            raise webob.exc.HTTPBadRequest(explanation=e.format_message())

        resp = webob.Response(status_int=202)

        # build location of newly-created image entity if rotation is not zero
        if rotation > 0:
            image_id = str(image['id'])
            image_ref = common.url_join(req.application_url, 'images',
                                        image_id)
            resp.headers['Location'] = image_ref

        return resp
Example #12
0
    def _normalize_cell(self, cell, existing=None):
        """Normalize input cell data.  Normalizations include:

        * Converting cell['type'] to is_parent boolean.
        * Merging existing transport URL with transport information.
        """

        if 'name' in cell:
            cell['name'] = common.normalize_name(cell['name'])

        # Start with the cell type conversion
        if 'type' in cell:
            cell['is_parent'] = cell['type'] == 'parent'
            del cell['type']
        # Avoid cell type being overwritten to 'child'
        elif existing:
            cell['is_parent'] = existing['is_parent']
        else:
            cell['is_parent'] = False

        # Now we disassemble the existing transport URL...
        transport_url = existing.get('transport_url') if existing else None
        transport_url = rpc.get_transport_url(transport_url)

        if 'rpc_virtual_host' in cell:
            transport_url.virtual_host = cell.pop('rpc_virtual_host')

        if not transport_url.hosts:
            transport_url.hosts.append(messaging.TransportHost())
        transport_host = transport_url.hosts[0]
        if 'rpc_port' in cell:
            cell['rpc_port'] = int(cell['rpc_port'])
        # Copy over the input fields
        transport_field_map = {
            'username': '******',
            'password': '******',
            'hostname': 'rpc_host',
            'port': 'rpc_port',
        }
        for key, input_field in transport_field_map.items():
            # Only override the value if we're given an override
            if input_field in cell:
                setattr(transport_host, key, cell.pop(input_field))

        # Now set the transport URL
        cell['transport_url'] = str(transport_url)
Example #13
0
    def _normalize_cell(self, cell, existing=None):
        """Normalize input cell data.  Normalizations include:

        * Converting cell['type'] to is_parent boolean.
        * Merging existing transport URL with transport information.
        """

        if 'name' in cell:
            cell['name'] = common.normalize_name(cell['name'])

        # Start with the cell type conversion
        if 'type' in cell:
            cell['is_parent'] = cell['type'] == 'parent'
            del cell['type']
        # Avoid cell type being overwritten to 'child'
        elif existing:
            cell['is_parent'] = existing['is_parent']
        else:
            cell['is_parent'] = False

        # Now we disassemble the existing transport URL...
        transport_url = existing.get('transport_url') if existing else None
        transport_url = rpc.get_transport_url(transport_url)

        if 'rpc_virtual_host' in cell:
            transport_url.virtual_host = cell.pop('rpc_virtual_host')

        if not transport_url.hosts:
            transport_url.hosts.append(messaging.TransportHost())
        transport_host = transport_url.hosts[0]
        if 'rpc_port' in cell:
            cell['rpc_port'] = int(cell['rpc_port'])
        # Copy over the input fields
        transport_field_map = {
            'username': '******',
            'password': '******',
            'hostname': 'rpc_host',
            'port': 'rpc_port',
        }
        for key, input_field in transport_field_map.items():
            # Only override the value if we're given an override
            if input_field in cell:
                setattr(transport_host, key, cell.pop(input_field))

        # Now set the transport URL
        cell['transport_url'] = str(transport_url)
    def update(self, req, id, body):
        """Updates the name and/or availability_zone of given aggregate."""
        context = _get_context(req)
        authorize(context, action="update")
        updates = body["aggregate"]
        if "name" in updates:
            updates["name"] = common.normalize_name(updates["name"])

        try:
            aggregate = self.api.update_aggregate(context, id, updates)
        except exception.AggregateNameExists as e:
            raise exc.HTTPConflict(explanation=e.format_message())
        except exception.AggregateNotFound as e:
            raise exc.HTTPNotFound(explanation=e.format_message())
        except exception.InvalidAggregateAction as e:
            raise exc.HTTPBadRequest(explanation=e.format_message())

        return self._marshall_aggregate(aggregate)
    def update(self, req, id, body):
        """Updates the name and/or availability_zone of given aggregate."""
        context = _get_context(req)
        context.can(aggr_policies.POLICY_ROOT % 'update')
        updates = body["aggregate"]
        if 'name' in updates:
            updates['name'] = common.normalize_name(updates['name'])

        try:
            aggregate = self.api.update_aggregate(context, id, updates)
        except exception.AggregateNameExists as e:
            raise exc.HTTPConflict(explanation=e.format_message())
        except exception.AggregateNotFound as e:
            raise exc.HTTPNotFound(explanation=e.format_message())
        except exception.InvalidAggregateAction as e:
            raise exc.HTTPBadRequest(explanation=e.format_message())

        return self._marshall_aggregate(req, aggregate)
Example #16
0
    def update(self, req, id, body):
        """Updates the name and/or availability_zone of given aggregate."""
        context = _get_context(req)
        context.can(aggr_policies.POLICY_ROOT % 'update')
        updates = body["aggregate"]
        if 'name' in updates:
            updates['name'] = common.normalize_name(updates['name'])

        try:
            aggregate = self.api.update_aggregate(context, id, updates)
        except exception.AggregateNameExists as e:
            raise exc.HTTPConflict(explanation=e.format_message())
        except exception.AggregateNotFound as e:
            raise exc.HTTPNotFound(explanation=e.format_message())
        except exception.InvalidAggregateAction as e:
            raise exc.HTTPBadRequest(explanation=e.format_message())

        return self._marshall_aggregate(req, aggregate)
Example #17
0
    def update(self, req, id, body):
        """Update server then pass on to version-specific controller."""

        ctxt = req.environ["nova.context"]
        update_dict = {}
        authorize(ctxt, action="update")

        if "name" in body["server"]:
            update_dict["display_name"] = common.normalize_name(body["server"]["name"])

        if list(self.update_extension_manager):
            self.update_extension_manager.map(self._update_extension_point, body["server"], update_dict)

        instance = self._get_server(ctxt, req, id, is_detail=True)
        try:
            # NOTE(mikal): this try block needs to stay because save() still
            # might throw an exception.
            instance.update(update_dict)
            instance.save()
            return self._view_builder.show(req, instance, extend_address=False)
        except exception.InstanceNotFound:
            msg = _("Instance could not be found")
            raise exc.HTTPNotFound(explanation=msg)
Example #18
0
    def create(self, req, body):
        """Creates a new server for a given user."""

        context = req.environ['nova.context']
        server_dict = body['server']
        password = self._get_server_admin_password(server_dict)
        name = common.normalize_name(server_dict['name'])

        if api_version_request.is_supported(req, min_version='2.19'):
            if 'description' in server_dict:
                # This is allowed to be None
                description = server_dict['description']
            else:
                # No default description
                description = None
        else:
            description = name

        # Arguments to be passed to instance create function
        create_kwargs = {}

        # Query extensions which want to manipulate the keyword
        # arguments.
        # NOTE(cyeoh): This is the hook that extensions use
        # to replace the extension specific code below.
        # When the extensions are ported this will also result
        # in some convenience function from this class being
        # moved to the extension
        if list(self.create_extension_manager):
            self.create_extension_manager.map(self._create_extension_point,
                                              server_dict, create_kwargs, body)

        availability_zone = create_kwargs.pop("availability_zone", None)

        helpers.translate_attributes(helpers.CREATE,
                                     server_dict, create_kwargs)

        target = {
            'project_id': context.project_id,
            'user_id': context.user_id,
            'availability_zone': availability_zone}
        context.can(server_policies.SERVERS % 'create', target)

        # TODO(Shao He, Feng) move this policy check to os-availability-zone
        # extension after refactor it.
        parse_az = self.compute_api.parse_availability_zone
        try:
            availability_zone, host, node = parse_az(context,
                                                     availability_zone)
        except exception.InvalidInput as err:
            raise exc.HTTPBadRequest(explanation=six.text_type(err))
        if host or node:
            context.can(server_policies.SERVERS % 'create:forced_host', {})

        block_device_mapping = create_kwargs.get("block_device_mapping")
        # TODO(Shao He, Feng) move this policy check to os-block-device-mapping
        # extension after refactor it.
        if block_device_mapping:
            context.can(server_policies.SERVERS % 'create:attach_volume',
                        target)

        image_uuid = self._image_from_req_data(server_dict, create_kwargs)

        # NOTE(cyeoh): Although an extension can set
        # return_reservation_id in order to request that a reservation
        # id be returned to the client instead of the newly created
        # instance information we do not want to pass this parameter
        # to the compute create call which always returns both. We use
        # this flag after the instance create call to determine what
        # to return to the client
        return_reservation_id = create_kwargs.pop('return_reservation_id',
                                                  False)

        requested_networks = None
        if ('os-networks' in self.extension_info.get_extensions()
                or utils.is_neutron()):
            requested_networks = server_dict.get('networks')

        if requested_networks is not None:
            requested_networks = self._get_requested_networks(
                requested_networks)

        if requested_networks and len(requested_networks):
            context.can(server_policies.SERVERS % 'create:attach_network',
                        target)

        try:
            flavor_id = self._flavor_id_from_req_data(body)
        except ValueError:
            msg = _("Invalid flavorRef provided.")
            raise exc.HTTPBadRequest(explanation=msg)

        try:
            inst_type = flavors.get_flavor_by_flavor_id(
                    flavor_id, ctxt=context, read_deleted="no")

            (instances, resv_id) = self.compute_api.create(context,
                            inst_type,
                            image_uuid,
                            display_name=name,
                            display_description=description,
                            availability_zone=availability_zone,
                            forced_host=host, forced_node=node,
                            metadata=server_dict.get('metadata', {}),
                            admin_password=password,
                            requested_networks=requested_networks,
                            check_server_group_quota=True,
                            **create_kwargs)
        except (exception.QuotaError,
                exception.PortLimitExceeded) as error:
            raise exc.HTTPForbidden(
                explanation=error.format_message())
        except exception.ImageNotFound:
            msg = _("Can not find requested image")
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.FlavorNotFound:
            msg = _("Invalid flavorRef provided.")
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.KeypairNotFound:
            msg = _("Invalid key_name provided.")
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.ConfigDriveInvalidValue:
            msg = _("Invalid config_drive provided.")
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.ExternalNetworkAttachForbidden as error:
            raise exc.HTTPForbidden(explanation=error.format_message())
        except messaging.RemoteError as err:
            msg = "%(err_type)s: %(err_msg)s" % {'err_type': err.exc_type,
                                                 'err_msg': err.value}
            raise exc.HTTPBadRequest(explanation=msg)
        except UnicodeDecodeError as error:
            msg = "UnicodeError: %s" % error
            raise exc.HTTPBadRequest(explanation=msg)
        except (exception.ImageNotActive,
                exception.ImageBadRequest,
                exception.FixedIpNotFoundForAddress,
                exception.FlavorDiskTooSmall,
                exception.FlavorMemoryTooSmall,
                exception.InvalidMetadata,
                exception.InvalidRequest,
                exception.InvalidVolume,
                exception.MultiplePortsNotApplicable,
                exception.InvalidFixedIpAndMaxCountRequest,
                exception.InstanceUserDataMalformed,
                exception.InstanceUserDataTooLarge,
                exception.PortNotFound,
                exception.FixedIpAlreadyInUse,
                exception.SecurityGroupNotFound,
                exception.PortRequiresFixedIP,
                exception.NetworkRequiresSubnet,
                exception.NetworkNotFound,
                exception.NetworkDuplicated,
                exception.InvalidBDM,
                exception.InvalidBDMSnapshot,
                exception.InvalidBDMVolume,
                exception.InvalidBDMImage,
                exception.InvalidBDMBootSequence,
                exception.InvalidBDMLocalsLimit,
                exception.InvalidBDMVolumeNotBootable,
                exception.InvalidBDMEphemeralSize,
                exception.InvalidBDMFormat,
                exception.InvalidBDMSwapSize,
                exception.AutoDiskConfigDisabledByImage,
                exception.ImageNUMATopologyIncomplete,
                exception.ImageNUMATopologyForbidden,
                exception.ImageNUMATopologyAsymmetric,
                exception.ImageNUMATopologyCPUOutOfRange,
                exception.ImageNUMATopologyCPUDuplicates,
                exception.ImageNUMATopologyCPUsUnassigned,
                exception.ImageNUMATopologyMemoryOutOfRange,
                exception.InstanceGroupNotFound,
                exception.PciRequestAliasNotDefined,
                exception.UnableToAutoAllocateNetwork) as error:
            raise exc.HTTPBadRequest(explanation=error.format_message())
        except (exception.PortInUse,
                exception.InstanceExists,
                exception.NetworkAmbiguous,
                exception.NoUniqueMatch) as error:
            raise exc.HTTPConflict(explanation=error.format_message())

        # If the caller wanted a reservation_id, return it
        if return_reservation_id:
            # NOTE(cyeoh): In v3 reservation_id was wrapped in
            # servers_reservation but this is reverted for V2 API
            # compatibility. In the long term with the tasks API we
            # will probably just drop the concept of reservation_id
            return wsgi.ResponseObject({'reservation_id': resv_id})

        req.cache_db_instances(instances)
        server = self._view_builder.create(req, instances[0])

        if CONF.enable_instance_password:
            server['server']['adminPass'] = password

        robj = wsgi.ResponseObject(server)

        return self._add_location(robj)
Example #19
0
    def _action_rebuild(self, req, id, body):
        """Rebuild an instance with the given attributes."""
        rebuild_dict = body['rebuild']

        image_href = rebuild_dict["imageRef"]
        image_href = common.image_uuid_from_href(image_href, 'imageRef')

        password = self._get_server_admin_password(rebuild_dict)

        context = req.environ['nova.context']
        context.can(server_policies.SERVERS % 'rebuild')
        instance = self._get_server(context, req, id)

        attr_map = {
            'name': 'display_name',
            'description': 'display_description',
            'metadata': 'metadata',
        }

        kwargs = {}

        helpers.translate_attributes(helpers.REBUILD, rebuild_dict, kwargs)

        for request_attribute, instance_attribute in attr_map.items():
            try:
                if request_attribute == 'name':
                    kwargs[instance_attribute] = common.normalize_name(
                        rebuild_dict[request_attribute])
                else:
                    kwargs[instance_attribute] = rebuild_dict[
                        request_attribute]
            except (KeyError, TypeError):
                pass

        try:
            self.compute_api.rebuild(context,
                                     instance,
                                     image_href,
                                     password,
                                     **kwargs)
        except exception.InstanceIsLocked as e:
            raise exc.HTTPConflict(explanation=e.format_message())
        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(state_error,
                    'rebuild', id)
        except exception.InstanceNotFound:
            msg = _("Instance could not be found")
            raise exc.HTTPNotFound(explanation=msg)
        except exception.InstanceUnknownCell as e:
            raise exc.HTTPNotFound(explanation=e.format_message())
        except exception.ImageNotFound:
            msg = _("Cannot find image for rebuild")
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.QuotaError as error:
            raise exc.HTTPForbidden(explanation=error.format_message())
        except (exception.ImageNotActive,
                exception.FlavorDiskTooSmall,
                exception.FlavorMemoryTooSmall,
                exception.InvalidMetadata,
                exception.AutoDiskConfigDisabledByImage) as error:
            raise exc.HTTPBadRequest(explanation=error.format_message())

        instance = self._get_server(context, req, id, is_detail=True)

        view = self._view_builder.show(req, instance, extend_address=False)

        # Add on the admin_password attribute since the view doesn't do it
        # unless instance passwords are disabled
        if CONF.enable_instance_password:
            view['server']['adminPass'] = password

        robj = wsgi.ResponseObject(view)
        return self._add_location(robj)
Example #20
0
    def create(self, req, body):
        """Creates a new server for a given user."""

        context = req.environ["nova.context"]
        server_dict = body["server"]
        password = self._get_server_admin_password(server_dict)
        name = common.normalize_name(server_dict["name"])

        # Arguments to be passed to instance create function
        create_kwargs = {}

        # Query extensions which want to manipulate the keyword
        # arguments.
        # NOTE(cyeoh): This is the hook that extensions use
        # to replace the extension specific code below.
        # When the extensions are ported this will also result
        # in some convenience function from this class being
        # moved to the extension
        if list(self.create_extension_manager):
            self.create_extension_manager.map(self._create_extension_point, server_dict, create_kwargs, body)

        availability_zone = create_kwargs.get("availability_zone")

        target = {"project_id": context.project_id, "user_id": context.user_id, "availability_zone": availability_zone}
        authorize(context, target, "create")

        # TODO(Shao He, Feng) move this policy check to os-availabilty-zone
        # extension after refactor it.
        if availability_zone:
            _dummy, host, node = self.compute_api._handle_availability_zone(context, availability_zone)
            if host or node:
                authorize(context, {}, "create:forced_host")

        block_device_mapping = create_kwargs.get("block_device_mapping")
        # TODO(Shao He, Feng) move this policy check to os-block-device-mapping
        # extension after refactor it.
        if block_device_mapping:
            authorize(context, target, "create:attach_volume")

        image_uuid = self._image_from_req_data(server_dict, create_kwargs)

        # NOTE(cyeoh): Although an extension can set
        # return_reservation_id in order to request that a reservation
        # id be returned to the client instead of the newly created
        # instance information we do not want to pass this parameter
        # to the compute create call which always returns both. We use
        # this flag after the instance create call to determine what
        # to return to the client
        return_reservation_id = create_kwargs.pop("return_reservation_id", False)

        requested_networks = None
        if "os-networks" in self.extension_info.get_extensions() or utils.is_neutron():
            requested_networks = server_dict.get("networks")

        if requested_networks is not None:
            requested_networks = self._get_requested_networks(requested_networks)

        if requested_networks and len(requested_networks):
            authorize(context, target, "create:attach_network")

        try:
            flavor_id = self._flavor_id_from_req_data(body)
        except ValueError:
            msg = _("Invalid flavorRef provided.")
            raise exc.HTTPBadRequest(explanation=msg)

        try:
            inst_type = flavors.get_flavor_by_flavor_id(flavor_id, ctxt=context, read_deleted="no")

            (instances, resv_id) = self.compute_api.create(
                context,
                inst_type,
                image_uuid,
                display_name=name,
                display_description=name,
                metadata=server_dict.get("metadata", {}),
                admin_password=password,
                requested_networks=requested_networks,
                check_server_group_quota=True,
                **create_kwargs
            )
        except (exception.QuotaError, exception.PortLimitExceeded) as error:
            raise exc.HTTPForbidden(explanation=error.format_message())
        except exception.ImageNotFound:
            msg = _("Can not find requested image")
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.FlavorNotFound:
            msg = _("Invalid flavorRef provided.")
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.KeypairNotFound:
            msg = _("Invalid key_name provided.")
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.ConfigDriveInvalidValue:
            msg = _("Invalid config_drive provided.")
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.ExternalNetworkAttachForbidden as error:
            raise exc.HTTPForbidden(explanation=error.format_message())
        except messaging.RemoteError as err:
            msg = "%(err_type)s: %(err_msg)s" % {"err_type": err.exc_type, "err_msg": err.value}
            raise exc.HTTPBadRequest(explanation=msg)
        except UnicodeDecodeError as error:
            msg = "UnicodeError: %s" % error
            raise exc.HTTPBadRequest(explanation=msg)
        except (
            exception.ImageNotActive,
            exception.ImageBadRequest,
            exception.FlavorDiskTooSmall,
            exception.FlavorMemoryTooSmall,
            exception.InvalidMetadata,
            exception.InvalidRequest,
            exception.InvalidVolume,
            exception.MultiplePortsNotApplicable,
            exception.InvalidFixedIpAndMaxCountRequest,
            exception.InstanceUserDataMalformed,
            exception.InstanceUserDataTooLarge,
            exception.PortNotFound,
            exception.FixedIpAlreadyInUse,
            exception.SecurityGroupNotFound,
            exception.PortRequiresFixedIP,
            exception.NetworkRequiresSubnet,
            exception.NetworkNotFound,
            exception.NetworkDuplicated,
            exception.InvalidBDMSnapshot,
            exception.InvalidBDMVolume,
            exception.InvalidBDMImage,
            exception.InvalidBDMBootSequence,
            exception.InvalidBDMLocalsLimit,
            exception.InvalidBDMVolumeNotBootable,
            exception.InvalidBDMEphemeralSize,
            exception.InvalidBDMFormat,
            exception.InvalidBDMSwapSize,
            exception.AutoDiskConfigDisabledByImage,
            exception.ImageNUMATopologyIncomplete,
            exception.ImageNUMATopologyForbidden,
            exception.ImageNUMATopologyAsymmetric,
            exception.ImageNUMATopologyCPUOutOfRange,
            exception.ImageNUMATopologyCPUDuplicates,
            exception.ImageNUMATopologyCPUsUnassigned,
            exception.ImageNUMATopologyMemoryOutOfRange,
        ) as error:
            raise exc.HTTPBadRequest(explanation=error.format_message())
        except (
            exception.PortInUse,
            exception.InstanceExists,
            exception.NetworkAmbiguous,
            exception.NoUniqueMatch,
        ) as error:
            raise exc.HTTPConflict(explanation=error.format_message())

        # If the caller wanted a reservation_id, return it
        if return_reservation_id:
            # NOTE(cyeoh): In v3 reservation_id was wrapped in
            # servers_reservation but this is reverted for V2 API
            # compatibility. In the long term with the tasks API we
            # will probably just drop the concept of reservation_id
            return wsgi.ResponseObject({"reservation_id": resv_id})

        req.cache_db_instances(instances)
        server = self._view_builder.create(req, instances[0])

        if CONF.enable_instance_password:
            server["server"]["adminPass"] = password

        robj = wsgi.ResponseObject(server)

        return self._add_location(robj)
Example #21
0
    def _action_rebuild(self, req, id, body):
        """Rebuild an instance with the given attributes."""
        rebuild_dict = body["rebuild"]

        image_href = rebuild_dict["imageRef"]
        image_href = self._image_uuid_from_href(image_href)

        password = self._get_server_admin_password(rebuild_dict)

        context = req.environ["nova.context"]
        authorize(context, action="rebuild")
        instance = self._get_server(context, req, id)

        attr_map = {"name": "display_name", "metadata": "metadata"}

        rebuild_kwargs = {}

        if list(self.rebuild_extension_manager):
            self.rebuild_extension_manager.map(self._rebuild_extension_point, rebuild_dict, rebuild_kwargs)

        for request_attribute, instance_attribute in attr_map.items():
            try:
                if request_attribute == "name":
                    rebuild_kwargs[instance_attribute] = common.normalize_name(rebuild_dict[request_attribute])
                else:
                    rebuild_kwargs[instance_attribute] = rebuild_dict[request_attribute]
            except (KeyError, TypeError):
                pass

        try:
            self.compute_api.rebuild(context, instance, image_href, password, **rebuild_kwargs)
        except exception.InstanceIsLocked as e:
            raise exc.HTTPConflict(explanation=e.format_message())
        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(state_error, "rebuild", id)
        except exception.InstanceNotFound:
            msg = _("Instance could not be found")
            raise exc.HTTPNotFound(explanation=msg)
        except exception.InstanceUnknownCell as e:
            raise exc.HTTPNotFound(explanation=e.format_message())
        except exception.ImageNotFound:
            msg = _("Cannot find image for rebuild")
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.QuotaError as error:
            raise exc.HTTPForbidden(explanation=error.format_message())
        except (
            exception.ImageNotActive,
            exception.FlavorDiskTooSmall,
            exception.FlavorMemoryTooSmall,
            exception.InvalidMetadata,
            exception.AutoDiskConfigDisabledByImage,
        ) as error:
            raise exc.HTTPBadRequest(explanation=error.format_message())

        instance = self._get_server(context, req, id, is_detail=True)

        view = self._view_builder.show(req, instance, extend_address=False)

        # Add on the admin_password attribute since the view doesn't do it
        # unless instance passwords are disabled
        if CONF.enable_instance_password:
            view["server"]["adminPass"] = password

        robj = wsgi.ResponseObject(view)
        return self._add_location(robj)
Example #22
0
    def create(self, req, body):
        """Creates a new server for a given user."""

        context = req.environ['nova.context']
        server_dict = body['server']
        password = self._get_server_admin_password(server_dict)
        name = common.normalize_name(server_dict['name'])

        if api_version_request.is_supported(req, min_version='2.19'):
            if 'description' in server_dict:
                # This is allowed to be None
                description = server_dict['description']
            else:
                # No default description
                description = None
        else:
            description = name

        # Arguments to be passed to instance create function
        create_kwargs = {}

        # Query extensions which want to manipulate the keyword
        # arguments.
        # NOTE(cyeoh): This is the hook that extensions use
        # to replace the extension specific code below.
        # When the extensions are ported this will also result
        # in some convenience function from this class being
        # moved to the extension
        if list(self.create_extension_manager):
            self.create_extension_manager.map(self._create_extension_point,
                                              server_dict, create_kwargs, body)

        availability_zone = create_kwargs.pop("availability_zone", None)

        helpers.translate_attributes(helpers.CREATE,
                                     server_dict, create_kwargs)

        target = {
            'project_id': context.project_id,
            'user_id': context.user_id,
            'availability_zone': availability_zone}
        context.can(server_policies.SERVERS % 'create', target)

        # TODO(Shao He, Feng) move this policy check to os-availability-zone
        # extension after refactor it.
        parse_az = self.compute_api.parse_availability_zone
        try:
            availability_zone, host, node = parse_az(context,
                                                     availability_zone)
        except exception.InvalidInput as err:
            raise exc.HTTPBadRequest(explanation=six.text_type(err))
        if host or node:
            context.can(server_policies.SERVERS % 'create:forced_host', {})

        min_compute_version = objects.Service.get_minimum_version(
            nova_context.get_admin_context(), 'nova-compute')
        supports_device_tagging = (min_compute_version >=
                                   DEVICE_TAGGING_MIN_COMPUTE_VERSION)

        block_device_mapping = create_kwargs.get("block_device_mapping")
        # TODO(Shao He, Feng) move this policy check to os-block-device-mapping
        # extension after refactor it.
        if block_device_mapping:
            context.can(server_policies.SERVERS % 'create:attach_volume',
                        target)
            for bdm in block_device_mapping:
                if bdm.get('tag', None) and not supports_device_tagging:
                    msg = _('Block device tags are not yet supported.')
                    raise exc.HTTPBadRequest(explanation=msg)

        image_uuid = self._image_from_req_data(server_dict, create_kwargs)

        # NOTE(cyeoh): Although an extension can set
        # return_reservation_id in order to request that a reservation
        # id be returned to the client instead of the newly created
        # instance information we do not want to pass this parameter
        # to the compute create call which always returns both. We use
        # this flag after the instance create call to determine what
        # to return to the client
        return_reservation_id = create_kwargs.pop('return_reservation_id',
                                                  False)

        requested_networks = None
        if ('os-networks' in self.extension_info.get_extensions()
                or utils.is_neutron()):
            requested_networks = server_dict.get('networks')

        if requested_networks is not None:
            requested_networks = self._get_requested_networks(
                requested_networks, supports_device_tagging)

        if requested_networks and len(requested_networks):
            context.can(server_policies.SERVERS % 'create:attach_network',
                        target)

        flavor_id = self._flavor_id_from_req_data(body)
        try:
            inst_type = flavors.get_flavor_by_flavor_id(
                    flavor_id, ctxt=context, read_deleted="no")

            (instances, resv_id) = self.compute_api.create(context,
                            inst_type,
                            image_uuid,
                            display_name=name,
                            display_description=description,
                            availability_zone=availability_zone,
                            forced_host=host, forced_node=node,
                            metadata=server_dict.get('metadata', {}),
                            admin_password=password,
                            requested_networks=requested_networks,
                            check_server_group_quota=True,
                            **create_kwargs)
        except (exception.QuotaError,
                exception.PortLimitExceeded) as error:
            raise exc.HTTPForbidden(
                explanation=error.format_message())
        except exception.ImageNotFound:
            msg = _("Can not find requested image")
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.KeypairNotFound:
            msg = _("Invalid key_name provided.")
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.ConfigDriveInvalidValue:
            msg = _("Invalid config_drive provided.")
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.ExternalNetworkAttachForbidden as error:
            raise exc.HTTPForbidden(explanation=error.format_message())
        except messaging.RemoteError as err:
            msg = "%(err_type)s: %(err_msg)s" % {'err_type': err.exc_type,
                                                 'err_msg': err.value}
            raise exc.HTTPBadRequest(explanation=msg)
        except UnicodeDecodeError as error:
            msg = "UnicodeError: %s" % error
            raise exc.HTTPBadRequest(explanation=msg)
        except (exception.ImageNotActive,
                exception.ImageBadRequest,
                exception.FixedIpNotFoundForAddress,
                exception.FlavorNotFound,
                exception.FlavorDiskTooSmall,
                exception.FlavorMemoryTooSmall,
                exception.InvalidMetadata,
                exception.InvalidRequest,
                exception.InvalidVolume,
                exception.MultiplePortsNotApplicable,
                exception.InvalidFixedIpAndMaxCountRequest,
                exception.InstanceUserDataMalformed,
                exception.InstanceUserDataTooLarge,
                exception.PortNotFound,
                exception.FixedIpAlreadyInUse,
                exception.SecurityGroupNotFound,
                exception.PortRequiresFixedIP,
                exception.NetworkRequiresSubnet,
                exception.NetworkNotFound,
                exception.NetworkDuplicated,
                exception.InvalidBDM,
                exception.InvalidBDMSnapshot,
                exception.InvalidBDMVolume,
                exception.InvalidBDMImage,
                exception.InvalidBDMBootSequence,
                exception.InvalidBDMLocalsLimit,
                exception.InvalidBDMVolumeNotBootable,
                exception.InvalidBDMEphemeralSize,
                exception.InvalidBDMFormat,
                exception.InvalidBDMSwapSize,
                exception.AutoDiskConfigDisabledByImage,
                exception.ImageNUMATopologyIncomplete,
                exception.ImageNUMATopologyForbidden,
                exception.ImageNUMATopologyAsymmetric,
                exception.ImageNUMATopologyCPUOutOfRange,
                exception.ImageNUMATopologyCPUDuplicates,
                exception.ImageNUMATopologyCPUsUnassigned,
                exception.ImageNUMATopologyMemoryOutOfRange,
                exception.InstanceGroupNotFound,
                exception.PciRequestAliasNotDefined,
                exception.UnableToAutoAllocateNetwork) as error:
            raise exc.HTTPBadRequest(explanation=error.format_message())
        except (exception.PortInUse,
                exception.InstanceExists,
                exception.NetworkAmbiguous,
                exception.NoUniqueMatch) as error:
            raise exc.HTTPConflict(explanation=error.format_message())

        # If the caller wanted a reservation_id, return it
        if return_reservation_id:
            return wsgi.ResponseObject({'reservation_id': resv_id})

        req.cache_db_instances(instances)
        server = self._view_builder.create(req, instances[0])

        if CONF.enable_instance_password:
            server['server']['adminPass'] = password

        robj = wsgi.ResponseObject(server)

        return self._add_location(robj)