Replace ApiError with new exceptions
* Convert ApiError to EC2APIError * Add new exceptions to replace ApiError where it didn't belong * Fixes bug 926250 Change-Id: Ia711440ee0313faf8ea8c87e2c0a2f5b39cc55a2
This commit is contained in:
		@@ -1607,7 +1607,7 @@ class VsaDriveTypeCommands(object):
 | 
				
			|||||||
        """Marks volume types as deleted"""
 | 
					        """Marks volume types as deleted"""
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            volume_types.destroy(self.context, name)
 | 
					            volume_types.destroy(self.context, name)
 | 
				
			||||||
        except exception.ApiError:
 | 
					        except exception.InvalidVolumeType:
 | 
				
			||||||
            print "Valid volume type name is required"
 | 
					            print "Valid volume type name is required"
 | 
				
			||||||
            sys.exit(1)
 | 
					            sys.exit(1)
 | 
				
			||||||
        except exception.DBError, e:
 | 
					        except exception.DBError, e:
 | 
				
			||||||
@@ -1786,7 +1786,7 @@ class InstanceTypeCommands(object):
 | 
				
			|||||||
        """Marks instance types / flavors as deleted"""
 | 
					        """Marks instance types / flavors as deleted"""
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            instance_types.destroy(name)
 | 
					            instance_types.destroy(name)
 | 
				
			||||||
        except exception.ApiError:
 | 
					        except exception.InstanceTypeNotFound:
 | 
				
			||||||
            print "Valid instance type name is required"
 | 
					            print "Valid instance type name is required"
 | 
				
			||||||
            sys.exit(1)
 | 
					            sys.exit(1)
 | 
				
			||||||
        except exception.DBError, e:
 | 
					        except exception.DBError, e:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -598,8 +598,8 @@ class Executor(wsgi.Application):
 | 
				
			|||||||
        except exception.NotFound as ex:
 | 
					        except exception.NotFound as ex:
 | 
				
			||||||
            LOG.info(_('NotFound raised: %s'), unicode(ex), context=context)
 | 
					            LOG.info(_('NotFound raised: %s'), unicode(ex), context=context)
 | 
				
			||||||
            return ec2_error(req, request_id, type(ex).__name__, unicode(ex))
 | 
					            return ec2_error(req, request_id, type(ex).__name__, unicode(ex))
 | 
				
			||||||
        except exception.ApiError as ex:
 | 
					        except exception.EC2APIError as ex:
 | 
				
			||||||
            LOG.exception(_('ApiError raised: %s'), unicode(ex),
 | 
					            LOG.exception(_('EC2APIError raised: %s'), unicode(ex),
 | 
				
			||||||
                          context=context)
 | 
					                          context=context)
 | 
				
			||||||
            if ex.code:
 | 
					            if ex.code:
 | 
				
			||||||
                return ec2_error(req, request_id, ex.code, unicode(ex))
 | 
					                return ec2_error(req, request_id, ex.code, unicode(ex))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -600,7 +600,7 @@ class CloudController(object):
 | 
				
			|||||||
                                      group_id=None, **kwargs):
 | 
					                                      group_id=None, **kwargs):
 | 
				
			||||||
        if not group_name and not group_id:
 | 
					        if not group_name and not group_id:
 | 
				
			||||||
            err = "Not enough parameters, need group_name or group_id"
 | 
					            err = "Not enough parameters, need group_name or group_id"
 | 
				
			||||||
            raise exception.ApiError(_(err))
 | 
					            raise exception.EC2APIError(_(err))
 | 
				
			||||||
        self.compute_api.ensure_default_security_group(context)
 | 
					        self.compute_api.ensure_default_security_group(context)
 | 
				
			||||||
        notfound = exception.SecurityGroupNotFound
 | 
					        notfound = exception.SecurityGroupNotFound
 | 
				
			||||||
        if group_name:
 | 
					        if group_name:
 | 
				
			||||||
@@ -626,7 +626,7 @@ class CloudController(object):
 | 
				
			|||||||
            rulesvalues = self._rule_args_to_dict(context, values)
 | 
					            rulesvalues = self._rule_args_to_dict(context, values)
 | 
				
			||||||
            if not rulesvalues:
 | 
					            if not rulesvalues:
 | 
				
			||||||
                err = "%s Not enough parameters to build a valid rule"
 | 
					                err = "%s Not enough parameters to build a valid rule"
 | 
				
			||||||
                raise exception.ApiError(_(err % rulesvalues))
 | 
					                raise exception.EC2APIError(_(err % rulesvalues))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for values_for_rule in rulesvalues:
 | 
					            for values_for_rule in rulesvalues:
 | 
				
			||||||
                values_for_rule['parent_group_id'] = security_group.id
 | 
					                values_for_rule['parent_group_id'] = security_group.id
 | 
				
			||||||
@@ -640,7 +640,7 @@ class CloudController(object):
 | 
				
			|||||||
                    context,
 | 
					                    context,
 | 
				
			||||||
                    security_group_id=security_group['id'])
 | 
					                    security_group_id=security_group['id'])
 | 
				
			||||||
            return True
 | 
					            return True
 | 
				
			||||||
        raise exception.ApiError(_("No rule for the specified parameters."))
 | 
					        raise exception.EC2APIError(_("No rule for the specified parameters."))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # TODO(soren): This has only been tested with Boto as the client.
 | 
					    # TODO(soren): This has only been tested with Boto as the client.
 | 
				
			||||||
    #              Unfortunately, it seems Boto is using an old API
 | 
					    #              Unfortunately, it seems Boto is using an old API
 | 
				
			||||||
@@ -650,7 +650,7 @@ class CloudController(object):
 | 
				
			|||||||
                                         group_id=None, **kwargs):
 | 
					                                         group_id=None, **kwargs):
 | 
				
			||||||
        if not group_name and not group_id:
 | 
					        if not group_name and not group_id:
 | 
				
			||||||
            err = "Not enough parameters, need group_name or group_id"
 | 
					            err = "Not enough parameters, need group_name or group_id"
 | 
				
			||||||
            raise exception.ApiError(_(err))
 | 
					            raise exception.EC2APIError(_(err))
 | 
				
			||||||
        self.compute_api.ensure_default_security_group(context)
 | 
					        self.compute_api.ensure_default_security_group(context)
 | 
				
			||||||
        notfound = exception.SecurityGroupNotFound
 | 
					        notfound = exception.SecurityGroupNotFound
 | 
				
			||||||
        if group_name:
 | 
					        if group_name:
 | 
				
			||||||
@@ -676,13 +676,13 @@ class CloudController(object):
 | 
				
			|||||||
            rulesvalues = self._rule_args_to_dict(context, values)
 | 
					            rulesvalues = self._rule_args_to_dict(context, values)
 | 
				
			||||||
            if not rulesvalues:
 | 
					            if not rulesvalues:
 | 
				
			||||||
                err = "%s Not enough parameters to build a valid rule"
 | 
					                err = "%s Not enough parameters to build a valid rule"
 | 
				
			||||||
                raise exception.ApiError(_(err % rulesvalues))
 | 
					                raise exception.EC2APIError(_(err % rulesvalues))
 | 
				
			||||||
            for values_for_rule in rulesvalues:
 | 
					            for values_for_rule in rulesvalues:
 | 
				
			||||||
                values_for_rule['parent_group_id'] = security_group.id
 | 
					                values_for_rule['parent_group_id'] = security_group.id
 | 
				
			||||||
                if self._security_group_rule_exists(security_group,
 | 
					                if self._security_group_rule_exists(security_group,
 | 
				
			||||||
                                                    values_for_rule):
 | 
					                                                    values_for_rule):
 | 
				
			||||||
                    err = '%s - This rule already exists in group'
 | 
					                    err = '%s - This rule already exists in group'
 | 
				
			||||||
                    raise exception.ApiError(_(err) % values_for_rule)
 | 
					                    raise exception.EC2APIError(_(err) % values_for_rule)
 | 
				
			||||||
                postvalues.append(values_for_rule)
 | 
					                postvalues.append(values_for_rule)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for values_for_rule in postvalues:
 | 
					        for values_for_rule in postvalues:
 | 
				
			||||||
@@ -696,7 +696,7 @@ class CloudController(object):
 | 
				
			|||||||
                    security_group_id=security_group['id'])
 | 
					                    security_group_id=security_group['id'])
 | 
				
			||||||
            return True
 | 
					            return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        raise exception.ApiError(_("No rule for the specified parameters."))
 | 
					        raise exception.EC2APIError(_("No rule for the specified parameters."))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _get_source_project_id(self, context, source_security_group_owner_id):
 | 
					    def _get_source_project_id(self, context, source_security_group_owner_id):
 | 
				
			||||||
        if source_security_group_owner_id:
 | 
					        if source_security_group_owner_id:
 | 
				
			||||||
@@ -735,7 +735,8 @@ class CloudController(object):
 | 
				
			|||||||
        LOG.audit(_("Create Security Group %s"), group_name, context=context)
 | 
					        LOG.audit(_("Create Security Group %s"), group_name, context=context)
 | 
				
			||||||
        self.compute_api.ensure_default_security_group(context)
 | 
					        self.compute_api.ensure_default_security_group(context)
 | 
				
			||||||
        if db.security_group_exists(context, context.project_id, group_name):
 | 
					        if db.security_group_exists(context, context.project_id, group_name):
 | 
				
			||||||
            raise exception.ApiError(_('group %s already exists') % group_name)
 | 
					            msg = _('group %s already exists')
 | 
				
			||||||
 | 
					            raise exception.EC2APIError(msg % group_name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        group = {'user_id': context.user_id,
 | 
					        group = {'user_id': context.user_id,
 | 
				
			||||||
                 'project_id': context.project_id,
 | 
					                 'project_id': context.project_id,
 | 
				
			||||||
@@ -750,7 +751,7 @@ class CloudController(object):
 | 
				
			|||||||
                              **kwargs):
 | 
					                              **kwargs):
 | 
				
			||||||
        if not group_name and not group_id:
 | 
					        if not group_name and not group_id:
 | 
				
			||||||
            err = "Not enough parameters, need group_name or group_id"
 | 
					            err = "Not enough parameters, need group_name or group_id"
 | 
				
			||||||
            raise exception.ApiError(_(err))
 | 
					            raise exception.EC2APIError(_(err))
 | 
				
			||||||
        notfound = exception.SecurityGroupNotFound
 | 
					        notfound = exception.SecurityGroupNotFound
 | 
				
			||||||
        if group_name:
 | 
					        if group_name:
 | 
				
			||||||
            security_group = db.security_group_get_by_name(context,
 | 
					            security_group = db.security_group_get_by_name(context,
 | 
				
			||||||
@@ -906,7 +907,7 @@ class CloudController(object):
 | 
				
			|||||||
    def describe_instance_attribute(self, context, instance_id, attribute,
 | 
					    def describe_instance_attribute(self, context, instance_id, attribute,
 | 
				
			||||||
                                    **kwargs):
 | 
					                                    **kwargs):
 | 
				
			||||||
        def _unsupported_attribute(instance, result):
 | 
					        def _unsupported_attribute(instance, result):
 | 
				
			||||||
            raise exception.ApiError(_('attribute not supported: %s') %
 | 
					            raise exception.EC2APIError(_('attribute not supported: %s') %
 | 
				
			||||||
                                     attribute)
 | 
					                                     attribute)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def _format_attr_block_device_mapping(instance, result):
 | 
					        def _format_attr_block_device_mapping(instance, result):
 | 
				
			||||||
@@ -962,7 +963,7 @@ class CloudController(object):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        fn = attribute_formatter.get(attribute)
 | 
					        fn = attribute_formatter.get(attribute)
 | 
				
			||||||
        if fn is None:
 | 
					        if fn is None:
 | 
				
			||||||
            raise exception.ApiError(
 | 
					            raise exception.EC2APIError(
 | 
				
			||||||
                _('attribute not supported: %s') % attribute)
 | 
					                _('attribute not supported: %s') % attribute)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ec2_instance_id = instance_id
 | 
					        ec2_instance_id = instance_id
 | 
				
			||||||
@@ -1225,7 +1226,7 @@ class CloudController(object):
 | 
				
			|||||||
            raise exception.ImageNotFound(image_id=kwargs['image_id'])
 | 
					            raise exception.ImageNotFound(image_id=kwargs['image_id'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if image_state != 'available':
 | 
					        if image_state != 'available':
 | 
				
			||||||
            raise exception.ApiError(_('Image must be available'))
 | 
					            raise exception.EC2APIError(_('Image must be available'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        (instances, resv_id) = self.compute_api.create(context,
 | 
					        (instances, resv_id) = self.compute_api.create(context,
 | 
				
			||||||
            instance_type=instance_types.get_instance_type_by_name(
 | 
					            instance_type=instance_types.get_instance_type_by_name(
 | 
				
			||||||
@@ -1425,7 +1426,7 @@ class CloudController(object):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        fn = supported_attributes.get(attribute)
 | 
					        fn = supported_attributes.get(attribute)
 | 
				
			||||||
        if fn is None:
 | 
					        if fn is None:
 | 
				
			||||||
            raise exception.ApiError(_('attribute not supported: %s')
 | 
					            raise exception.EC2APIError(_('attribute not supported: %s')
 | 
				
			||||||
                                     % attribute)
 | 
					                                     % attribute)
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            image = self._get_image(context, image_id)
 | 
					            image = self._get_image(context, image_id)
 | 
				
			||||||
@@ -1440,14 +1441,15 @@ class CloudController(object):
 | 
				
			|||||||
                               operation_type, **kwargs):
 | 
					                               operation_type, **kwargs):
 | 
				
			||||||
        # TODO(devcamcar): Support users and groups other than 'all'.
 | 
					        # TODO(devcamcar): Support users and groups other than 'all'.
 | 
				
			||||||
        if attribute != 'launchPermission':
 | 
					        if attribute != 'launchPermission':
 | 
				
			||||||
            raise exception.ApiError(_('attribute not supported: %s')
 | 
					            raise exception.EC2APIError(_('attribute not supported: %s')
 | 
				
			||||||
                                     % attribute)
 | 
					                                     % attribute)
 | 
				
			||||||
        if not 'user_group' in kwargs:
 | 
					        if not 'user_group' in kwargs:
 | 
				
			||||||
            raise exception.ApiError(_('user or group not specified'))
 | 
					            raise exception.EC2APIError(_('user or group not specified'))
 | 
				
			||||||
        if len(kwargs['user_group']) != 1 and kwargs['user_group'][0] != 'all':
 | 
					        if len(kwargs['user_group']) != 1 and kwargs['user_group'][0] != 'all':
 | 
				
			||||||
            raise exception.ApiError(_('only group "all" is supported'))
 | 
					            raise exception.EC2APIError(_('only group "all" is supported'))
 | 
				
			||||||
        if not operation_type in ['add', 'remove']:
 | 
					        if not operation_type in ['add', 'remove']:
 | 
				
			||||||
            raise exception.ApiError(_('operation_type must be add or remove'))
 | 
					            msg = _('operation_type must be add or remove')
 | 
				
			||||||
 | 
					            raise exception.EC2APIError(msg)
 | 
				
			||||||
        LOG.audit(_("Updating image %s publicity"), image_id, context=context)
 | 
					        LOG.audit(_("Updating image %s publicity"), image_id, context=context)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
@@ -1504,7 +1506,7 @@ class CloudController(object):
 | 
				
			|||||||
                #                 Or is there any better way?
 | 
					                #                 Or is there any better way?
 | 
				
			||||||
                timeout = 1 * 60 * 60 * 60
 | 
					                timeout = 1 * 60 * 60 * 60
 | 
				
			||||||
                if time.time() > start_time + timeout:
 | 
					                if time.time() > start_time + timeout:
 | 
				
			||||||
                    raise exception.ApiError(
 | 
					                    raise exception.EC2APIError(
 | 
				
			||||||
                        _('Couldn\'t stop instance with in %d sec') % timeout)
 | 
					                        _('Couldn\'t stop instance with in %d sec') % timeout)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        src_image = self._get_image(context, instance['image_ref'])
 | 
					        src_image = self._get_image(context, instance['image_ref'])
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -116,7 +116,7 @@ class CloudpipeController(object):
 | 
				
			|||||||
            except db.NoMoreNetworks:
 | 
					            except db.NoMoreNetworks:
 | 
				
			||||||
                msg = _("Unable to claim IP for VPN instances, ensure it "
 | 
					                msg = _("Unable to claim IP for VPN instances, ensure it "
 | 
				
			||||||
                        "isn't running, and try again in a few minutes")
 | 
					                        "isn't running, and try again in a few minutes")
 | 
				
			||||||
                raise exception.ApiError(msg)
 | 
					                raise exception.HTTPBadRequest(explanation=msg)
 | 
				
			||||||
            instance = self._get_cloudpipe_for_project(ctxt, proj)
 | 
					            instance = self._get_cloudpipe_for_project(ctxt, proj)
 | 
				
			||||||
        return {'instance_id': instance['uuid']}
 | 
					        return {'instance_id': instance['uuid']}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -54,8 +54,8 @@ class ConsoleOutputController(wsgi.Controller):
 | 
				
			|||||||
            output = self.compute_api.get_console_output(context,
 | 
					            output = self.compute_api.get_console_output(context,
 | 
				
			||||||
                                                         instance,
 | 
					                                                         instance,
 | 
				
			||||||
                                                         length)
 | 
					                                                         length)
 | 
				
			||||||
        except exception.ApiError, e:
 | 
					        except exception.NotFound:
 | 
				
			||||||
            raise webob.exc.HTTPBadRequest(explanation=e.message)
 | 
					            raise webob.exc.HTTPNotFound(_('Instance not found'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return {'output': output}
 | 
					        return {'output': output}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -54,10 +54,10 @@ class ConsolesController(wsgi.Controller):
 | 
				
			|||||||
                                                      console_type)
 | 
					                                                      console_type)
 | 
				
			||||||
        except exception.ConsoleTypeInvalid, e:
 | 
					        except exception.ConsoleTypeInvalid, e:
 | 
				
			||||||
            raise webob.exc.HTTPBadRequest(_('Invalid type specification'))
 | 
					            raise webob.exc.HTTPBadRequest(_('Invalid type specification'))
 | 
				
			||||||
        except exception.ApiError, e:
 | 
					 | 
				
			||||||
            raise webob.exc.HTTPBadRequest(explanation=e.message)
 | 
					 | 
				
			||||||
        except exception.NotAuthorized, e:
 | 
					        except exception.NotAuthorized, e:
 | 
				
			||||||
            raise webob.exc.HTTPUnauthorized()
 | 
					            raise webob.exc.HTTPUnauthorized()
 | 
				
			||||||
 | 
					        except exception.NotFound:
 | 
				
			||||||
 | 
					            raise webob.exc.HTTPNotFound(_('Instance not found'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return {'console': {'type': console_type, 'url': output['url']}}
 | 
					        return {'console': {'type': console_type, 'url': output['url']}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -204,14 +204,14 @@ class FloatingIPActionController(wsgi.Controller):
 | 
				
			|||||||
            msg = _("Address not specified")
 | 
					            msg = _("Address not specified")
 | 
				
			||||||
            raise webob.exc.HTTPBadRequest(explanation=msg)
 | 
					            raise webob.exc.HTTPBadRequest(explanation=msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        instance = self.compute_api.get(context, id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            instance = self.compute_api.get(context, id)
 | 
					 | 
				
			||||||
            self.compute_api.associate_floating_ip(context, instance,
 | 
					            self.compute_api.associate_floating_ip(context, instance,
 | 
				
			||||||
                                                   address)
 | 
					                                                   address)
 | 
				
			||||||
        except exception.ApiError, e:
 | 
					        except exception.FixedIpNotFoundForInstance:
 | 
				
			||||||
            raise webob.exc.HTTPBadRequest(explanation=e.message)
 | 
					            msg = _("No fixed ips associated to instance")
 | 
				
			||||||
        except exception.NotAuthorized, e:
 | 
					            raise webob.exc.HTTPBadRequest(explanation=msg)
 | 
				
			||||||
            raise webob.exc.HTTPUnauthorized()
 | 
					 | 
				
			||||||
        except rpc.RemoteError:
 | 
					        except rpc.RemoteError:
 | 
				
			||||||
            msg = _("Associate floating ip failed")
 | 
					            msg = _("Associate floating ip failed")
 | 
				
			||||||
            raise webob.exc.HTTPInternalServerError(explanation=msg)
 | 
					            raise webob.exc.HTTPInternalServerError(explanation=msg)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,35 +31,29 @@ class ServerStartStopActionController(wsgi.Controller):
 | 
				
			|||||||
        super(ServerStartStopActionController, self).__init__(*args, **kwargs)
 | 
					        super(ServerStartStopActionController, self).__init__(*args, **kwargs)
 | 
				
			||||||
        self.compute_api = compute.API()
 | 
					        self.compute_api = compute.API()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _get_instance(self, context, instance_uuid):
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            return self.compute_api.get(context, instance_uuid)
 | 
				
			||||||
 | 
					        except exception.NotFound:
 | 
				
			||||||
 | 
					            msg = _("Instance not found")
 | 
				
			||||||
 | 
					            raise webob.exc.HTTPNotFound(explanation=msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @wsgi.action('os-start')
 | 
					    @wsgi.action('os-start')
 | 
				
			||||||
    def _start_server(self, req, id, body):
 | 
					    def _start_server(self, req, id, body):
 | 
				
			||||||
        """Start an instance. """
 | 
					        """Start an instance. """
 | 
				
			||||||
        context = req.environ['nova.context']
 | 
					        context = req.environ['nova.context']
 | 
				
			||||||
 | 
					        LOG.debug(_("start instance %r"), id)
 | 
				
			||||||
        try:
 | 
					        instance = self._get_instance(context, id)
 | 
				
			||||||
            LOG.debug(_("start instance %r"), id)
 | 
					        self.compute_api.start(context, instance)
 | 
				
			||||||
            instance = self.compute_api.get(context, id)
 | 
					 | 
				
			||||||
            self.compute_api.start(context, instance)
 | 
					 | 
				
			||||||
        except exception.ApiError, e:
 | 
					 | 
				
			||||||
            raise webob.exc.HTTPBadRequest(explanation=e.message)
 | 
					 | 
				
			||||||
        except exception.NotAuthorized, e:
 | 
					 | 
				
			||||||
            raise webob.exc.HTTPUnauthorized()
 | 
					 | 
				
			||||||
        return webob.Response(status_int=202)
 | 
					        return webob.Response(status_int=202)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @wsgi.action('os-stop')
 | 
					    @wsgi.action('os-stop')
 | 
				
			||||||
    def _stop_server(self, req, id, body):
 | 
					    def _stop_server(self, req, id, body):
 | 
				
			||||||
        """Stop an instance."""
 | 
					        """Stop an instance."""
 | 
				
			||||||
        context = req.environ['nova.context']
 | 
					        context = req.environ['nova.context']
 | 
				
			||||||
 | 
					        LOG.debug(_("stop instance %r"), id)
 | 
				
			||||||
        try:
 | 
					        instance = self._get_instance(context, id)
 | 
				
			||||||
            LOG.debug(_("stop instance %r"), id)
 | 
					        self.compute_api.stop(context, instance)
 | 
				
			||||||
            instance = self.compute_api.get(context, id)
 | 
					 | 
				
			||||||
            self.compute_api.stop(context, instance)
 | 
					 | 
				
			||||||
        except exception.ApiError, e:
 | 
					 | 
				
			||||||
            raise webob.exc.HTTPBadRequest(explanation=e.message)
 | 
					 | 
				
			||||||
        except exception.NotAuthorized, e:
 | 
					 | 
				
			||||||
            raise webob.exc.HTTPUnauthorized()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return webob.Response(status_int=202)
 | 
					        return webob.Response(status_int=202)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -100,7 +100,7 @@ class VolumeTypesController(object):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            vol_type = volume_types.get_volume_type(context, id)
 | 
					            vol_type = volume_types.get_volume_type(context, id)
 | 
				
			||||||
        except exception.NotFound or exception.ApiError:
 | 
					        except exception.NotFound:
 | 
				
			||||||
            raise exc.HTTPNotFound()
 | 
					            raise exc.HTTPNotFound()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return {'volume_type': vol_type}
 | 
					        return {'volume_type': vol_type}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -165,7 +165,7 @@ class Controller(object):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def _handle_quota_error(self, error):
 | 
					    def _handle_quota_error(self, error):
 | 
				
			||||||
        """Reraise quota errors as api-specific http exceptions."""
 | 
					        """Reraise quota errors as api-specific http exceptions."""
 | 
				
			||||||
        if error.code == "MetadataLimitExceeded":
 | 
					        if error.kwargs['code'] == "MetadataLimitExceeded":
 | 
				
			||||||
            raise exc.HTTPRequestEntityTooLarge(explanation=error.message,
 | 
					            raise exc.HTTPRequestEntityTooLarge(explanation=error.message,
 | 
				
			||||||
                                                headers={'Retry-After': 0})
 | 
					                                                headers={'Retry-After': 0})
 | 
				
			||||||
        raise error
 | 
					        raise error
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -496,12 +496,8 @@ class Controller(wsgi.Controller):
 | 
				
			|||||||
            "InstanceLimitExceeded": error.message,
 | 
					            "InstanceLimitExceeded": error.message,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        expl = code_mappings.get(error.code)
 | 
					        expl = code_mappings.get(error.kwargs['code'], error.message)
 | 
				
			||||||
        if expl:
 | 
					        raise exc.HTTPRequestEntityTooLarge(explanation=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})
 | 
					                                            headers={'Retry-After': 0})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _validate_server_name(self, value):
 | 
					    def _validate_server_name(self, value):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -64,7 +64,7 @@ class VolumeTypesController(object):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            vol_type = volume_types.get_volume_type(context, id)
 | 
					            vol_type = volume_types.get_volume_type(context, id)
 | 
				
			||||||
        except exception.NotFound or exception.ApiError:
 | 
					        except exception.NotFound:
 | 
				
			||||||
            raise exc.HTTPNotFound()
 | 
					            raise exc.HTTPNotFound()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return {'volume_type': vol_type}
 | 
					        return {'volume_type': vol_type}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -136,8 +136,8 @@ class API(base.Base):
 | 
				
			|||||||
            content_limit = quota.allowed_injected_file_content_bytes(
 | 
					            content_limit = quota.allowed_injected_file_content_bytes(
 | 
				
			||||||
                                                    context, len(content))
 | 
					                                                    context, len(content))
 | 
				
			||||||
            if len(content) > content_limit:
 | 
					            if len(content) > content_limit:
 | 
				
			||||||
                raise exception.QuotaError(
 | 
					                code = "OnsetFileContentLimitExceeded"
 | 
				
			||||||
                                  code="OnsetFileContentLimitExceeded")
 | 
					                raise exception.QuotaError(code=code)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _check_metadata_properties_quota(self, context, metadata=None):
 | 
					    def _check_metadata_properties_quota(self, context, metadata=None):
 | 
				
			||||||
        """Enforce quota limits on metadata properties."""
 | 
					        """Enforce quota limits on metadata properties."""
 | 
				
			||||||
@@ -150,7 +150,7 @@ class API(base.Base):
 | 
				
			|||||||
            msg = _("Quota exceeded for %(pid)s, tried to set "
 | 
					            msg = _("Quota exceeded for %(pid)s, tried to set "
 | 
				
			||||||
                    "%(num_metadata)s metadata properties") % locals()
 | 
					                    "%(num_metadata)s metadata properties") % locals()
 | 
				
			||||||
            LOG.warn(msg)
 | 
					            LOG.warn(msg)
 | 
				
			||||||
            raise exception.QuotaError(msg, "MetadataLimitExceeded")
 | 
					            raise exception.QuotaError(code="MetadataLimitExceeded")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Because metadata is stored in the DB, we hard-code the size limits
 | 
					        # Because metadata is stored in the DB, we hard-code the size limits
 | 
				
			||||||
        # In future, we may support more variable length strings, so we act
 | 
					        # In future, we may support more variable length strings, so we act
 | 
				
			||||||
@@ -161,7 +161,7 @@ class API(base.Base):
 | 
				
			|||||||
                msg = _("Quota exceeded for %(pid)s, metadata property "
 | 
					                msg = _("Quota exceeded for %(pid)s, metadata property "
 | 
				
			||||||
                        "key or value too long") % locals()
 | 
					                        "key or value too long") % locals()
 | 
				
			||||||
                LOG.warn(msg)
 | 
					                LOG.warn(msg)
 | 
				
			||||||
                raise exception.QuotaError(msg, "MetadataLimitExceeded")
 | 
					                raise exception.QuotaError(code="MetadataLimitExceeded")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _check_requested_networks(self, context, requested_networks):
 | 
					    def _check_requested_networks(self, context, requested_networks):
 | 
				
			||||||
        """ Check if the networks requested belongs to the project
 | 
					        """ Check if the networks requested belongs to the project
 | 
				
			||||||
@@ -218,7 +218,7 @@ class API(base.Base):
 | 
				
			|||||||
            else:
 | 
					            else:
 | 
				
			||||||
                message = _("Instance quota exceeded. You can only run %s "
 | 
					                message = _("Instance quota exceeded. You can only run %s "
 | 
				
			||||||
                            "more instances of this type.") % num_instances
 | 
					                            "more instances of this type.") % num_instances
 | 
				
			||||||
            raise exception.QuotaError(message, "InstanceLimitExceeded")
 | 
					            raise exception.QuotaError(code="InstanceLimitExceeded")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._check_metadata_properties_quota(context, metadata)
 | 
					        self._check_metadata_properties_quota(context, metadata)
 | 
				
			||||||
        self._check_injected_file_quota(context, injected_files)
 | 
					        self._check_injected_file_quota(context, injected_files)
 | 
				
			||||||
@@ -1631,8 +1631,7 @@ class API(base.Base):
 | 
				
			|||||||
    def attach_volume(self, context, instance, volume_id, device):
 | 
					    def attach_volume(self, context, instance, volume_id, device):
 | 
				
			||||||
        """Attach an existing volume to an existing instance."""
 | 
					        """Attach an existing volume to an existing instance."""
 | 
				
			||||||
        if not re.match("^/dev/x{0,1}[a-z]d[a-z]+$", device):
 | 
					        if not re.match("^/dev/x{0,1}[a-z]d[a-z]+$", device):
 | 
				
			||||||
            raise exception.ApiError(_("Invalid device specified: %s. "
 | 
					            raise exception.InvalidDevicePath(path=device)
 | 
				
			||||||
                                     "Example device: /dev/vdb") % device)
 | 
					 | 
				
			||||||
        volume = self.volume_api.get(context, volume_id)
 | 
					        volume = self.volume_api.get(context, volume_id)
 | 
				
			||||||
        self.volume_api.check_attach(context, volume)
 | 
					        self.volume_api.check_attach(context, volume)
 | 
				
			||||||
        params = {"volume_id": volume_id,
 | 
					        params = {"volume_id": volume_id,
 | 
				
			||||||
@@ -1647,7 +1646,7 @@ class API(base.Base):
 | 
				
			|||||||
        """Detach a volume from an instance."""
 | 
					        """Detach a volume from an instance."""
 | 
				
			||||||
        instance = self.db.volume_get_instance(context.elevated(), volume_id)
 | 
					        instance = self.db.volume_get_instance(context.elevated(), volume_id)
 | 
				
			||||||
        if not instance:
 | 
					        if not instance:
 | 
				
			||||||
            raise exception.ApiError(_("Volume isn't attached to anything!"))
 | 
					            raise exception.VolumeUnattached(volume_id=volume_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        check_policy(context, 'detach_volume', instance)
 | 
					        check_policy(context, 'detach_volume', instance)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1672,30 +1671,29 @@ class API(base.Base):
 | 
				
			|||||||
        # in its info, if this changes, the next few lines will need to
 | 
					        # in its info, if this changes, the next few lines will need to
 | 
				
			||||||
        # accommodate the info containing floating as well as fixed ip
 | 
					        # accommodate the info containing floating as well as fixed ip
 | 
				
			||||||
        # addresses
 | 
					        # addresses
 | 
				
			||||||
 | 
					 | 
				
			||||||
        fail_bag = _('instance |%s| has no fixed ips. '
 | 
					 | 
				
			||||||
                     'unable to associate floating ip') % instance_uuid
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        nw_info = self.network_api.get_instance_nw_info(context.elevated(),
 | 
					        nw_info = self.network_api.get_instance_nw_info(context.elevated(),
 | 
				
			||||||
                                                        instance)
 | 
					                                                        instance)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if nw_info:
 | 
					        if not nw_info:
 | 
				
			||||||
            ips = [ip for ip in nw_info[0].fixed_ips()]
 | 
					            raise exception.FixedIpNotFoundForInstance(
 | 
				
			||||||
 | 
					                    instance_id=instance_uuid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # TODO(tr3buchet): this will associate the floating IP with the
 | 
					        ips = [ip for ip in nw_info[0].fixed_ips()]
 | 
				
			||||||
            # first # fixed_ip (lowest id) an instance has. This should be
 | 
					
 | 
				
			||||||
            # changed to # support specifying a particular fixed_ip if
 | 
					        if not ips:
 | 
				
			||||||
            # multiple exist.
 | 
					            raise exception.FixedIpNotFoundForInstance(
 | 
				
			||||||
            if not ips:
 | 
					                    instance_id=instance_uuid)
 | 
				
			||||||
                raise exception.ApiError(fail_bag)
 | 
					
 | 
				
			||||||
            if len(ips) > 1:
 | 
					        # TODO(tr3buchet): this will associate the floating IP with the
 | 
				
			||||||
                LOG.warning(_('multiple fixedips exist, using the first: %s'),
 | 
					        # first fixed_ip (lowest id) an instance has. This should be
 | 
				
			||||||
                                                             ips[0]['address'])
 | 
					        # changed to support specifying a particular fixed_ip if
 | 
				
			||||||
            self.network_api.associate_floating_ip(context,
 | 
					        # multiple exist.
 | 
				
			||||||
                                               floating_address=address,
 | 
					        if len(ips) > 1:
 | 
				
			||||||
                                               fixed_address=ips[0]['address'])
 | 
					            msg = _('multiple fixedips exist, using the first: %s')
 | 
				
			||||||
            return
 | 
					            LOG.warning(msg, ips[0]['address'])
 | 
				
			||||||
        raise exception.ApiError(fail_bag)
 | 
					
 | 
				
			||||||
 | 
					        self.network_api.associate_floating_ip(context,
 | 
				
			||||||
 | 
					                floating_address=address, fixed_address=ips[0]['address'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @wrap_check_policy
 | 
					    @wrap_check_policy
 | 
				
			||||||
    def get_instance_metadata(self, context, instance):
 | 
					    def get_instance_metadata(self, context, instance):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -72,9 +72,7 @@ def create(name, memory, vcpus, root_gb, ephemeral_gb, flavorid, swap=None,
 | 
				
			|||||||
        return db.instance_type_create(context.get_admin_context(), kwargs)
 | 
					        return db.instance_type_create(context.get_admin_context(), kwargs)
 | 
				
			||||||
    except exception.DBError, e:
 | 
					    except exception.DBError, e:
 | 
				
			||||||
        LOG.exception(_('DB error: %s') % e)
 | 
					        LOG.exception(_('DB error: %s') % e)
 | 
				
			||||||
        msg = _("Cannot create instance_type with name %(name)s and "
 | 
					        raise exception.InstanceTypeCreateFailed()
 | 
				
			||||||
                "flavorid %(flavorid)s") % locals()
 | 
					 | 
				
			||||||
        raise exception.ApiError(msg)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def destroy(name):
 | 
					def destroy(name):
 | 
				
			||||||
@@ -106,10 +104,7 @@ get_all_flavors = get_all_types
 | 
				
			|||||||
def get_default_instance_type():
 | 
					def get_default_instance_type():
 | 
				
			||||||
    """Get the default instance type."""
 | 
					    """Get the default instance type."""
 | 
				
			||||||
    name = FLAGS.default_instance_type
 | 
					    name = FLAGS.default_instance_type
 | 
				
			||||||
    try:
 | 
					    return get_instance_type_by_name(name)
 | 
				
			||||||
        return get_instance_type_by_name(name)
 | 
					 | 
				
			||||||
    except exception.InstanceTypeNotFound as e:
 | 
					 | 
				
			||||||
        raise exception.ApiError(e)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_instance_type(instance_type_id):
 | 
					def get_instance_type(instance_type_id):
 | 
				
			||||||
@@ -118,10 +113,7 @@ def get_instance_type(instance_type_id):
 | 
				
			|||||||
        return get_default_instance_type()
 | 
					        return get_default_instance_type()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ctxt = context.get_admin_context()
 | 
					    ctxt = context.get_admin_context()
 | 
				
			||||||
    try:
 | 
					    return db.instance_type_get(ctxt, instance_type_id)
 | 
				
			||||||
        return db.instance_type_get(ctxt, instance_type_id)
 | 
					 | 
				
			||||||
    except exception.InstanceTypeNotFound as e:
 | 
					 | 
				
			||||||
        raise exception.ApiError(e)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_instance_type_by_name(name):
 | 
					def get_instance_type_by_name(name):
 | 
				
			||||||
@@ -130,11 +122,7 @@ def get_instance_type_by_name(name):
 | 
				
			|||||||
        return get_default_instance_type()
 | 
					        return get_default_instance_type()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ctxt = context.get_admin_context()
 | 
					    ctxt = context.get_admin_context()
 | 
				
			||||||
 | 
					    return db.instance_type_get_by_name(ctxt, name)
 | 
				
			||||||
    try:
 | 
					 | 
				
			||||||
        return db.instance_type_get_by_name(ctxt, name)
 | 
					 | 
				
			||||||
    except exception.InstanceTypeNotFound as e:
 | 
					 | 
				
			||||||
        raise exception.ApiError(e)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# TODO(termie): flavor-specific code should probably be in the API that uses
 | 
					# TODO(termie): flavor-specific code should probably be in the API that uses
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -80,7 +80,7 @@ class Error(Exception):
 | 
				
			|||||||
        super(Error, self).__init__(message)
 | 
					        super(Error, self).__init__(message)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ApiError(Error):
 | 
					class EC2APIError(Error):
 | 
				
			||||||
    def __init__(self, message='Unknown', code=None):
 | 
					    def __init__(self, message='Unknown', code=None):
 | 
				
			||||||
        self.msg = message
 | 
					        self.msg = message
 | 
				
			||||||
        self.code = code
 | 
					        self.code = code
 | 
				
			||||||
@@ -88,7 +88,7 @@ class ApiError(Error):
 | 
				
			|||||||
            outstr = '%s: %s' % (code, message)
 | 
					            outstr = '%s: %s' % (code, message)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            outstr = '%s' % message
 | 
					            outstr = '%s' % message
 | 
				
			||||||
        super(ApiError, self).__init__(outstr)
 | 
					        super(EC2APIError, self).__init__(outstr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DBError(Error):
 | 
					class DBError(Error):
 | 
				
			||||||
@@ -223,6 +223,14 @@ class Invalid(NovaException):
 | 
				
			|||||||
    message = _("Unacceptable parameters.")
 | 
					    message = _("Unacceptable parameters.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class InvalidSnapshot(Invalid):
 | 
				
			||||||
 | 
					    message = _("Invalid snapshot") + ": %(reason)s"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class VolumeUnattached(Invalid):
 | 
				
			||||||
 | 
					    message = _("Volume %(volume_id)s is not attached to anything")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class InvalidKeypair(Invalid):
 | 
					class InvalidKeypair(Invalid):
 | 
				
			||||||
    message = _("Keypair data is invalid")
 | 
					    message = _("Keypair data is invalid")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -248,7 +256,11 @@ class InvalidInstanceType(Invalid):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class InvalidVolumeType(Invalid):
 | 
					class InvalidVolumeType(Invalid):
 | 
				
			||||||
    message = _("Invalid volume type %(volume_type)s.")
 | 
					    message = _("Invalid volume type") + ": %(reason)s"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class InvalidVolume(Invalid):
 | 
				
			||||||
 | 
					    message = _("Invalid volume") + ": %(reason)s"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class InvalidPortRange(Invalid):
 | 
					class InvalidPortRange(Invalid):
 | 
				
			||||||
@@ -930,9 +942,8 @@ class WillNotSchedule(NovaException):
 | 
				
			|||||||
    message = _("Host %(host)s is not up or doesn't exist.")
 | 
					    message = _("Host %(host)s is not up or doesn't exist.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class QuotaError(ApiError):
 | 
					class QuotaError(NovaException):
 | 
				
			||||||
    """Quota Exceeded."""
 | 
					    message = _("Quota exceeded") + ": code=%(code)s"
 | 
				
			||||||
    pass
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AggregateNotFound(NotFound):
 | 
					class AggregateNotFound(NotFound):
 | 
				
			||||||
@@ -962,3 +973,24 @@ class AggregateHostExists(Duplicate):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class DuplicateSfVolumeNames(Duplicate):
 | 
					class DuplicateSfVolumeNames(Duplicate):
 | 
				
			||||||
    message = _("Detected more than one volume with name %(vol_name)")
 | 
					    message = _("Detected more than one volume with name %(vol_name)")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class VolumeTypeCreateFailed(NovaException):
 | 
				
			||||||
 | 
					    message = _("Cannot create volume_type with "
 | 
				
			||||||
 | 
					                "name %(name)s and specs %(extra_specs)s")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class InstanceTypeCreateFailed(NovaException):
 | 
				
			||||||
 | 
					    message = _("Unable to create instance type")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SolidFireAPIException(NovaException):
 | 
				
			||||||
 | 
					    message = _("Bad response from SolidFire API")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SolidFireAPIStatusException(SolidFireAPIException):
 | 
				
			||||||
 | 
					    message = _("Error in SolidFire API response: status=%(status)s")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SolidFireAPIDataException(SolidFireAPIException):
 | 
				
			||||||
 | 
					    message = _("Error in SolidFire API response: data=%(data)s")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -368,11 +368,9 @@ class FloatingIP(object):
 | 
				
			|||||||
        # NOTE(tr3buchet): all network hosts in zone now use the same pool
 | 
					        # NOTE(tr3buchet): all network hosts in zone now use the same pool
 | 
				
			||||||
        LOG.debug("QUOTA: %s" % quota.allowed_floating_ips(context, 1))
 | 
					        LOG.debug("QUOTA: %s" % quota.allowed_floating_ips(context, 1))
 | 
				
			||||||
        if quota.allowed_floating_ips(context, 1) < 1:
 | 
					        if quota.allowed_floating_ips(context, 1) < 1:
 | 
				
			||||||
            LOG.warn(_('Quota exceeded for %s, tried to allocate '
 | 
					            LOG.warn(_('Quota exceeded for %s, tried to allocate address'),
 | 
				
			||||||
                       'address'),
 | 
					 | 
				
			||||||
                     context.project_id)
 | 
					                     context.project_id)
 | 
				
			||||||
            raise exception.QuotaError(_('Address quota exceeded. You cannot '
 | 
					            raise exception.QuotaError(code='AddressLimitExceeded')
 | 
				
			||||||
                                     'allocate any more addresses'))
 | 
					 | 
				
			||||||
        pool = pool or FLAGS.default_floating_pool
 | 
					        pool = pool or FLAGS.default_floating_pool
 | 
				
			||||||
        return self.db.floating_ip_allocate_address(context,
 | 
					        return self.db.floating_ip_allocate_address(context,
 | 
				
			||||||
                                                    project_id,
 | 
					                                                    project_id,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -285,7 +285,7 @@ class CloudTestCase(test.TestCase):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def test_delete_security_group_no_params(self):
 | 
					    def test_delete_security_group_no_params(self):
 | 
				
			||||||
        delete = self.cloud.delete_security_group
 | 
					        delete = self.cloud.delete_security_group
 | 
				
			||||||
        self.assertRaises(exception.ApiError, delete, self.context)
 | 
					        self.assertRaises(exception.EC2APIError, delete, self.context)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_authorize_security_group_ingress(self):
 | 
					    def test_authorize_security_group_ingress(self):
 | 
				
			||||||
        kwargs = {'project_id': self.context.project_id, 'name': 'test'}
 | 
					        kwargs = {'project_id': self.context.project_id, 'name': 'test'}
 | 
				
			||||||
@@ -415,12 +415,12 @@ class CloudTestCase(test.TestCase):
 | 
				
			|||||||
                                       {'project_id': self.context.project_id,
 | 
					                                       {'project_id': self.context.project_id,
 | 
				
			||||||
                                        'name': 'test'})
 | 
					                                        'name': 'test'})
 | 
				
			||||||
        authz = self.cloud.authorize_security_group_ingress
 | 
					        authz = self.cloud.authorize_security_group_ingress
 | 
				
			||||||
        self.assertRaises(exception.ApiError, authz, self.context, 'test')
 | 
					        self.assertRaises(exception.EC2APIError, authz, self.context, 'test')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_authorize_security_group_ingress_missing_group_name_or_id(self):
 | 
					    def test_authorize_security_group_ingress_missing_group_name_or_id(self):
 | 
				
			||||||
        kwargs = {'project_id': self.context.project_id, 'name': 'test'}
 | 
					        kwargs = {'project_id': self.context.project_id, 'name': 'test'}
 | 
				
			||||||
        authz = self.cloud.authorize_security_group_ingress
 | 
					        authz = self.cloud.authorize_security_group_ingress
 | 
				
			||||||
        self.assertRaises(exception.ApiError, authz, self.context, **kwargs)
 | 
					        self.assertRaises(exception.EC2APIError, authz, self.context, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_authorize_security_group_ingress_already_exists(self):
 | 
					    def test_authorize_security_group_ingress_already_exists(self):
 | 
				
			||||||
        kwargs = {'project_id': self.context.project_id, 'name': 'test'}
 | 
					        kwargs = {'project_id': self.context.project_id, 'name': 'test'}
 | 
				
			||||||
@@ -428,13 +428,14 @@ class CloudTestCase(test.TestCase):
 | 
				
			|||||||
        authz = self.cloud.authorize_security_group_ingress
 | 
					        authz = self.cloud.authorize_security_group_ingress
 | 
				
			||||||
        kwargs = {'to_port': '999', 'from_port': '999', 'ip_protocol': 'tcp'}
 | 
					        kwargs = {'to_port': '999', 'from_port': '999', 'ip_protocol': 'tcp'}
 | 
				
			||||||
        authz(self.context, group_name=sec['name'], **kwargs)
 | 
					        authz(self.context, group_name=sec['name'], **kwargs)
 | 
				
			||||||
        self.assertRaises(exception.ApiError, authz, self.context,
 | 
					        self.assertRaises(exception.EC2APIError, authz, self.context,
 | 
				
			||||||
                          group_name=sec['name'], **kwargs)
 | 
					                          group_name=sec['name'], **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_revoke_security_group_ingress_missing_group_name_or_id(self):
 | 
					    def test_revoke_security_group_ingress_missing_group_name_or_id(self):
 | 
				
			||||||
        kwargs = {'to_port': '999', 'from_port': '999', 'ip_protocol': 'tcp'}
 | 
					        kwargs = {'to_port': '999', 'from_port': '999', 'ip_protocol': 'tcp'}
 | 
				
			||||||
        revoke = self.cloud.revoke_security_group_ingress
 | 
					        revoke = self.cloud.revoke_security_group_ingress
 | 
				
			||||||
        self.assertRaises(exception.ApiError, revoke, self.context, **kwargs)
 | 
					        self.assertRaises(exception.EC2APIError, revoke,
 | 
				
			||||||
 | 
					                self.context, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_describe_volumes(self):
 | 
					    def test_describe_volumes(self):
 | 
				
			||||||
        """Makes sure describe_volumes works and filters results."""
 | 
					        """Makes sure describe_volumes works and filters results."""
 | 
				
			||||||
@@ -1315,7 +1316,7 @@ class CloudTestCase(test.TestCase):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        self.stubs.UnsetAll()
 | 
					        self.stubs.UnsetAll()
 | 
				
			||||||
        self.stubs.Set(fake._FakeImageService, 'show', fake_show_no_state)
 | 
					        self.stubs.Set(fake._FakeImageService, 'show', fake_show_no_state)
 | 
				
			||||||
        self.assertRaises(exception.ApiError, run_instances,
 | 
					        self.assertRaises(exception.EC2APIError, run_instances,
 | 
				
			||||||
                          self.context, **kwargs)
 | 
					                          self.context, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_run_instances_image_state_invalid(self):
 | 
					    def test_run_instances_image_state_invalid(self):
 | 
				
			||||||
@@ -1334,7 +1335,7 @@ class CloudTestCase(test.TestCase):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        self.stubs.UnsetAll()
 | 
					        self.stubs.UnsetAll()
 | 
				
			||||||
        self.stubs.Set(fake._FakeImageService, 'show', fake_show_decrypt)
 | 
					        self.stubs.Set(fake._FakeImageService, 'show', fake_show_decrypt)
 | 
				
			||||||
        self.assertRaises(exception.ApiError, run_instances,
 | 
					        self.assertRaises(exception.EC2APIError, run_instances,
 | 
				
			||||||
                          self.context, **kwargs)
 | 
					                          self.context, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_run_instances_image_status_active(self):
 | 
					    def test_run_instances_image_status_active(self):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,7 +40,7 @@ def fake_get(self, context, instance_uuid):
 | 
				
			|||||||
    return {'uuid': instance_uuid}
 | 
					    return {'uuid': instance_uuid}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def fake_get_not_found(self, context, instance_uuid):
 | 
					def fake_get_not_found(*args, **kwargs):
 | 
				
			||||||
    raise exception.NotFound()
 | 
					    raise exception.NotFound()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -86,6 +86,17 @@ class ConsoleOutputExtensionTest(test.TestCase):
 | 
				
			|||||||
        res = req.get_response(fakes.wsgi_app())
 | 
					        res = req.get_response(fakes.wsgi_app())
 | 
				
			||||||
        self.assertEqual(res.status_int, 404)
 | 
					        self.assertEqual(res.status_int, 404)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_get_text_console_no_instance_on_get_output(self):
 | 
				
			||||||
 | 
					        self.stubs.Set(compute.API, 'get_console_output', fake_get_not_found)
 | 
				
			||||||
 | 
					        body = {'os-getConsoleOutput': {}}
 | 
				
			||||||
 | 
					        req = webob.Request.blank('/v2/fake/servers/1/action')
 | 
				
			||||||
 | 
					        req.method = "POST"
 | 
				
			||||||
 | 
					        req.body = json.dumps(body)
 | 
				
			||||||
 | 
					        req.headers["content-type"] = "application/json"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        res = req.get_response(fakes.wsgi_app())
 | 
				
			||||||
 | 
					        self.assertEqual(res.status_int, 404)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_get_text_console_bad_body(self):
 | 
					    def test_get_text_console_bad_body(self):
 | 
				
			||||||
        body = {}
 | 
					        body = {}
 | 
				
			||||||
        req = webob.Request.blank('/v2/fake/servers/1/action')
 | 
					        req = webob.Request.blank('/v2/fake/servers/1/action')
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,7 +36,7 @@ def fake_get(self, context, instance_uuid):
 | 
				
			|||||||
    return {'uuid': instance_uuid}
 | 
					    return {'uuid': instance_uuid}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def fake_get_not_found(self, context, instance_uuid):
 | 
					def fake_get_not_found(*args, **kwargs):
 | 
				
			||||||
    raise exception.NotFound()
 | 
					    raise exception.NotFound()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -83,6 +83,17 @@ class ConsolesExtensionTest(test.TestCase):
 | 
				
			|||||||
        res = req.get_response(fakes.wsgi_app())
 | 
					        res = req.get_response(fakes.wsgi_app())
 | 
				
			||||||
        self.assertEqual(res.status_int, 404)
 | 
					        self.assertEqual(res.status_int, 404)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_get_vnc_console_no_instance_on_console_get(self):
 | 
				
			||||||
 | 
					        self.stubs.Set(compute.API, 'get_vnc_console', fake_get_not_found)
 | 
				
			||||||
 | 
					        body = {'os-getVNCConsole': {'type': 'novnc'}}
 | 
				
			||||||
 | 
					        req = webob.Request.blank('/v2/fake/servers/1/action')
 | 
				
			||||||
 | 
					        req.method = "POST"
 | 
				
			||||||
 | 
					        req.body = json.dumps(body)
 | 
				
			||||||
 | 
					        req.headers["content-type"] = "application/json"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        res = req.get_response(fakes.wsgi_app())
 | 
				
			||||||
 | 
					        self.assertEqual(res.status_int, 404)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_get_vnc_console_invalid_type(self):
 | 
					    def test_get_vnc_console_invalid_type(self):
 | 
				
			||||||
        self.stubs.Set(compute.API, 'get', fake_get)
 | 
					        self.stubs.Set(compute.API, 'get', fake_get)
 | 
				
			||||||
        body = {'os-getVNCConsole': {'type': 'invalid'}}
 | 
					        body = {'os-getVNCConsole': {'type': 'invalid'}}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,11 +13,12 @@
 | 
				
			|||||||
#    under the License.
 | 
					#    under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import unittest
 | 
					import unittest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import mox
 | 
					import mox
 | 
				
			||||||
 | 
					import webob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from nova.api.openstack.compute.contrib import server_start_stop
 | 
					from nova.api.openstack.compute.contrib import server_start_stop
 | 
				
			||||||
from nova import context
 | 
					from nova import context
 | 
				
			||||||
from nova import exception
 | 
					 | 
				
			||||||
from nova import compute
 | 
					from nova import compute
 | 
				
			||||||
from nova import test
 | 
					from nova import test
 | 
				
			||||||
from nova.tests.api.openstack import fakes
 | 
					from nova.tests.api.openstack import fakes
 | 
				
			||||||
@@ -60,13 +61,13 @@ class ServerStartStopTest(test.TestCase):
 | 
				
			|||||||
    def test_start_with_bogus_id(self):
 | 
					    def test_start_with_bogus_id(self):
 | 
				
			||||||
        req = fakes.HTTPRequest.blank('/v2/fake/servers/test_inst/action')
 | 
					        req = fakes.HTTPRequest.blank('/v2/fake/servers/test_inst/action')
 | 
				
			||||||
        body = dict(start="")
 | 
					        body = dict(start="")
 | 
				
			||||||
        self.assertRaises(exception.InstanceNotFound,
 | 
					        self.assertRaises(webob.exc.HTTPNotFound,
 | 
				
			||||||
            self.controller._start_server, req, 'test_inst', body)
 | 
					            self.controller._start_server, req, 'test_inst', body)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_stop_with_bogus_id(self):
 | 
					    def test_stop_with_bogus_id(self):
 | 
				
			||||||
        req = fakes.HTTPRequest.blank('/v2/fake/servers/test_inst/action')
 | 
					        req = fakes.HTTPRequest.blank('/v2/fake/servers/test_inst/action')
 | 
				
			||||||
        body = dict(start="")
 | 
					        body = dict(start="")
 | 
				
			||||||
        self.assertRaises(exception.InstanceNotFound,
 | 
					        self.assertRaises(webob.exc.HTTPNotFound,
 | 
				
			||||||
            self.controller._stop_server, req, 'test_inst', body)
 | 
					            self.controller._stop_server, req, 'test_inst', body)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,14 +13,12 @@
 | 
				
			|||||||
#    License for the specific language governing permissions and limitations
 | 
					#    License for the specific language governing permissions and limitations
 | 
				
			||||||
#    under the License.
 | 
					#    under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from nova import context
 | 
					 | 
				
			||||||
from nova import db
 | 
					from nova import db
 | 
				
			||||||
from nova import exception
 | 
					from nova import exception
 | 
				
			||||||
from nova import flags
 | 
					from nova import flags
 | 
				
			||||||
from nova import log as logging
 | 
					from nova import log as logging
 | 
				
			||||||
from nova import rpc
 | 
					from nova import rpc
 | 
				
			||||||
from nova.scheduler import vsa as vsa_sched
 | 
					from nova.scheduler import vsa as vsa_sched
 | 
				
			||||||
from nova import test
 | 
					 | 
				
			||||||
from nova.tests.scheduler import test_scheduler
 | 
					from nova.tests.scheduler import test_scheduler
 | 
				
			||||||
from nova import utils
 | 
					from nova import utils
 | 
				
			||||||
from nova.volume import volume_types
 | 
					from nova.volume import volume_types
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -176,5 +176,5 @@ class SolidFireVolumeTestCase(test.TestCase):
 | 
				
			|||||||
    def test_get_cluster_info_fail(self):
 | 
					    def test_get_cluster_info_fail(self):
 | 
				
			||||||
        SFID._issue_api_request = self.fake_issue_api_request_fails
 | 
					        SFID._issue_api_request = self.fake_issue_api_request_fails
 | 
				
			||||||
        sfv = SFID()
 | 
					        sfv = SFID()
 | 
				
			||||||
        self.assertRaises(exception.ApiError,
 | 
					        self.assertRaises(exception.SolidFireAPIException,
 | 
				
			||||||
                          sfv._get_cluster_info)
 | 
					                          sfv._get_cluster_info)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2357,7 +2357,7 @@ class ComputeAPITestCase(BaseTestCase):
 | 
				
			|||||||
        address = '0.1.2.3'
 | 
					        address = '0.1.2.3'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.compute.run_instance(self.context, instance_uuid)
 | 
					        self.compute.run_instance(self.context, instance_uuid)
 | 
				
			||||||
        self.assertRaises(exception.ApiError,
 | 
					        self.assertRaises(exception.FixedIpNotFoundForInstance,
 | 
				
			||||||
                          self.compute_api.associate_floating_ip,
 | 
					                          self.compute_api.associate_floating_ip,
 | 
				
			||||||
                          self.context,
 | 
					                          self.context,
 | 
				
			||||||
                          instance,
 | 
					                          instance,
 | 
				
			||||||
@@ -2967,7 +2967,7 @@ class ComputeAPITestCase(BaseTestCase):
 | 
				
			|||||||
        self.compute_api.delete(self.context, instance)
 | 
					        self.compute_api.delete(self.context, instance)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_attach_volume_invalid(self):
 | 
					    def test_attach_volume_invalid(self):
 | 
				
			||||||
        self.assertRaises(exception.ApiError,
 | 
					        self.assertRaises(exception.InvalidDevicePath,
 | 
				
			||||||
                self.compute_api.attach_volume,
 | 
					                self.compute_api.attach_volume,
 | 
				
			||||||
                self.context,
 | 
					                self.context,
 | 
				
			||||||
                None,
 | 
					                None,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,15 +20,15 @@ from nova import test
 | 
				
			|||||||
from nova import exception
 | 
					from nova import exception
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ApiErrorTestCase(test.TestCase):
 | 
					class EC2APIErrorTestCase(test.TestCase):
 | 
				
			||||||
    def test_return_valid_error(self):
 | 
					    def test_return_valid_error(self):
 | 
				
			||||||
        # without 'code' arg
 | 
					        # without 'code' arg
 | 
				
			||||||
        err = exception.ApiError('fake error')
 | 
					        err = exception.EC2APIError('fake error')
 | 
				
			||||||
        self.assertEqual(err.__str__(), 'fake error')
 | 
					        self.assertEqual(err.__str__(), 'fake error')
 | 
				
			||||||
        self.assertEqual(err.code, None)
 | 
					        self.assertEqual(err.code, None)
 | 
				
			||||||
        self.assertEqual(err.msg, 'fake error')
 | 
					        self.assertEqual(err.msg, 'fake error')
 | 
				
			||||||
        # with 'code' arg
 | 
					        # with 'code' arg
 | 
				
			||||||
        err = exception.ApiError('fake error', 'blah code')
 | 
					        err = exception.EC2APIError('fake error', 'blah code')
 | 
				
			||||||
        self.assertEqual(err.__str__(), 'blah code: fake error')
 | 
					        self.assertEqual(err.__str__(), 'blah code: fake error')
 | 
				
			||||||
        self.assertEqual(err.code, 'blah code')
 | 
					        self.assertEqual(err.code, 'blah code')
 | 
				
			||||||
        self.assertEqual(err.msg, 'fake error')
 | 
					        self.assertEqual(err.msg, 'fake error')
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -85,7 +85,7 @@ class InstanceTypeTestCase(test.TestCase):
 | 
				
			|||||||
                            'instance type was not created')
 | 
					                            'instance type was not created')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        instance_types.destroy(name)
 | 
					        instance_types.destroy(name)
 | 
				
			||||||
        self.assertRaises(exception.ApiError,
 | 
					        self.assertRaises(exception.InstanceTypeNotFound,
 | 
				
			||||||
                          instance_types.get_instance_type, inst_type_id)
 | 
					                          instance_types.get_instance_type, inst_type_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # deleted instance should not be in list anymoer
 | 
					        # deleted instance should not be in list anymoer
 | 
				
			||||||
@@ -133,7 +133,7 @@ class InstanceTypeTestCase(test.TestCase):
 | 
				
			|||||||
                          'unknown_flavor')
 | 
					                          'unknown_flavor')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_duplicate_names_fail(self):
 | 
					    def test_duplicate_names_fail(self):
 | 
				
			||||||
        """Ensures that name duplicates raise ApiError"""
 | 
					        """Ensures that name duplicates raise InstanceTypeCreateFailed"""
 | 
				
			||||||
        name = 'some_name'
 | 
					        name = 'some_name'
 | 
				
			||||||
        instance_types.create(name, 256, 1, 120, 200, 'flavor1')
 | 
					        instance_types.create(name, 256, 1, 120, 200, 'flavor1')
 | 
				
			||||||
        self.assertRaises(exception.InstanceTypeExists,
 | 
					        self.assertRaises(exception.InstanceTypeExists,
 | 
				
			||||||
@@ -141,7 +141,7 @@ class InstanceTypeTestCase(test.TestCase):
 | 
				
			|||||||
                          name, 256, 1, 120, 200, 'flavor2')
 | 
					                          name, 256, 1, 120, 200, 'flavor2')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_duplicate_flavorids_fail(self):
 | 
					    def test_duplicate_flavorids_fail(self):
 | 
				
			||||||
        """Ensures that flavorid duplicates raise ApiError"""
 | 
					        """Ensures that flavorid duplicates raise InstanceTypeCreateFailed"""
 | 
				
			||||||
        flavorid = 'flavor1'
 | 
					        flavorid = 'flavor1'
 | 
				
			||||||
        instance_types.create('name one', 256, 1, 120, 200, flavorid)
 | 
					        instance_types.create('name one', 256, 1, 120, 200, flavorid)
 | 
				
			||||||
        self.assertRaises(exception.InstanceTypeExists,
 | 
					        self.assertRaises(exception.InstanceTypeExists,
 | 
				
			||||||
@@ -156,7 +156,7 @@ class InstanceTypeTestCase(test.TestCase):
 | 
				
			|||||||
    def test_will_not_get_bad_default_instance_type(self):
 | 
					    def test_will_not_get_bad_default_instance_type(self):
 | 
				
			||||||
        """ensures error raised on bad default instance type"""
 | 
					        """ensures error raised on bad default instance type"""
 | 
				
			||||||
        self.flags(default_instance_type='unknown_flavor')
 | 
					        self.flags(default_instance_type='unknown_flavor')
 | 
				
			||||||
        self.assertRaises(exception.ApiError,
 | 
					        self.assertRaises(exception.InstanceTypeNotFound,
 | 
				
			||||||
                          instance_types.get_default_instance_type)
 | 
					                          instance_types.get_default_instance_type)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_will_get_instance_type_by_id(self):
 | 
					    def test_will_get_instance_type_by_id(self):
 | 
				
			||||||
@@ -167,12 +167,12 @@ class InstanceTypeTestCase(test.TestCase):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def test_will_not_get_instance_type_by_unknown_id(self):
 | 
					    def test_will_not_get_instance_type_by_unknown_id(self):
 | 
				
			||||||
        """Ensure get by name returns default flavor with no name"""
 | 
					        """Ensure get by name returns default flavor with no name"""
 | 
				
			||||||
        self.assertRaises(exception.ApiError,
 | 
					        self.assertRaises(exception.InstanceTypeNotFound,
 | 
				
			||||||
                         instance_types.get_instance_type, 10000)
 | 
					                         instance_types.get_instance_type, 10000)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_will_not_get_instance_type_with_bad_id(self):
 | 
					    def test_will_not_get_instance_type_with_bad_id(self):
 | 
				
			||||||
        """Ensure get by name returns default flavor with bad name"""
 | 
					        """Ensure get by name returns default flavor with bad name"""
 | 
				
			||||||
        self.assertRaises(exception.ApiError,
 | 
					        self.assertRaises(exception.InstanceTypeNotFound,
 | 
				
			||||||
                          instance_types.get_instance_type, 'asdf')
 | 
					                          instance_types.get_instance_type, 'asdf')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_instance_type_get_by_None_name_returns_default(self):
 | 
					    def test_instance_type_get_by_None_name_returns_default(self):
 | 
				
			||||||
@@ -183,7 +183,7 @@ class InstanceTypeTestCase(test.TestCase):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def test_will_not_get_instance_type_with_bad_name(self):
 | 
					    def test_will_not_get_instance_type_with_bad_name(self):
 | 
				
			||||||
        """Ensure get by name returns default flavor with bad name"""
 | 
					        """Ensure get by name returns default flavor with bad name"""
 | 
				
			||||||
        self.assertRaises(exception.ApiError,
 | 
					        self.assertRaises(exception.InstanceTypeNotFound,
 | 
				
			||||||
                          instance_types.get_instance_type_by_name, 10000)
 | 
					                          instance_types.get_instance_type_by_name, 10000)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_will_not_get_instance_by_unknown_flavor_id(self):
 | 
					    def test_will_not_get_instance_by_unknown_flavor_id(self):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -249,7 +249,7 @@ class VolumeTestCase(test.TestCase):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        volume_api = nova.volume.api.API()
 | 
					        volume_api = nova.volume.api.API()
 | 
				
			||||||
        volume = volume_api.get(self.context, volume['id'])
 | 
					        volume = volume_api.get(self.context, volume['id'])
 | 
				
			||||||
        self.assertRaises(exception.ApiError,
 | 
					        self.assertRaises(exception.InvalidVolume,
 | 
				
			||||||
                          volume_api.create_snapshot,
 | 
					                          volume_api.create_snapshot,
 | 
				
			||||||
                          self.context, volume,
 | 
					                          self.context, volume,
 | 
				
			||||||
                          'fake_name', 'fake_description')
 | 
					                          'fake_name', 'fake_description')
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -85,7 +85,7 @@ class VolumeTypeTestCase(test.TestCase):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def test_non_existant_vol_type_shouldnt_delete(self):
 | 
					    def test_non_existant_vol_type_shouldnt_delete(self):
 | 
				
			||||||
        """Ensures that volume type creation fails with invalid args"""
 | 
					        """Ensures that volume type creation fails with invalid args"""
 | 
				
			||||||
        self.assertRaises(exception.ApiError,
 | 
					        self.assertRaises(exception.VolumeTypeNotFoundByName,
 | 
				
			||||||
                          volume_types.destroy, self.ctxt, "sfsfsdfdfs")
 | 
					                          volume_types.destroy, self.ctxt, "sfsfsdfdfs")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_repeated_vol_types_shouldnt_raise(self):
 | 
					    def test_repeated_vol_types_shouldnt_raise(self):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -90,7 +90,7 @@ class VsaTestCase(test.TestCase):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def test_vsa_create_wrong_image_name(self):
 | 
					    def test_vsa_create_wrong_image_name(self):
 | 
				
			||||||
        param = {'image_name': 'wrong_image_name'}
 | 
					        param = {'image_name': 'wrong_image_name'}
 | 
				
			||||||
        self.assertRaises(exception.ApiError,
 | 
					        self.assertRaises(exception.ImageNotFound,
 | 
				
			||||||
                          self.vsa_api.create, self.context, **param)
 | 
					                          self.vsa_api.create, self.context, **param)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_vsa_create_db_error(self):
 | 
					    def test_vsa_create_db_error(self):
 | 
				
			||||||
@@ -100,19 +100,19 @@ class VsaTestCase(test.TestCase):
 | 
				
			|||||||
            raise exception.Error
 | 
					            raise exception.Error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.stubs.Set(nova.db, 'vsa_create', fake_vsa_create)
 | 
					        self.stubs.Set(nova.db, 'vsa_create', fake_vsa_create)
 | 
				
			||||||
        self.assertRaises(exception.ApiError,
 | 
					        self.assertRaises(exception.Error,
 | 
				
			||||||
                          self.vsa_api.create, self.context)
 | 
					                          self.vsa_api.create, self.context)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_vsa_create_wrong_storage_params(self):
 | 
					    def test_vsa_create_wrong_storage_params(self):
 | 
				
			||||||
        vsa_list1 = self.vsa_api.get_all(self.context)
 | 
					        vsa_list1 = self.vsa_api.get_all(self.context)
 | 
				
			||||||
        param = {'storage': [{'stub': 1}]}
 | 
					        param = {'storage': [{'stub': 1}]}
 | 
				
			||||||
        self.assertRaises(exception.ApiError,
 | 
					        self.assertRaises(exception.InvalidVolumeType,
 | 
				
			||||||
                          self.vsa_api.create, self.context, **param)
 | 
					                          self.vsa_api.create, self.context, **param)
 | 
				
			||||||
        vsa_list2 = self.vsa_api.get_all(self.context)
 | 
					        vsa_list2 = self.vsa_api.get_all(self.context)
 | 
				
			||||||
        self.assertEqual(len(vsa_list2), len(vsa_list1))
 | 
					        self.assertEqual(len(vsa_list2), len(vsa_list1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        param = {'storage': [{'drive_name': 'wrong name'}]}
 | 
					        param = {'storage': [{'drive_name': 'wrong name'}]}
 | 
				
			||||||
        self.assertRaises(exception.ApiError,
 | 
					        self.assertRaises(exception.InvalidVolumeType,
 | 
				
			||||||
                          self.vsa_api.create, self.context, **param)
 | 
					                          self.vsa_api.create, self.context, **param)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_vsa_create_with_storage(self, multi_vol_creation=True):
 | 
					    def test_vsa_create_with_storage(self, multi_vol_creation=True):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -107,14 +107,14 @@ class VsaVolumesTestCase(test.TestCase):
 | 
				
			|||||||
                         'deleting')
 | 
					                         'deleting')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_vsa_volume_delete_nonavail_volume(self):
 | 
					    def test_vsa_volume_delete_nonavail_volume(self):
 | 
				
			||||||
        """ Check volume deleton in different states. """
 | 
					        """ Check volume deletion in different states. """
 | 
				
			||||||
        volume_param = self._default_volume_param()
 | 
					        volume_param = self._default_volume_param()
 | 
				
			||||||
        volume_ref = self.volume_api.create(self.context, **volume_param)
 | 
					        volume_ref = self.volume_api.create(self.context, **volume_param)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.volume_api.update(self.context,
 | 
					        self.volume_api.update(self.context,
 | 
				
			||||||
                               volume_ref,
 | 
					                               volume_ref,
 | 
				
			||||||
                               {'status': 'in-use'})
 | 
					                               {'status': 'in-use'})
 | 
				
			||||||
        self.assertRaises(exception.ApiError,
 | 
					        self.assertRaises(exception.InvalidVolume,
 | 
				
			||||||
                            self.volume_api.delete,
 | 
					                            self.volume_api.delete,
 | 
				
			||||||
                            self.context, volume_ref)
 | 
					                            self.context, volume_ref)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -551,8 +551,8 @@ class ProxyConnection(driver.ComputeDriver):
 | 
				
			|||||||
        raise NotImplementedError()
 | 
					        raise NotImplementedError()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_diagnostics(self, instance_name):
 | 
					    def get_diagnostics(self, instance_name):
 | 
				
			||||||
        raise exception.ApiError(_("diagnostics are not supported "
 | 
					        # diagnostics are not supported for baremetal
 | 
				
			||||||
                                   "for baremetal"))
 | 
					        raise NotImplementedError()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_disks(self, instance_name):
 | 
					    def get_disks(self, instance_name):
 | 
				
			||||||
        raise NotImplementedError()
 | 
					        raise NotImplementedError()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -610,12 +610,12 @@ class VMWareVMOps(object):
 | 
				
			|||||||
            LOG.exception(exc)
 | 
					            LOG.exception(exc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def pause(self, instance):
 | 
					    def pause(self, instance):
 | 
				
			||||||
        """Pause a VM instance."""
 | 
					        msg = _("pause not supported for vmwareapi")
 | 
				
			||||||
        raise exception.ApiError("pause not supported for vmwareapi")
 | 
					        raise NotImplementedError(msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def unpause(self, instance):
 | 
					    def unpause(self, instance):
 | 
				
			||||||
        """Un-Pause a VM instance."""
 | 
					        msg = _("unpause not supported for vmwareapi")
 | 
				
			||||||
        raise exception.ApiError("unpause not supported for vmwareapi")
 | 
					        raise NotImplementedError(msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def suspend(self, instance):
 | 
					    def suspend(self, instance):
 | 
				
			||||||
        """Suspend the specified instance."""
 | 
					        """Suspend the specified instance."""
 | 
				
			||||||
@@ -694,8 +694,8 @@ class VMWareVMOps(object):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def get_diagnostics(self, instance):
 | 
					    def get_diagnostics(self, instance):
 | 
				
			||||||
        """Return data about VM diagnostics."""
 | 
					        """Return data about VM diagnostics."""
 | 
				
			||||||
        raise exception.ApiError("get_diagnostics not implemented for "
 | 
					        msg = _("get_diagnostics not implemented for vmwareapi")
 | 
				
			||||||
                                 "vmwareapi")
 | 
					        raise NotImplementedError(msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_console_output(self, instance):
 | 
					    def get_console_output(self, instance):
 | 
				
			||||||
        """Return snapshot of console."""
 | 
					        """Return snapshot of console."""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -71,8 +71,8 @@ class API(base.Base):
 | 
				
			|||||||
        check_policy(context, 'create')
 | 
					        check_policy(context, 'create')
 | 
				
			||||||
        if snapshot is not None:
 | 
					        if snapshot is not None:
 | 
				
			||||||
            if snapshot['status'] != "available":
 | 
					            if snapshot['status'] != "available":
 | 
				
			||||||
                raise exception.ApiError(
 | 
					                msg = _("status must be available")
 | 
				
			||||||
                    _("Snapshot status must be available"))
 | 
					                raise exception.InvalidSnapshot(reason=msg)
 | 
				
			||||||
            if not size:
 | 
					            if not size:
 | 
				
			||||||
                size = snapshot['volume_size']
 | 
					                size = snapshot['volume_size']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -84,8 +84,7 @@ class API(base.Base):
 | 
				
			|||||||
            pid = context.project_id
 | 
					            pid = context.project_id
 | 
				
			||||||
            LOG.warn(_("Quota exceeded for %(pid)s, tried to create"
 | 
					            LOG.warn(_("Quota exceeded for %(pid)s, tried to create"
 | 
				
			||||||
                    " %(size)sG volume") % locals())
 | 
					                    " %(size)sG volume") % locals())
 | 
				
			||||||
            raise exception.QuotaError(_("Volume quota exceeded. You cannot "
 | 
					            raise exception.QuotaError(code="VolumeSizeTooLarge")
 | 
				
			||||||
                                     "create a volume of size %sG") % size)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if availability_zone is None:
 | 
					        if availability_zone is None:
 | 
				
			||||||
            availability_zone = FLAGS.storage_availability_zone
 | 
					            availability_zone = FLAGS.storage_availability_zone
 | 
				
			||||||
@@ -131,7 +130,8 @@ class API(base.Base):
 | 
				
			|||||||
    def delete(self, context, volume):
 | 
					    def delete(self, context, volume):
 | 
				
			||||||
        volume_id = volume['id']
 | 
					        volume_id = volume['id']
 | 
				
			||||||
        if volume['status'] != "available":
 | 
					        if volume['status'] != "available":
 | 
				
			||||||
            raise exception.ApiError(_("Volume status must be available"))
 | 
					            msg = _("Volume status must be available")
 | 
				
			||||||
 | 
					            raise exception.InvalidVolume(reason=msg)
 | 
				
			||||||
        now = utils.utcnow()
 | 
					        now = utils.utcnow()
 | 
				
			||||||
        self.db.volume_update(context, volume_id, {'status': 'deleting',
 | 
					        self.db.volume_update(context, volume_id, {'status': 'deleting',
 | 
				
			||||||
                                                   'terminated_at': now})
 | 
					                                                   'terminated_at': now})
 | 
				
			||||||
@@ -207,15 +207,18 @@ class API(base.Base):
 | 
				
			|||||||
    def check_attach(self, context, volume):
 | 
					    def check_attach(self, context, volume):
 | 
				
			||||||
        # TODO(vish): abstract status checking?
 | 
					        # TODO(vish): abstract status checking?
 | 
				
			||||||
        if volume['status'] != "available":
 | 
					        if volume['status'] != "available":
 | 
				
			||||||
            raise exception.ApiError(_("Volume status must be available"))
 | 
					            msg = _("status must be available")
 | 
				
			||||||
 | 
					            raise exception.InvalidVolume(reason=msg)
 | 
				
			||||||
        if volume['attach_status'] == "attached":
 | 
					        if volume['attach_status'] == "attached":
 | 
				
			||||||
            raise exception.ApiError(_("Volume is already attached"))
 | 
					            msg = _("already attached")
 | 
				
			||||||
 | 
					            raise exception.InvalidVolume(reason=msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @wrap_check_policy
 | 
					    @wrap_check_policy
 | 
				
			||||||
    def check_detach(self, context, volume):
 | 
					    def check_detach(self, context, volume):
 | 
				
			||||||
        # TODO(vish): abstract status checking?
 | 
					        # TODO(vish): abstract status checking?
 | 
				
			||||||
        if volume['status'] == "available":
 | 
					        if volume['status'] == "available":
 | 
				
			||||||
            raise exception.ApiError(_("Volume is already detached"))
 | 
					            msg = _("already detached")
 | 
				
			||||||
 | 
					            raise exception.InvalidVolume(reason=msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def remove_from_compute(self, context, volume, instance_id, host):
 | 
					    def remove_from_compute(self, context, volume, instance_id, host):
 | 
				
			||||||
        """Remove volume from specified compute host."""
 | 
					        """Remove volume from specified compute host."""
 | 
				
			||||||
@@ -266,7 +269,8 @@ class API(base.Base):
 | 
				
			|||||||
        check_policy(context, 'create_snapshot', volume)
 | 
					        check_policy(context, 'create_snapshot', volume)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ((not force) and (volume['status'] != "available")):
 | 
					        if ((not force) and (volume['status'] != "available")):
 | 
				
			||||||
            raise exception.ApiError(_("Volume status must be available"))
 | 
					            msg = _("must be available")
 | 
				
			||||||
 | 
					            raise exception.InvalidVolume(reason=msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        options = {
 | 
					        options = {
 | 
				
			||||||
            'volume_id': volume['id'],
 | 
					            'volume_id': volume['id'],
 | 
				
			||||||
@@ -298,7 +302,8 @@ class API(base.Base):
 | 
				
			|||||||
    @wrap_check_policy
 | 
					    @wrap_check_policy
 | 
				
			||||||
    def delete_snapshot(self, context, snapshot):
 | 
					    def delete_snapshot(self, context, snapshot):
 | 
				
			||||||
        if snapshot['status'] != "available":
 | 
					        if snapshot['status'] != "available":
 | 
				
			||||||
            raise exception.ApiError(_("Snapshot status must be available"))
 | 
					            msg = _("must be available")
 | 
				
			||||||
 | 
					            raise exception.InvalidVolume(reason=msg)
 | 
				
			||||||
        self.db.snapshot_update(context, snapshot['id'],
 | 
					        self.db.snapshot_update(context, snapshot['id'],
 | 
				
			||||||
                                {'status': 'deleting'})
 | 
					                                {'status': 'deleting'})
 | 
				
			||||||
        rpc.cast(context,
 | 
					        rpc.cast(context,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -702,9 +702,7 @@ class SolidFireSanISCSIDriver(SanISCSIDriver):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if response.status != 200:
 | 
					        if response.status != 200:
 | 
				
			||||||
            connection.close()
 | 
					            connection.close()
 | 
				
			||||||
            msg = _("Error in SolidFire API response, status was: %s"
 | 
					            raise exception.SolidFireAPIException(status=response.status)
 | 
				
			||||||
                    % response.status)
 | 
					 | 
				
			||||||
            raise exception.ApiError(msg)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            data = response.read()
 | 
					            data = response.read()
 | 
				
			||||||
@@ -763,9 +761,7 @@ class SolidFireSanISCSIDriver(SanISCSIDriver):
 | 
				
			|||||||
        params = {}
 | 
					        params = {}
 | 
				
			||||||
        data = self._issue_api_request('GetClusterInfo', params)
 | 
					        data = self._issue_api_request('GetClusterInfo', params)
 | 
				
			||||||
        if 'result' not in data:
 | 
					        if 'result' not in data:
 | 
				
			||||||
            msg = _("Error in SolidFire API response data was: %s"
 | 
					            raise exception.SolidFireAPIDataException(data=data)
 | 
				
			||||||
                    % data)
 | 
					 | 
				
			||||||
            raise exception.ApiError(msg)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return data['result']
 | 
					        return data['result']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -827,14 +823,10 @@ class SolidFireSanISCSIDriver(SanISCSIDriver):
 | 
				
			|||||||
                  'attributes': attributes}
 | 
					                  'attributes': attributes}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        data = self._issue_api_request('CreateVolume', params)
 | 
					        data = self._issue_api_request('CreateVolume', params)
 | 
				
			||||||
        if 'result' not in data:
 | 
					
 | 
				
			||||||
            msg = _("Error in SolidFire API response data was: %s"
 | 
					        if 'result' not in data or 'volumeID' not in data['result']:
 | 
				
			||||||
                    % data)
 | 
					            raise exception.SolidFireAPIDataException(data=data)
 | 
				
			||||||
            raise exception.ApiError(msg)
 | 
					
 | 
				
			||||||
        if 'volumeID' not in data['result']:
 | 
					 | 
				
			||||||
            msg = _("Error in SolidFire API response data was: %s"
 | 
					 | 
				
			||||||
                    % data)
 | 
					 | 
				
			||||||
            raise exception.ApiError(msg)
 | 
					 | 
				
			||||||
        volume_id = data['result']['volumeID']
 | 
					        volume_id = data['result']['volumeID']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        volume_list = self._get_volumes_by_sfaccount(account_id)
 | 
					        volume_list = self._get_volumes_by_sfaccount(account_id)
 | 
				
			||||||
@@ -873,9 +865,7 @@ class SolidFireSanISCSIDriver(SanISCSIDriver):
 | 
				
			|||||||
        params = {'accountID': sfaccount['accountID']}
 | 
					        params = {'accountID': sfaccount['accountID']}
 | 
				
			||||||
        data = self._issue_api_request('ListVolumesForAccount', params)
 | 
					        data = self._issue_api_request('ListVolumesForAccount', params)
 | 
				
			||||||
        if 'result' not in data:
 | 
					        if 'result' not in data:
 | 
				
			||||||
            msg = _("Error in SolidFire API response, data was: %s"
 | 
					            raise exception.SolidFireAPIDataException(data=data)
 | 
				
			||||||
                    % data)
 | 
					 | 
				
			||||||
            raise exception.ApiError(msg)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        found_count = 0
 | 
					        found_count = 0
 | 
				
			||||||
        volid = -1
 | 
					        volid = -1
 | 
				
			||||||
@@ -891,9 +881,7 @@ class SolidFireSanISCSIDriver(SanISCSIDriver):
 | 
				
			|||||||
        params = {'volumeID': volid}
 | 
					        params = {'volumeID': volid}
 | 
				
			||||||
        data = self._issue_api_request('DeleteVolume', params)
 | 
					        data = self._issue_api_request('DeleteVolume', params)
 | 
				
			||||||
        if 'result' not in data:
 | 
					        if 'result' not in data:
 | 
				
			||||||
            msg = _("Error in SolidFire API response, data was: %s"
 | 
					            raise exception.SolidFireAPIDataException(data=data)
 | 
				
			||||||
                    % data)
 | 
					 | 
				
			||||||
            raise exception.ApiError(msg)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        LOG.debug(_("Leaving SolidFire delete_volume"))
 | 
					        LOG.debug(_("Leaving SolidFire delete_volume"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,21 +39,17 @@ def create(context, name, extra_specs={}):
 | 
				
			|||||||
                                   extra_specs=extra_specs))
 | 
					                                   extra_specs=extra_specs))
 | 
				
			||||||
    except exception.DBError, e:
 | 
					    except exception.DBError, e:
 | 
				
			||||||
        LOG.exception(_('DB error: %s') % e)
 | 
					        LOG.exception(_('DB error: %s') % e)
 | 
				
			||||||
        raise exception.ApiError(_("Cannot create volume_type with "
 | 
					        raise exception.VolumeTypeCreateFailed(name=name,
 | 
				
			||||||
                                    "name %(name)s and specs %(extra_specs)s")
 | 
					                                               extra_specs=extra_specs)
 | 
				
			||||||
                                    % locals())
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def destroy(context, name):
 | 
					def destroy(context, name):
 | 
				
			||||||
    """Marks volume types as deleted."""
 | 
					    """Marks volume types as deleted."""
 | 
				
			||||||
    if name is None:
 | 
					    if name is None:
 | 
				
			||||||
        raise exception.InvalidVolumeType(volume_type=name)
 | 
					        msg = _("name cannot be None")
 | 
				
			||||||
 | 
					        raise exception.InvalidVolumeType(reason=msg)
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        try:
 | 
					        db.volume_type_destroy(context, name)
 | 
				
			||||||
            db.volume_type_destroy(context, name)
 | 
					 | 
				
			||||||
        except exception.NotFound:
 | 
					 | 
				
			||||||
            LOG.exception(_('Volume type %s not found for deletion') % name)
 | 
					 | 
				
			||||||
            raise exception.ApiError(_("Unknown volume type: %s") % name)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_all_types(context, inactive=0, search_opts={}):
 | 
					def get_all_types(context, inactive=0, search_opts={}):
 | 
				
			||||||
@@ -97,26 +93,22 @@ def get_all_types(context, inactive=0, search_opts={}):
 | 
				
			|||||||
def get_volume_type(ctxt, id):
 | 
					def get_volume_type(ctxt, id):
 | 
				
			||||||
    """Retrieves single volume type by id."""
 | 
					    """Retrieves single volume type by id."""
 | 
				
			||||||
    if id is None:
 | 
					    if id is None:
 | 
				
			||||||
        raise exception.InvalidVolumeType(volume_type=id)
 | 
					        msg = _("id cannot be None")
 | 
				
			||||||
 | 
					        raise exception.InvalidVolumeType(reason=msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ctxt is None:
 | 
					    if ctxt is None:
 | 
				
			||||||
        ctxt = context.get_admin_context()
 | 
					        ctxt = context.get_admin_context()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try:
 | 
					    return db.volume_type_get(ctxt, id)
 | 
				
			||||||
        return db.volume_type_get(ctxt, id)
 | 
					 | 
				
			||||||
    except exception.DBError:
 | 
					 | 
				
			||||||
        raise exception.ApiError(_("Unknown volume type: %s") % id)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_volume_type_by_name(context, name):
 | 
					def get_volume_type_by_name(context, name):
 | 
				
			||||||
    """Retrieves single volume type by name."""
 | 
					    """Retrieves single volume type by name."""
 | 
				
			||||||
    if name is None:
 | 
					    if name is None:
 | 
				
			||||||
        raise exception.InvalidVolumeType(volume_type=name)
 | 
					        msg = _("name cannot be None")
 | 
				
			||||||
 | 
					        raise exception.InvalidVolumeType(reason=msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try:
 | 
					    return db.volume_type_get_by_name(context, name)
 | 
				
			||||||
        return db.volume_type_get_by_name(context, name)
 | 
					 | 
				
			||||||
    except exception.DBError:
 | 
					 | 
				
			||||||
        raise exception.ApiError(_("Unknown volume type: %s") % name)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def is_key_value_present(volume_type_id, key, value, volume_type=None):
 | 
					def is_key_value_present(volume_type_id, key, value, volume_type=None):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,8 +23,6 @@ For assistance and guidelines pls contact
 | 
				
			|||||||
    Zadara Storage Inc & Openstack community
 | 
					    Zadara Storage Inc & Openstack community
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import sys
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from nova import compute
 | 
					from nova import compute
 | 
				
			||||||
from nova import exception
 | 
					from nova import exception
 | 
				
			||||||
from nova import flags
 | 
					from nova import flags
 | 
				
			||||||
@@ -81,8 +79,8 @@ class API(base.Base):
 | 
				
			|||||||
            vol_type['extra_specs'].get('drive_type') is None or
 | 
					            vol_type['extra_specs'].get('drive_type') is None or
 | 
				
			||||||
            vol_type['extra_specs'].get('drive_size') is None):
 | 
					            vol_type['extra_specs'].get('drive_size') is None):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            raise exception.ApiError(_("Invalid drive type %s")
 | 
					            msg = _("invalid drive data")
 | 
				
			||||||
                                        % vol_type['name'])
 | 
					            raise exception.InvalidVolumeType(reason=msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _get_default_vsa_instance_type(self):
 | 
					    def _get_default_vsa_instance_type(self):
 | 
				
			||||||
        return instance_types.get_instance_type_by_name(
 | 
					        return instance_types.get_instance_type_by_name(
 | 
				
			||||||
@@ -104,13 +102,14 @@ class API(base.Base):
 | 
				
			|||||||
            num_disks = node.get('num_drives', 1)
 | 
					            num_disks = node.get('num_drives', 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if name is None:
 | 
					            if name is None:
 | 
				
			||||||
                raise exception.ApiError(_("No drive_name param found in %s")
 | 
					                msg = _("drive_name not defined")
 | 
				
			||||||
                                            % node)
 | 
					                raise exception.InvalidVolumeType(reason=msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
                vol_type = volume_types.get_volume_type_by_name(context, name)
 | 
					                vol_type = volume_types.get_volume_type_by_name(context, name)
 | 
				
			||||||
            except exception.NotFound:
 | 
					            except exception.NotFound:
 | 
				
			||||||
                raise exception.ApiError(_("Invalid drive type name %s")
 | 
					                msg = _("invalid drive type name %s")
 | 
				
			||||||
                                            % name)
 | 
					                raise exception.InvalidVolumeType(reason=msg % name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self._check_volume_type_correctness(vol_type)
 | 
					            self._check_volume_type_correctness(vol_type)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -177,13 +176,10 @@ class API(base.Base):
 | 
				
			|||||||
        # check if image is ready before starting any work
 | 
					        # check if image is ready before starting any work
 | 
				
			||||||
        if image_name is None:
 | 
					        if image_name is None:
 | 
				
			||||||
            image_name = FLAGS.vc_image_name
 | 
					            image_name = FLAGS.vc_image_name
 | 
				
			||||||
        try:
 | 
					
 | 
				
			||||||
            image_service = self.compute_api.image_service
 | 
					        image_service = self.compute_api.image_service
 | 
				
			||||||
            vc_image = image_service.show_by_name(context, image_name)
 | 
					        vc_image = image_service.show_by_name(context, image_name)
 | 
				
			||||||
            vc_image_href = vc_image['id']
 | 
					        vc_image_href = vc_image['id']
 | 
				
			||||||
        except exception.ImageNotFound:
 | 
					 | 
				
			||||||
            raise exception.ApiError(_("Failed to find configured image %s")
 | 
					 | 
				
			||||||
                                        % image_name)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        options = {
 | 
					        options = {
 | 
				
			||||||
            'display_name': display_name,
 | 
					            'display_name': display_name,
 | 
				
			||||||
@@ -198,10 +194,8 @@ class API(base.Base):
 | 
				
			|||||||
        LOG.info(_("Creating VSA: %s") % options)
 | 
					        LOG.info(_("Creating VSA: %s") % options)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # create DB entry for VSA instance
 | 
					        # create DB entry for VSA instance
 | 
				
			||||||
        try:
 | 
					        vsa_ref = self.db.vsa_create(context, options)
 | 
				
			||||||
            vsa_ref = self.db.vsa_create(context, options)
 | 
					
 | 
				
			||||||
        except exception.Error:
 | 
					 | 
				
			||||||
            raise exception.ApiError(_(sys.exc_info()[1]))
 | 
					 | 
				
			||||||
        vsa_id = vsa_ref['id']
 | 
					        vsa_id = vsa_ref['id']
 | 
				
			||||||
        vsa_name = vsa_ref['name']
 | 
					        vsa_name = vsa_ref['name']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -209,10 +203,9 @@ class API(base.Base):
 | 
				
			|||||||
        try:
 | 
					        try:
 | 
				
			||||||
            volume_params = self._check_storage_parameters(context, vsa_name,
 | 
					            volume_params = self._check_storage_parameters(context, vsa_name,
 | 
				
			||||||
                                                           storage, shared)
 | 
					                                                           storage, shared)
 | 
				
			||||||
        except exception.ApiError:
 | 
					        except exception.InvalidVolumeType:
 | 
				
			||||||
            self.db.vsa_destroy(context, vsa_id)
 | 
					            self.db.vsa_destroy(context, vsa_id)
 | 
				
			||||||
            raise exception.ApiError(_("Error in storage parameters: %s")
 | 
					            raise
 | 
				
			||||||
                                        % storage)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # after creating DB entry, re-check and set some defaults
 | 
					        # after creating DB entry, re-check and set some defaults
 | 
				
			||||||
        updates = {}
 | 
					        updates = {}
 | 
				
			||||||
@@ -358,7 +351,7 @@ class API(base.Base):
 | 
				
			|||||||
                LOG.info(_("VSA ID %(vsa_id)s: Deleting %(direction)s "
 | 
					                LOG.info(_("VSA ID %(vsa_id)s: Deleting %(direction)s "
 | 
				
			||||||
                           "volume %(vol_name)s"), locals())
 | 
					                           "volume %(vol_name)s"), locals())
 | 
				
			||||||
                self.volume_api.delete(context, volume)
 | 
					                self.volume_api.delete(context, volume)
 | 
				
			||||||
            except exception.ApiError:
 | 
					            except exception.InvalidVolume:
 | 
				
			||||||
                LOG.info(_("Unable to delete volume %s"), volume['name'])
 | 
					                LOG.info(_("Unable to delete volume %s"), volume['name'])
 | 
				
			||||||
                if force_delete:
 | 
					                if force_delete:
 | 
				
			||||||
                    LOG.info(_("VSA ID %(vsa_id)s: Forced delete. "
 | 
					                    LOG.info(_("VSA ID %(vsa_id)s: Forced delete. "
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user