def _migrate(self, req, id, body): """Permit admins to migrate a server to a new host.""" context = req.environ['nova.context'] authorize(context, 'migrate') instance = common.get_instance(self.compute_api, context, id, want_objects=True) try: self.compute_api.resize(req.environ['nova.context'], instance) except exception.TooManyInstances as e: raise exc.HTTPRequestEntityTooLarge(explanation=e.format_message()) except exception.QuotaError as error: raise exc.HTTPRequestEntityTooLarge( explanation=error.format_message(), headers={'Retry-After': 0}) 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, 'migrate') except exception.InstanceNotFound as e: raise exc.HTTPNotFound(explanation=e.format_message()) except exception.NoValidHost as e: raise exc.HTTPBadRequest(explanation=e.format_message()) return webob.Response(status_int=202)
def _update_instance_metadata(self, context, server_id, metadata, delete=False): try: server = self.compute_api.get(context, server_id) return self.compute_api.update_instance_metadata(context, server, metadata, delete) except exception.InstanceNotFound: msg = _('Server does not exist') raise exc.HTTPNotFound(explanation=msg) except (ValueError, AttributeError): msg = _("Malformed request body") raise exc.HTTPBadRequest(explanation=msg) except exception.InvalidMetadata as error: raise exc.HTTPBadRequest(explanation=unicode(error)) except exception.InvalidMetadataSize as error: raise exc.HTTPRequestEntityTooLarge(explanation=unicode(error)) except exception.QuotaError as error: raise exc.HTTPRequestEntityTooLarge(explanation=unicode(error), headers={'Retry-After': 0})
def _update_instance_metadata(self, context, server_id, metadata, delete=False): try: server = self.compute_api.get(context, server_id) return self.compute_api.update_instance_metadata( context, server, metadata, delete) except exception.InstanceNotFound: msg = _('Server does not exist') raise exc.HTTPNotFound(explanation=msg) except exception.InvalidMetadata as error: raise exc.HTTPBadRequest(explanation=error.format_message()) except exception.InvalidMetadataSize as error: raise exc.HTTPRequestEntityTooLarge( explanation=error.format_message()) except exception.QuotaError as error: raise exc.HTTPRequestEntityTooLarge( explanation=error.format_message(), headers={'Retry-After': 0}) except exception.InstanceInvalidState as state_error: common.raise_http_conflict_for_instance_invalid_state( state_error, 'update metadata')
def restore(self, req, id): """Restore an existing backupjobrun""" backupjobrun_id = id LOG.debug(_('Restoring backupjobrun %(backupjobrun_id)s') % locals()) context = req.environ['raksha.context'] LOG.audit(_("Restoring backupjobrun %(backupjobrun_id)s"), locals(), context=context) try: self.backupjob_api.backupjobrun_restore( context, backupjobrun_id=backupjobrun_id) except exception.InvalidInput as error: raise exc.HTTPBadRequest(explanation=unicode(error)) except exception.InvalidVolume as error: raise exc.HTTPBadRequest(explanation=unicode(error)) except exception.InvalidBackupJob as error: raise exc.HTTPBadRequest(explanation=unicode(error)) except exception.BackupJobNotFound as error: raise exc.HTTPNotFound(explanation=unicode(error)) except exception.VolumeNotFound as error: raise exc.HTTPNotFound(explanation=unicode(error)) except exception.VolumeSizeExceedsAvailableQuota as error: raise exc.HTTPRequestEntityTooLarge(explanation=error.message, headers={'Retry-After': 0}) except exception.VolumeLimitExceeded as error: raise exc.HTTPRequestEntityTooLarge(explanation=error.message, headers={'Retry-After': 0}) return webob.Response(status_int=202)
def _update_instance_metadata(self, context, server_id, metadata, delete=False): try: server = common.get_instance(self.compute_api, context, server_id, want_objects=True) return self.compute_api.update_instance_metadata( context, server, metadata, delete) except exception.InvalidMetadata as error: raise exc.HTTPBadRequest(explanation=error.format_message()) except exception.InvalidMetadataSize as error: raise exc.HTTPRequestEntityTooLarge( explanation=error.format_message()) except exception.QuotaError as error: raise exc.HTTPRequestEntityTooLarge( explanation=error.format_message(), headers={'Retry-After': 0}) 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, 'update metadata')
def restore(self, req, id, body): """Restore an existing backup to a volume.""" LOG.debug('Restoring backup %(backup_id)s (%(body)s)', { 'backup_id': id, 'body': body }) if not self.is_valid_body(body, 'restore'): msg = _("Incorrect request body format") raise exc.HTTPBadRequest(explanation=msg) context = req.environ['cinder.context'] restore = body['restore'] volume_id = restore.get('volume_id', None) # code begin by luobin availability_zone = restore.get('availability_zone', None) # code end by luobin description = restore.get('description', None) LOG.info(_("Restoring backup %(backup_id)s to volume %(volume_id)s"), { 'backup_id': id, 'volume_id': volume_id }, context=context) try: # code begin by luobin new_restore = self.backup_api.restore( context, backup_id=id, volume_id=volume_id, availability_zone=availability_zone, description=description) # code end by luobin except exception.InvalidInput as error: raise exc.HTTPBadRequest(explanation=error.msg) except exception.InvalidVolume as error: raise exc.HTTPBadRequest(explanation=error.msg) except exception.InvalidBackup as error: raise exc.HTTPBadRequest(explanation=error.msg) except exception.BackupNotFound as error: raise exc.HTTPNotFound(explanation=error.msg) except exception.VolumeNotFound as error: raise exc.HTTPNotFound(explanation=error.msg) except exception.VolumeSizeExceedsAvailableQuota as error: raise exc.HTTPRequestEntityTooLarge(explanation=error.msg, headers={'Retry-After': 0}) except exception.VolumeLimitExceeded as error: raise exc.HTTPRequestEntityTooLarge(explanation=error.msg, headers={'Retry-After': 0}) retval = self._view_builder.restore_summary( req, dict(new_restore.iteritems())) return retval
def restore(self, req, id, body): """Restore an existing backup to a volume.""" LOG.debug(_('Restoring backup %(backup_id)s (%(body)s)'), { 'backup_id': id, 'body': body }) if not self.is_valid_body(body, 'restore'): raise exc.HTTPBadRequest() context = req.environ['cinder.context'] try: restore = body['restore'] except KeyError: msg = _("Incorrect request body format") raise exc.HTTPBadRequest(explanation=msg) volume_id = restore.get('volume_id', None) LOG.audit(_("Restoring backup %(backup_id)s to volume %(volume_id)s"), { 'backup_id': id, 'volume_id': volume_id }, context=context) try: new_restore = self.backup_api.restore(context, backup_id=id, volume_id=volume_id) except exception.InvalidInput as error: raise exc.HTTPBadRequest(explanation=unicode(error)) except exception.InvalidVolume as error: raise exc.HTTPBadRequest(explanation=unicode(error)) except exception.InvalidBackup as error: raise exc.HTTPBadRequest(explanation=unicode(error)) except exception.BackupNotFound as error: raise exc.HTTPNotFound(explanation=unicode(error)) except exception.VolumeNotFound as error: raise exc.HTTPNotFound(explanation=unicode(error)) except exception.VolumeSizeExceedsAvailableQuota as error: raise exc.HTTPRequestEntityTooLarge(explanation=error.message, headers={'Retry-After': 0}) except exception.VolumeLimitExceeded as error: raise exc.HTTPRequestEntityTooLarge(explanation=error.message, headers={'Retry-After': 0}) retval = self._view_builder.restore_summary( req, dict(new_restore.iteritems())) return retval
def _update_instance_metadata(self, context, server_id, metadata, delete=False): try: server = common.get_instance(self.compute_api, context, server_id) return self.compute_api.update_instance_metadata( context, server, metadata, delete) except exception.InstanceNotFound: msg = _('Server does not exist') raise exc.HTTPNotFound(explanation=msg) except (ValueError, AttributeError): msg = _("Malformed request body") raise exc.HTTPBadRequest(explanation=msg) except exception.InvalidMetadata as error: raise exc.HTTPBadRequest(explanation=error.format_message()) except exception.InvalidMetadataSize as error: raise exc.HTTPRequestEntityTooLarge( explanation=error.format_message()) except exception.QuotaError as error: raise exc.HTTPForbidden(explanation=error.format_message()) 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, 'update metadata', server_id)
def __call__(self, req): resp = None success = False try: if req.path_info not in self._routes: raise exc.HTTPNotFound if req.method != 'POST': raise exc.HTTPMethodNotAllowed(explanation='Only POST allowed') if req.content_length > self.REQMAXBYTES: req.logged_body = req.body_file.read(self.REQMAXBYTES) + '...' raise exc.HTTPRequestEntityTooLarge(explanation='Request max ' 'size is {0} bytes'.format(self.REQMAXBYTES)) reqjson = loads(req.body) req.logged_body = reqjson handler = self._routes[req.path_info] respjson = handler(self, reqjson) resp = Response(body=dumps(respjson), content_type='application/json') resp.logged_body = respjson success = True except Exception as e: if isinstance(e, exc.HTTPException): resp = e elif isinstance(e, (JSONDecodeError, SchemaError)): resp = exc.HTTPBadRequest(explanation=repr(e)) else: resp = exc.HTTPInternalServerError(explanation=repr(e)) resp.logged_body = resp.explanation finally: try: self.log(req, resp, success) except Exception as e: resp = exc.HTTPInternalServerError(explanation='Log failure: {0}\n' 'req: {1}\nresp: {2}'.format(repr(e), getattr(req, 'logged_body', None), getattr(resp, 'logged_body', None))) return resp
def restore(self, req, id, body): """Restore an existing backup to a volume.""" LOG.debug('Restoring backup %(backup_id)s (%(body)s)', {'backup_id': id, 'body': body}) context = req.environ['cinder.context'] restore = body['restore'] volume_id = restore.get('volume_id', None) name = restore.get('name', None) LOG.info("Restoring backup %(backup_id)s to volume %(volume_id)s.", {'backup_id': id, 'volume_id': volume_id}, context=context) try: new_restore = self.backup_api.restore(context, backup_id=id, volume_id=volume_id, name=name) # Not found exception will be handled at the wsgi level except (exception.InvalidInput, exception.InvalidVolume, exception.InvalidBackup) as error: raise exc.HTTPBadRequest(explanation=error.msg) except (exception.VolumeSizeExceedsAvailableQuota, exception.VolumeLimitExceeded) as error: raise exc.HTTPRequestEntityTooLarge( explanation=error.msg, headers={'Retry-After': '0'}) retval = self._view_builder.restore_summary( req, dict(new_restore)) return retval
def accept(self, req, id, body): """Accept a new volume transfer.""" transfer_id = id LOG.debug(_('Accepting volume transfer %s'), transfer_id) if not self.is_valid_body(body, 'accept'): raise exc.HTTPBadRequest() context = req.environ['cinder.context'] try: accept = body['accept'] auth_key = accept['auth_key'] except KeyError: msg = _("Incorrect request body format") raise exc.HTTPBadRequest(explanation=msg) LOG.audit(_("Accepting transfer %s"), transfer_id, context=context) try: accepted_transfer = self.transfer_api.accept( context, transfer_id, auth_key) except exception.VolumeSizeExceedsAvailableQuota as error: raise exc.HTTPRequestEntityTooLarge(explanation=error.message, headers={'Retry-After': 0}) except exception.InvalidVolume as error: raise exc.HTTPBadRequest(explanation=unicode(error)) transfer = \ self._view_builder.summary(req, dict(accepted_transfer.iteritems())) return transfer
def accept(self, req, id, body): """Accept a new volume transfer.""" transfer_id = id LOG.debug('Accepting volume transfer %s', transfer_id) self.assert_valid_body(body, 'accept') context = req.environ['storage.context'] accept = body['accept'] try: auth_key = accept['auth_key'] except KeyError: msg = _("Incorrect request body format") raise exc.HTTPBadRequest(explanation=msg) LOG.info(_LI("Accepting transfer %s"), transfer_id, context=context) try: accepted_transfer = self.transfer_api.accept( context, transfer_id, auth_key) except exception.VolumeSizeExceedsAvailableQuota as error: raise exc.HTTPRequestEntityTooLarge(explanation=error.msg, headers={'Retry-After': '0'}) except exception.InvalidVolume as error: raise exc.HTTPBadRequest(explanation=error.msg) transfer = \ self._view_builder.summary(req, dict(accepted_transfer)) return transfer
def _resize(self, req, instance_id, flavor_id, **kwargs): """Begin the resize process with given instance/flavor.""" context = req.environ["nova.context"] instance = self._get_server(context, req, instance_id) try: self.compute_api.resize(context, instance, flavor_id, **kwargs) except exception.QuotaError as error: raise exc.HTTPRequestEntityTooLarge( explanation=error.format_message(), headers={'Retry-After': 0}) except exception.FlavorNotFound: msg = _("Unable to locate requested flavor.") raise exc.HTTPBadRequest(explanation=msg) except exception.CannotResizeToSameFlavor: msg = _("Resize requires a flavor change.") raise exc.HTTPBadRequest(explanation=msg) 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, 'resize') except exception.ImageNotAuthorized: msg = _("You are not authorized to access the image " "the instance was started with.") raise exc.HTTPUnauthorized(explanation=msg) except exception.ImageNotFound: msg = _("Image that the instance was started " "with could not be found.") raise exc.HTTPBadRequest(explanation=msg) except exception.Invalid: msg = _("Invalid instance image.") raise exc.HTTPBadRequest(explanation=msg) return webob.Response(status_int=202)
def _migrate(self, req, id, body): """Permit admins to migrate a server to a new host.""" context = req.environ['nova.context'] authorize(context, 'migrate') #ADD by zhjh 2014-12-03 migrate instance to a selected host. host = body["migrate"]["host"] if (isinstance(body['migrate'], dict) and 'host' in body['migrate']) else None try: instance = self.compute_api.get(context, id, want_objects=True) #MOD by zhjh 2014-12-04 migrate instance to a selected host. #self.compute_api.resize(req.environ['nova.context'], instance) self.compute_api.resize(req.environ['nova.context'], instance, host=host) except exception.QuotaError as error: raise exc.HTTPRequestEntityTooLarge( explanation=error.format_message(), headers={'Retry-After': 0}) 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, 'migrate') except exception.InstanceNotFound as e: raise exc.HTTPNotFound(explanation=e.format_message()) except Exception as e: LOG.exception(_("Error in migrate %s"), e) raise exc.HTTPBadRequest() return webob.Response(status_int=202)
def restore(self, req, id, body): """Restore an existing backup to a volume.""" LOG.debug('Restoring backup %(backup_id)s (%(body)s)', { 'backup_id': id, 'body': body }) self.assert_valid_body(body, 'restore') context = req.environ['cinder.context'] restore = body['restore'] volume_id = restore.get('volume_id', None) name = restore.get('name', None) LOG.info(_LI("Restoring backup %(backup_id)s to volume %(volume_id)s"), { 'backup_id': id, 'volume_id': volume_id }, context=context) try: new_restore = self.backup_api.restore(context, backup_id=id, volume_id=volume_id, name=name) except exception.InvalidInput as error: raise exc.HTTPBadRequest(explanation=error.msg) except exception.InvalidVolume as error: raise exc.HTTPBadRequest(explanation=error.msg) except exception.InvalidBackup as error: raise exc.HTTPBadRequest(explanation=error.msg) except exception.BackupNotFound as error: raise exc.HTTPNotFound(explanation=error.msg) except exception.VolumeNotFound as error: raise exc.HTTPNotFound(explanation=error.msg) except exception.VolumeSizeExceedsAvailableQuota as error: raise exc.HTTPRequestEntityTooLarge(explanation=error.msg, headers={'Retry-After': 0}) except exception.VolumeLimitExceeded as error: raise exc.HTTPRequestEntityTooLarge(explanation=error.msg, headers={'Retry-After': 0}) retval = self._view_builder.restore_summary(req, dict(new_restore)) return retval
def code2exception(code, detail): """Transforms a code + detail into a WebOb exception""" if code == 400: return exc.HTTPBadRequest(detail) if code == 401: return exc.HTTPUnauthorized(detail) if code == 402: return exc.HTTPPaymentRequired(detail) if code == 403: return exc.HTTPForbidden(detail) if code == 404: return exc.HTTPNotFound(detail) if code == 405: return exc.HTTPMethodNotAllowed(detail) if code == 406: return exc.HTTPNotAcceptable(detail) if code == 407: return exc.HTTPProxyAuthenticationRequired(detail) if code == 408: return exc.HTTPRequestTimeout(detail) if code == 409: return exc.HTTPConflict(detail) if code == 410: return exc.HTTPGone(detail) if code == 411: return exc.HTTPLengthRequired(detail) if code == 412: return exc.HTTPPreconditionFailed(detail) if code == 413: return exc.HTTPRequestEntityTooLarge(detail) if code == 414: return exc.HTTPRequestURITooLong(detail) if code == 415: return exc.HTTPUnsupportedMediaType(detail) if code == 416: return exc.HTTPRequestRangeNotSatisfiable(detail) if code == 417: return exc.HTTPExpectationFailed(detail) if code == 500: return exc.HTTPInternalServerError(detail) if code == 501: return exc.HTTPNotImplemented(detail) if code == 502: return exc.HTTPBadGateway(detail) if code == 503: return exc.HTTPServiceUnavailable(detail) if code == 504: return exc.HTTPGatewayTimeout(detail) if code == 505: return exc.HTTPVersionNotSupported(detail) raise NotImplementedError(code)
def _handle_quota_error(self, error): """ Reraise quota errors as api-specific http exceptions """ if error.code == "OnsetFileLimitExceeded": expl = _("Personality file limit exceeded") raise exc.HTTPRequestEntityTooLarge(explanation=error.message, headers={'Retry-After': 0}) if error.code == "OnsetFilePathLimitExceeded": expl = _("Personality file path too long") raise exc.HTTPRequestEntityTooLarge(explanation=error.message, headers={'Retry-After': 0}) if error.code == "OnsetFileContentLimitExceeded": expl = _("Personality file content too long") raise exc.HTTPRequestEntityTooLarge(explanation=error.message, headers={'Retry-After': 0}) if error.code == "InstanceLimitExceeded": expl = _("Instance quotas have been exceeded") raise exc.HTTPRequestEntityTooLarge(explanation=error.message, headers={'Retry-After': 0}) # if the original error is okay, just reraise it raise error
def _update_instance_metadata(self, context, server_id, metadata, delete=False): try: # This is very ugly! But because the key/value pairs of metadata # must be a string and we must make 5.1API be consistent with # 5.0API, we can only compromise. # And, there is a bug in 5.0, that is, if we set boot order to # network,hd via updating metadata, when we migrate or hard reboot # the vm, the boot order would be changed to hd. if ('__bootDev' in metadata and isinstance(metadata['__bootDev'], list)): str_boot_dev = '' for boot_dev in metadata['__bootDev']: str_boot_dev = str_boot_dev + str(boot_dev) + ',' str_boot_dev = str_boot_dev[:len(str_boot_dev) - 1] metadata['__bootDev'] = str_boot_dev server = self.compute_api.get(context, server_id, want_objects=True) return self.compute_api.update_instance_metadata( context, server, metadata, delete) except exception.InstanceNotFound: msg = _('Server does not exist') raise exc.HTTPNotFound(explanation=msg) except (ValueError, AttributeError): msg = _("Malformed request body") raise exc.HTTPBadRequest(explanation=msg) except exception.InvalidMetadata as error: raise exc.HTTPBadRequest(explanation=error.format_message()) except exception.InvalidMetadataSize as error: raise exc.HTTPRequestEntityTooLarge( explanation=error.format_message()) except exception.QuotaError as error: raise exc.HTTPForbidden(explanation=error.format_message()) 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, 'update metadata')
def _handle_quota_error(self, error): """ Reraise quota errors as api-specific http exceptions """ code_mappings = { "OnsetFileLimitExceeded": _("Personality file limit exceeded"), "OnsetFilePathLimitExceeded": _("Personality file path too long"), "OnsetFileContentLimitExceeded": _("Personality file content too long"), # NOTE(bcwaldon): expose the message generated below in order # to better explain how the quota was exceeded "InstanceLimitExceeded": error.message, } expl = code_mappings.get(error.code) if expl: raise exc.HTTPRequestEntityTooLarge(explanation=expl, headers={'Retry-After': 0}) # if the original error is okay, just reraise it raise exc.HTTPRequestEntityTooLarge(explanation=error.msg, headers={'Retry-After': 0})
def translate_exceptions(): """Translate nova exceptions to http exceptions.""" try: yield except exception.Invalid as exp: msg = exp.format_message() raise exc.HTTPBadRequest(explanation=msg) except exception.SecurityGroupNotFound as exp: msg = exp.format_message() raise exc.HTTPNotFound(explanation=msg) except exception.InstanceNotFound as exp: msg = exp.format_message() raise exc.HTTPNotFound(explanation=msg) except exception.SecurityGroupLimitExceeded as exp: msg = exp.format_message() raise exc.HTTPRequestEntityTooLarge(explanation=msg)
def _update_snapshot_metadata(self, context, snapshot_id, metadata, delete=False): try: snapshot = self.volume_api.get_snapshot(context, snapshot_id) return self.volume_api.update_snapshot_metadata( context, snapshot, metadata, delete) # Not found exception will be handled at the wsgi level except (ValueError, AttributeError): msg = _("Malformed request body") raise exc.HTTPBadRequest(explanation=msg) except exception.InvalidVolumeMetadata as error: raise exc.HTTPBadRequest(explanation=error.msg) except exception.InvalidVolumeMetadataSize as error: raise exc.HTTPRequestEntityTooLarge(explanation=error.msg)
def __call__(self, request): if len(request.path_info + request.query_string) > 4096: return exc.HTTPRequestURITooLong() if request.method in ['PUT', 'POST']: if 'Content-Length' in request.headers and\ int(request.headers['Content-Length']) > 3145728: return exc.HTTPRequestEntityTooLarge() elif 'Content-Length' not in request.headers: return exc.HTTPLengthRequired() if not request.path_info in _SERVICES_PATHS: return exc.HTTPNotFound() func = _ROUTES.get((request.path_info, request.method)) if func is not None: return func(request) else: return exc.HTTPMethodNotAllowed()
def _migrate(self, req, id, body): """Permit admins to migrate a server to a new host.""" context = req.environ['nova.context'] authorize(context, 'migrate') try: instance = self.compute_api.get(context, id, want_objects=True) self.compute_api.resize(req.environ['nova.context'], instance) 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, 'migrate') except exception.InstanceNotFound as e: raise exc.HTTPNotFound(explanation=e.format_message()) except exception.FlavorNotFound as e: raise exc.HTTPNotFound(explanation=e.format_message()) except exception.CannotResizeToSameFlavor as e: raise exc.HTTPBadRequest(explanation=e.format_message()) except exception.TooManyInstances as e: raise exc.HTTPRequestEntityTooLarge(explanation=e.format_message()) return webob.Response(status_int=202)
def _update_snapshot_metadata(self, context, snapshot_id, metadata, delete=False): try: snapshot = self.volume_api.get_snapshot(context, snapshot_id) return self.volume_api.update_snapshot_metadata( context, snapshot, metadata, delete) except exception.SnapshotNotFound: msg = _('snapshot does not exist') raise exc.HTTPNotFound(explanation=msg) except (ValueError, AttributeError): msg = _("Malformed request body") raise exc.HTTPBadRequest(explanation=msg) except exception.InvalidVolumeMetadata as error: raise exc.HTTPBadRequest(explanation=error.msg) except exception.InvalidVolumeMetadataSize as error: raise exc.HTTPRequestEntityTooLarge(explanation=error.msg)
def _update_volume_metadata(self, context, volume_id, metadata, delete=False): try: volume = self.volume_api.get(context, volume_id) return self.volume_api.update_volume_metadata( context, volume, metadata, delete) except exception.VolumeNotFound: msg = _('volume does not exist') raise exc.HTTPNotFound(explanation=msg) except (ValueError, AttributeError): msg = _("Malformed request body") raise exc.HTTPBadRequest(explanation=msg) except exception.InvalidVolumeMetadata as error: raise exc.HTTPBadRequest(explanation=unicode(error)) except exception.InvalidVolumeMetadataSize as error: raise exc.HTTPRequestEntityTooLarge(explanation=unicode(error))
def accept(self, req, id, body): """Accept a new volume transfer.""" transfer_id = id LOG.debug('Accepting volume transfer %s', transfer_id) context = req.environ['cinder.context'] accept = body['accept'] auth_key = accept['auth_key'] LOG.info("Accepting transfer %s", transfer_id) try: accepted_transfer = self.transfer_api.accept( context, transfer_id, auth_key) except exception.VolumeSizeExceedsAvailableQuota as error: raise exc.HTTPRequestEntityTooLarge(explanation=error.msg, headers={'Retry-After': '0'}) except exception.InvalidVolume as error: raise exc.HTTPBadRequest(explanation=error.msg) transfer = \ self._view_builder.summary(req, dict(accepted_transfer)) return transfer
def _action_rebuild(self, req, id, body): """Rebuild an instance with the given attributes.""" body = body['rebuild'] try: image_href = body["imageRef"] except (KeyError, TypeError): msg = _("Could not parse imageRef from request.") raise exc.HTTPBadRequest(explanation=msg) image_href = self._image_uuid_from_href(image_href) password = self._get_server_admin_password(body) context = req.environ['nova.context'] instance = self._get_server(context, req, id) attr_map = { 'personality': 'files_to_inject', 'name': 'display_name', 'accessIPv4': 'access_ip_v4', 'accessIPv6': 'access_ip_v6', 'metadata': 'metadata', 'auto_disk_config': 'auto_disk_config', } kwargs = {} # take the preserve_ephemeral value into account only when the # corresponding extension is active if (self.ext_mgr.is_loaded('os-preserve-ephemeral-rebuild') and 'preserve_ephemeral' in body): kwargs['preserve_ephemeral'] = strutils.bool_from_string( body['preserve_ephemeral'], strict=True) if 'accessIPv4' in body: self._validate_access_ipv4(body['accessIPv4']) if 'accessIPv6' in body: self._validate_access_ipv6(body['accessIPv6']) if 'name' in body: self._validate_server_name(body['name']) for request_attribute, instance_attribute in attr_map.items(): try: kwargs[instance_attribute] = body[request_attribute] except (KeyError, TypeError): pass self._validate_metadata(kwargs.get('metadata', {})) if 'files_to_inject' in kwargs: personality = kwargs.pop('files_to_inject') files_to_inject = self._get_injected_files(personality) else: files_to_inject = None try: self.compute_api.rebuild(context, instance, image_href, password, files_to_inject=files_to_inject, **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.InvalidMetadataSize as error: raise exc.HTTPRequestEntityTooLarge( explanation=error.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) view = self._view_builder.show(req, instance) # Add on the adminPass 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)
def create(self, req, body): """Creates a new server for a given user.""" if not body: raise exc.HTTPUnprocessableEntity() if not 'server' in body: raise exc.HTTPUnprocessableEntity() body['server']['key_name'] = self._get_key_name(req, body) context = req.environ['nova.context'] server_dict = body['server'] password = self._get_server_admin_password(server_dict) if not 'name' in server_dict: msg = _("Server name is not defined") raise exc.HTTPBadRequest(explanation=msg) name = server_dict['name'] self._validate_server_name(name) name = name.strip() image_href = self._image_ref_from_req_data(body) image_href = self._image_uuid_from_href(image_href) personality = server_dict.get('personality') config_drive = server_dict.get('config_drive') injected_files = [] if personality: injected_files = self._get_injected_files(personality) sg_names = [] security_groups = server_dict.get('security_groups') if security_groups is not None: sg_names = [sg['name'] for sg in security_groups if sg.get('name')] if not sg_names: sg_names.append('default') sg_names = list(set(sg_names)) requested_networks = server_dict.get('networks') if requested_networks is not None: requested_networks = self._get_requested_networks( requested_networks) (access_ip_v4, ) = server_dict.get('accessIPv4'), if access_ip_v4 is not None: self._validate_access_ipv4(access_ip_v4) (access_ip_v6, ) = server_dict.get('accessIPv6'), if access_ip_v6 is not None: self._validate_access_ipv6(access_ip_v6) try: flavor_id = self._flavor_id_from_req_data(body) except ValueError as error: msg = _("Invalid flavorRef provided.") raise exc.HTTPBadRequest(explanation=msg) # optional openstack extensions: key_name = server_dict.get('key_name') user_data = server_dict.get('user_data') self._validate_user_data(user_data) availability_zone = server_dict.get('availability_zone') block_device_mapping = self._get_block_device_mapping(server_dict) ret_resv_id = server_dict.get('return_reservation_id', False) min_count = server_dict.get('min_count') max_count = server_dict.get('max_count') # min_count and max_count are optional. If they exist, they come # in as strings. We want to default 'min_count' to 1, and default # 'max_count' to be 'min_count'. min_count = int(min_count) if min_count else 1 max_count = int(max_count) if max_count else min_count if min_count > max_count: min_count = max_count auto_disk_config = server_dict.get('auto_disk_config') scheduler_hints = server_dict.get('scheduler_hints', {}) try: _get_inst_type = instance_types.get_instance_type_by_flavor_id inst_type = _get_inst_type(flavor_id, read_deleted="no") (instances, resv_id) = self.compute_api.create(context, inst_type, image_href, display_name=name, display_description=name, key_name=key_name, metadata=server_dict.get('metadata', {}), access_ip_v4=access_ip_v4, access_ip_v6=access_ip_v6, injected_files=injected_files, admin_password=password, min_count=min_count, max_count=max_count, requested_networks=requested_networks, security_group=sg_names, user_data=user_data, availability_zone=availability_zone, config_drive=config_drive, block_device_mapping=block_device_mapping, auto_disk_config=auto_disk_config, scheduler_hints=scheduler_hints) except exception.QuotaError as error: raise exc.HTTPRequestEntityTooLarge(explanation=unicode(error), headers={'Retry-After': 0}) except exception.InstanceTypeMemoryTooSmall as error: raise exc.HTTPBadRequest(explanation=unicode(error)) except exception.InstanceTypeNotFound as error: raise exc.HTTPBadRequest(explanation=unicode(error)) except exception.InstanceTypeDiskTooSmall as error: raise exc.HTTPBadRequest(explanation=unicode(error)) except exception.InvalidMetadata as error: raise exc.HTTPBadRequest(explanation=unicode(error)) except exception.ImageNotFound as error: msg = _("Can not find requested image") raise exc.HTTPBadRequest(explanation=msg) except exception.FlavorNotFound as error: msg = _("Invalid flavorRef provided.") raise exc.HTTPBadRequest(explanation=msg) except exception.KeypairNotFound as error: msg = _("Invalid key_name provided.") raise exc.HTTPBadRequest(explanation=msg) except exception.SecurityGroupNotFound as error: raise exc.HTTPBadRequest(explanation=unicode(error)) except rpc_common.RemoteError as err: msg = "%(err_type)s: %(err_msg)s" % {'err_type': err.exc_type, 'err_msg': err.value} raise exc.HTTPBadRequest(explanation=msg) # Let the caller deal with unhandled exceptions. # If the caller wanted a reservation_id, return it if ret_resv_id: return {'reservation_id': resv_id} req.cache_db_instances(instances) server = self._view_builder.create(req, instances[0]) if '_is_precooked' in server['server'].keys(): del server['server']['_is_precooked'] else: if FLAGS.enable_instance_password: server['server']['adminPass'] = password robj = wsgi.ResponseObject(server) return self._add_location(robj)
def restore(self, req, id, body): """Restore an existing backup to a volume.""" LOG.debug('Restoring backup %(backup_id)s (%(body)s)', { 'backup_id': id, 'body': body }) if not self.is_valid_body(body, 'restore'): msg = _("Incorrect request body format") raise exc.HTTPBadRequest(explanation=msg) context = req.environ['cinder.context'] restore = body['restore'] volume_id = restore.get('volume_id', None) periodic = restore.get('periodic', False) if periodic: backup = self.backup_api.get(context, backup_id=id) if backup['volume_id'] != volume_id: LOG.debug( "Can't restore backup %(backup_id)s to " "volume %(volume_id)s", { 'backup_id': id, 'volume_id': volume_id }, context=context) msg = _("Periodic backup must be restored to " "the original volume") raise exc.HTTPBadRequest(explanation=msg) context.set_periodic(True) LOG.info(_LI("Restoring periodic backup %(backup_id)s to " "volume %(volume_id)s"), { 'backup_id': id, 'volume_id': volume_id }, context=context) else: LOG.info(_LI("Restoring backup %(backup_id)s to " "volume %(volume_id)s"), { 'backup_id': id, 'volume_id': volume_id }, context=context) try: new_restore = self.backup_api.restore(context, backup_id=id, volume_id=volume_id) except exception.InvalidInput as error: raise exc.HTTPBadRequest(explanation=error.msg) except exception.InvalidVolume as error: raise exc.HTTPBadRequest(explanation=error.msg) except exception.InvalidBackup as error: raise exc.HTTPBadRequest(explanation=error.msg) except exception.BackupNotFound as error: raise exc.HTTPNotFound(explanation=error.msg) except exception.VolumeNotFound as error: raise exc.HTTPNotFound(explanation=error.msg) except exception.VolumeSizeExceedsAvailableQuota as error: raise exc.HTTPRequestEntityTooLarge(explanation=error.msg, headers={'Retry-After': 0}) except exception.VolumeLimitExceeded as error: raise exc.HTTPRequestEntityTooLarge(explanation=error.msg, headers={'Retry-After': 0}) retval = self._view_builder.restore_summary( req, dict(new_restore.iteritems())) return retval
def _action_rebuild(self, req, id, body): """Rebuild an instance with the given attributes.""" try: rebuild_dict = body['rebuild'] except (KeyError, TypeError): msg = _('Invalid request body') raise exc.HTTPBadRequest(explanation=msg) try: image_href = rebuild_dict["image_ref"] except (KeyError, TypeError): msg = _("Could not parse image_ref from request.") raise exc.HTTPBadRequest(explanation=msg) image_href = self._image_uuid_from_href(image_href) password = self._get_server_admin_password(rebuild_dict) context = req.environ['nova.context'] instance = self._get_server(context, req, id) attr_map = { 'name': 'display_name', 'metadata': 'metadata', } rebuild_kwargs = {} if 'name' in rebuild_dict: self._validate_server_name(rebuild_dict['name']) if 'preserve_ephemeral' in rebuild_dict: rebuild_kwargs['preserve_ephemeral'] = strutils.bool_from_string( rebuild_dict['preserve_ephemeral'], strict=True) 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: 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') except exception.InstanceNotFound: msg = _("Instance could not be found") raise exc.HTTPNotFound(explanation=msg) except exception.InvalidMetadataSize as error: raise exc.HTTPRequestEntityTooLarge( explanation=error.format_message()) except exception.ImageNotFound: msg = _("Cannot find image for rebuild") raise exc.HTTPBadRequest(explanation=msg) except (exception.ImageNotActive, exception.FlavorDiskTooSmall, exception.FlavorMemoryTooSmall, exception.InvalidMetadata) as error: raise exc.HTTPBadRequest(explanation=error.format_message()) instance = self._get_server(context, req, id) view = self._view_builder.show(req, instance) # 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']['admin_password'] = password robj = wsgi.ResponseObject(view) return self._add_location(robj)