Ejemplo n.º 1
0
    def create(self, req, body):
        context = req.environ['engine.context']
        group_id = body['security_group_rule']['parent_group_id']

        self.compute_api.ensure_default_security_group(context)
        security_group = db.security_group_get(context, group_id)
        if not security_group:
            raise exception.SecurityGroupNotFound(security_group_id=group_id)

        msg = "Authorize security group ingress %s"
        LOG.audit(_(msg), security_group['name'], context=context)
        values = self._revoke_rule_args_to_dict(context,
                                                **body['security_group_rule'])
        if values is None:
            raise exception.ApiError(
                _("Not enough parameters to build a "
                  "valid rule."))
        values['parent_group_id'] = security_group.id

        if self._security_group_rule_exists(security_group, values):
            raise exception.ApiError(
                _('This rule already exists in group %s') % group_id)

        security_group_rule = db.security_group_rule_create(context, values)

        self.compute_api.trigger_security_group_rules_refresh(
            context, security_group_id=security_group['id'])

        return {
            'security_group_rule':
            self._format_security_group_rule(context, security_group_rule)
        }
Ejemplo n.º 2
0
 def check_attach(self, context, volume_id):
     volume = self.get(context, volume_id)
     # TODO(vish): abstract status checking?
     if volume['status'] != "available":
         raise exception.ApiError(_("Volume status must be available"))
     if volume['attach_status'] == "attached":
         raise exception.ApiError(_("Volume is already attached"))
Ejemplo n.º 3
0
    def _check_storage_parameters(self,
                                  context,
                                  vsa_name,
                                  storage,
                                  shared,
                                  first_index=0):
        """
        Translates storage array of disks to the list of volumes
        :param storage: List of dictionaries with following keys:
                        disk_name, num_disks, size
        :param shared: Specifies if storage is dedicated or shared.
                       For shared storage disks split into partitions
        """
        volume_params = []
        for node in storage:

            name = node.get('drive_name', None)
            num_disks = node.get('num_drives', 1)

            if name is None:
                raise exception.ApiError(
                    _("No drive_name param found in %s") % node)
            try:
                vol_type = volume_types.get_volume_type_by_name(context, name)
            except exception.NotFound:
                raise exception.ApiError(
                    _("Invalid drive type name %s") % name)

            self._check_volume_type_correctness(vol_type)

            # if size field present - override disk size specified in DB
            size = int(
                node.get('size', vol_type['extra_specs'].get('drive_size')))

            if shared:
                part_size = FLAGS.vsa_part_size_gb
                total_capacity = num_disks * size
                num_volumes = total_capacity / part_size
                size = part_size
            else:
                num_volumes = num_disks
                size = 0  # special handling for full drives

            for i in range(num_volumes):
                volume_name = "drive-%03d" % first_index
                first_index += 1
                volume_desc = 'BE volume for VSA %s type %s' % \
                              (vsa_name, name)
                volume = {
                    'size': size,
                    'name': volume_name,
                    'description': volume_desc,
                    'volume_type_id': vol_type['id'],
                }
                volume_params.append(volume)

        return volume_params
Ejemplo n.º 4
0
 def test_return_valid_error(self):
     # without 'code' arg
     err = exception.ApiError('fake error')
     self.assertEqual(err.__str__(), 'fake error')
     self.assertEqual(err.code, None)
     self.assertEqual(err.msg, 'fake error')
     # with 'code' arg
     err = exception.ApiError('fake error', 'blah code')
     self.assertEqual(err.__str__(), 'blah code: fake error')
     self.assertEqual(err.code, 'blah code')
     self.assertEqual(err.msg, 'fake error')
Ejemplo n.º 5
0
    def _create_snapshot(self,
                         context,
                         volume_id,
                         name,
                         description,
                         force=False):
        volume = self.get(context, volume_id)
        if ((not force) and (volume['status'] != "available")):
            raise exception.ApiError(_("Volume status must be available"))

        options = {
            'volume_id': volume_id,
            'user_id': context.user_id,
            'project_id': context.project_id,
            'status': "creating",
            'progress': '0%',
            'volume_size': volume['size'],
            'display_name': name,
            'display_description': description
        }

        snapshot = self.db.snapshot_create(context, options)
        rpc.cast(
            context, FLAGS.scheduler_topic, {
                "method": "create_snapshot",
                "args": {
                    "topic": FLAGS.volume_topic,
                    "volume_id": volume_id,
                    "snapshot_id": snapshot['id']
                }
            })
        return snapshot
Ejemplo n.º 6
0
    def modify_user_role(self,
                         context,
                         user,
                         role,
                         project=None,
                         operation='add',
                         **kwargs):
        """Add or remove a role for a user and project."""
        if operation == 'add':
            if project:
                msg = _("Adding role %(role)s to user %(user)s"
                        " for project %(project)s") % locals()
                LOG.audit(msg, context=context)
            else:
                msg = _("Adding sitewide role %(role)s to"
                        " user %(user)s") % locals()
                LOG.audit(msg, context=context)
            manager.AuthManager().add_role(user, role, project)
        elif operation == 'remove':
            if project:
                msg = _("Removing role %(role)s from user %(user)s"
                        " for project %(project)s") % locals()
                LOG.audit(msg, context=context)
            else:
                msg = _("Removing sitewide role %(role)s"
                        " from user %(user)s") % locals()
                LOG.audit(msg, context=context)
            manager.AuthManager().remove_role(user, role, project)
        else:
            raise exception.ApiError(_('operation must be add or remove'))

        return True
Ejemplo n.º 7
0
 def block_external_addresses(self, context, cidr):
     """Add provider-level firewall rules to block incoming traffic."""
     LOG.audit(_('Blocking traffic to all projects incoming from %s'),
               cidr,
               context=context)
     cidr = urllib.unquote(cidr).decode()
     # raise if invalid
     netaddr.IPNetwork(cidr)
     rule = {'cidr': cidr}
     tcp_rule = rule.copy()
     tcp_rule.update({'protocol': 'tcp', 'from_port': 1, 'to_port': 65535})
     udp_rule = rule.copy()
     udp_rule.update({'protocol': 'udp', 'from_port': 1, 'to_port': 65535})
     icmp_rule = rule.copy()
     icmp_rule.update({
         'protocol': 'icmp',
         'from_port': -1,
         'to_port': None
     })
     rules_added = 0
     if not self._provider_fw_rule_exists(context, tcp_rule):
         db.provider_fw_rule_create(context, tcp_rule)
         rules_added += 1
     if not self._provider_fw_rule_exists(context, udp_rule):
         db.provider_fw_rule_create(context, udp_rule)
         rules_added += 1
     if not self._provider_fw_rule_exists(context, icmp_rule):
         db.provider_fw_rule_create(context, icmp_rule)
         rules_added += 1
     if not rules_added:
         raise exception.ApiError(_('Duplicate rule'))
     self.compute_api.trigger_provider_fw_rules_refresh(context)
     return {'status': 'OK', 'message': 'Added %s rules' % rules_added}
Ejemplo n.º 8
0
def get_instance_type_by_flavor_id(flavorid):
    """Retrieve instance type by flavorid."""
    ctxt = context.get_admin_context()
    try:
        return db.instance_type_get_by_flavor_id(ctxt, flavorid)
    except exception.DBError:
        raise exception.ApiError(_("Unknown instance type: %s") % flavorid)
Ejemplo n.º 9
0
def get_default_instance_type():
    """Get the default instance type."""
    name = FLAGS.default_instance_type
    try:
        return get_instance_type_by_name(name)
    except exception.DBError:
        raise exception.ApiError(_("Unknown instance type: %s") % name)
Ejemplo n.º 10
0
    def create(self,
               context,
               size,
               snapshot_id,
               name,
               description,
               volume_type=None,
               metadata=None,
               availability_zone=None):
        if snapshot_id is not None:
            snapshot = self.get_snapshot(context, snapshot_id)
            if snapshot['status'] != "available":
                raise exception.ApiError(
                    _("Snapshot status must be available"))
            if not size:
                size = snapshot['volume_size']

        if quota.allowed_volumes(context, 1, size) < 1:
            pid = context.project_id
            LOG.warn(
                _("Quota exceeded for %(pid)s, tried to create"
                  " %(size)sG volume") % locals())
            raise exception.QuotaError(
                _("Volume quota exceeded. You cannot "
                  "create a volume of size %sG") % size)

        if availability_zone is None:
            availability_zone = FLAGS.storage_availability_zone

        if volume_type is None:
            volume_type_id = None
        else:
            volume_type_id = volume_type.get('id', None)

        options = {
            'size': size,
            'user_id': context.user_id,
            'project_id': context.project_id,
            'snapshot_id': snapshot_id,
            'availability_zone': availability_zone,
            'status': "creating",
            'attach_status': "detached",
            'display_name': name,
            'display_description': description,
            'volume_type_id': volume_type_id,
            'metadata': metadata,
        }

        volume = self.db.volume_create(context, options)
        rpc.cast(
            context, FLAGS.scheduler_topic, {
                "method": "create_volume",
                "args": {
                    "topic": FLAGS.volume_topic,
                    "volume_id": volume['id'],
                    "snapshot_id": snapshot_id
                }
            })
        return volume
Ejemplo n.º 11
0
    def _check_volume_type_correctness(self, vol_type):
        if vol_type.get('extra_specs') is None or\
           vol_type['extra_specs'].get('type') != 'vsa_drive' or\
           vol_type['extra_specs'].get('drive_type') is None or\
           vol_type['extra_specs'].get('drive_size') is None:

            raise exception.ApiError(
                _("Invalid drive type %s") % vol_type['name'])
Ejemplo n.º 12
0
def get_volume_type_by_name(context, name):
    """Retrieves single volume type by name."""
    if name is None:
        raise exception.InvalidVolumeType(volume_type=name)

    try:
        return db.volume_type_get_by_name(context, name)
    except exception.DBError:
        raise exception.ApiError(_("Unknown volume type: %s") % name)
Ejemplo n.º 13
0
def destroy(context, name):
    """Marks volume types as deleted."""
    if name is None:
        raise exception.InvalidVolumeType(volume_type=name)
    else:
        try:
            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)
Ejemplo n.º 14
0
def create(context, name, extra_specs={}):
    """Creates volume types."""
    try:
        db.volume_type_create(context, dict(name=name,
                                            extra_specs=extra_specs))
    except exception.DBError, e:
        LOG.exception(_('DB error: %s') % e)
        raise exception.ApiError(
            _("Cannot create volume_type with "
              "name %(name)s and specs %(extra_specs)s") % locals())
Ejemplo n.º 15
0
def purge(context, name):
    """Removes volume types from database."""
    if name is None:
        raise exception.InvalidVolumeType(volume_type=name)
    else:
        try:
            db.volume_type_purge(context, name)
        except exception.NotFound:
            LOG.exception(_('Volume type %s not found for purge') % name)
            raise exception.ApiError(_("Unknown volume type: %s") % name)
Ejemplo n.º 16
0
def get_instance_type_by_name(name):
    """Retrieves single instance type by name."""
    if name is None:
        return get_default_instance_type()

    ctxt = context.get_admin_context()

    try:
        return db.instance_type_get_by_name(ctxt, name)
    except exception.DBError:
        raise exception.ApiError(_("Unknown instance type: %s") % name)
Ejemplo n.º 17
0
def get_instance_type(instance_type_id):
    """Retrieves single instance type by id."""
    if instance_type_id is None:
        return get_default_instance_type()

    ctxt = context.get_admin_context()
    try:
        return db.instance_type_get(ctxt, instance_type_id)
    except exception.DBError:
        msg = _("Unknown instance type: %s") % instance_type_id
        raise exception.ApiError(msg)
Ejemplo n.º 18
0
def get_volume_type(ctxt, id):
    """Retrieves single volume type by id."""
    if id is None:
        raise exception.InvalidVolumeType(volume_type=id)

    if ctxt is None:
        ctxt = context.get_admin_context()

    try:
        return db.volume_type_get(ctxt, id)
    except exception.DBError:
        raise exception.ApiError(_("Unknown volume type: %s") % id)
Ejemplo n.º 19
0
 def delete_snapshot(self, context, snapshot_id):
     snapshot = self.get_snapshot(context, snapshot_id)
     if snapshot['status'] != "available":
         raise exception.ApiError(_("Snapshot status must be available"))
     self.db.snapshot_update(context, snapshot_id, {'status': 'deleting'})
     rpc.cast(
         context, FLAGS.scheduler_topic, {
             "method": "delete_snapshot",
             "args": {
                 "topic": FLAGS.volume_topic,
                 "snapshot_id": snapshot_id
             }
         })
Ejemplo n.º 20
0
 def modify_project_member(self, context, user, project, operation,
                           **kwargs):
     """Add or remove a user from a project."""
     if operation == 'add':
         msg = _("Adding user %(user)s to project %(project)s") % locals()
         LOG.audit(msg, context=context)
         manager.AuthManager().add_to_project(user, project)
     elif operation == 'remove':
         msg = _("Removing user %(user)s from"
                 " project %(project)s") % locals()
         LOG.audit(msg, context=context)
         manager.AuthManager().remove_from_project(user, project)
     else:
         raise exception.ApiError(_('operation must be add or remove'))
     return True
Ejemplo n.º 21
0
 def start_vpn(self, context, project):
     instance = self._vpn_for(context, project)
     if not instance:
         # NOTE(vish) import delayed because of __init__.py
         from engine.cloudpipe import pipelib
         pipe = pipelib.CloudPipe()
         proj = manager.AuthManager().get_project(project)
         user_id = proj.project_manager_id
         try:
             pipe.launch_vpn_instance(project, user_id)
         except db.NoMoreNetworks:
             raise exception.ApiError("Unable to claim IP for VPN instance"
                                      ", ensure it isn't running, and try "
                                      "again in a few minutes")
         instance = self._vpn_for(context, project)
     return {'instance_id': ec2utils.id_to_ec2_id(instance['id'])}
Ejemplo n.º 22
0
 def delete(self, context, volume_id):
     volume = self.get(context, volume_id)
     if volume['status'] != "available":
         raise exception.ApiError(_("Volume status must be available"))
     now = utils.utcnow()
     self.db.volume_update(context, volume_id, {
         'status': 'deleting',
         'terminated_at': now
     })
     host = volume['host']
     rpc.cast(context,
              self.db.queue_get_for(context, FLAGS.volume_topic, host), {
                  "method": "delete_volume",
                  "args": {
                      "volume_id": volume_id
                  }
              })
Ejemplo n.º 23
0
    def create(self, req, body):
        context = req.environ['engine.context']
        self.compute_api.ensure_default_security_group(context)
        name = body['security_group'].get('name')
        description = body['security_group'].get('description')
        if db.security_group_exists(context, context.project_id, name):
            raise exception.ApiError(_('group %s already exists') % name)

        group = {
            'user_id': context.user_id,
            'project_id': context.project_id,
            'name': name,
            'description': description
        }
        group_ref = db.security_group_create(context, group)

        return {
            'security_group': self._format_security_group(context, group_ref)
        }
Ejemplo n.º 24
0
    def delete(self, req, id):
        context = req.environ['engine.context']
        rule = sqlalchemy_api.security_group_rule_get(context, id)
        if not rule:
            raise exception.ApiError(_("Rule not found"))
        group_id = rule.parent_group_id

        self.compute_api.ensure_default_security_group(context)

        security_group = db.security_group_get(context, group_id)
        if not security_group:
            raise exception.SecurityGroupNotFound(security_group_id=group_id)

        msg = "Revoke security group ingress %s"
        LOG.audit(_(msg), security_group['name'], context=context)

        db.security_group_rule_destroy(context, rule['id'])
        self.compute_api.trigger_security_group_rules_refresh(
            context, security_group_id=security_group['id'])
        return exc.HTTPAccepted()
Ejemplo n.º 25
0
    def create(self, req, body):
        """Create a new cloudpipe instance, if none exists.

        Parameters: {cloudpipe: {project_id: XYZ}}
        """

        ctxt = req.environ['engine.context']
        params = body.get('cloudpipe', {})
        project_id = params.get('project_id', ctxt.project_id)
        instance = self._get_cloudpipe_for_project(ctxt, project_id)
        if not instance:
            proj = self.auth_manager.get_project(project_id)
            user_id = proj.project_manager_id
            try:
                self.cloudpipe.launch_vpn_instance(project_id, user_id)
            except db.NoMoreNetworks:
                msg = _("Unable to claim IP for VPN instances, ensure it "
                        "isn't running, and try again in a few minutes")
                raise exception.ApiError(msg)
            instance = self._get_cloudpipe_for_project(ctxt, proj)
        return {'instance_id': instance['uuid']}
Ejemplo n.º 26
0
def create(name, memory, vcpus, local_gb, flavorid, swap=0, rxtx_factor=1):
    """Creates instance types."""
    kwargs = {
        'memory_mb': memory,
        'vcpus': vcpus,
        'local_gb': local_gb,
        'swap': swap,
        'rxtx_factor': rxtx_factor,
    }

    # ensure some attributes are integers and greater than or equal to 0
    for option in kwargs:
        try:
            kwargs[option] = int(kwargs[option])
            assert kwargs[option] >= 0
        except (ValueError, AssertionError):
            msg = _("create arguments must be positive integers")
            raise exception.InvalidInput(reason=msg)

    # some value are required to be nonzero, not just positive
    for option in ['memory_mb', 'vcpus']:
        try:
            assert kwargs[option] > 0
        except AssertionError:
            msg = _("create arguments must be positive integers")
            raise exception.InvalidInput(reason=msg)

    kwargs['name'] = name
    kwargs['flavorid'] = flavorid

    try:
        return db.instance_type_create(context.get_admin_context(), kwargs)
    except exception.DBError, e:
        LOG.exception(_('DB error: %s') % e)
        msg = _("Cannot create instance_type with name %(name)s and "
                "flavorid %(flavorid)s") % locals()
        raise exception.ApiError(msg)
Ejemplo n.º 27
0
 def get_diagnostics(self, instance):
     """Return data about VM diagnostics."""
     raise exception.ApiError("get_diagnostics not implemented for "
                              "vmwareapi")
Ejemplo n.º 28
0
 def unpause(self, instance):
     """Un-Pause a VM instance."""
     raise exception.ApiError("unpause not supported for vmwareapi")
Ejemplo n.º 29
0
    def create(self,
               context,
               display_name='',
               display_description='',
               vc_count=1,
               instance_type=None,
               image_name=None,
               availability_zone=None,
               storage=[],
               shared=None):
        """
        Provision VSA instance with corresponding compute instances
        and associated volumes
        :param storage: List of dictionaries with following keys:
                        disk_name, num_disks, size
        :param shared: Specifies if storage is dedicated or shared.
                       For shared storage disks split into partitions
        """

        LOG.info(_("*** Experimental VSA code ***"))

        if vc_count > FLAGS.max_vcs_in_vsa:
            LOG.warning(_("Requested number of VCs (%d) is too high."\
                          " Setting to default"), vc_count)
            vc_count = FLAGS.max_vcs_in_vsa

        if instance_type is None:
            instance_type = self._get_default_vsa_instance_type()

        if availability_zone is None:
            availability_zone = FLAGS.storage_availability_zone

        if storage is None:
            storage = []

        if not shared or shared == 'False':
            shared = False
        else:
            shared = True

        # check if image is ready before starting any work
        if image_name is None:
            image_name = FLAGS.vc_image_name
        try:
            image_service = self.compute_api.image_service
            vc_image = image_service.show_by_name(context, image_name)
            vc_image_href = vc_image['id']
        except exception.ImageNotFound:
            raise exception.ApiError(
                _("Failed to find configured image %s") % image_name)

        options = {
            'display_name': display_name,
            'display_description': display_description,
            'project_id': context.project_id,
            'availability_zone': availability_zone,
            'instance_type_id': instance_type['id'],
            'image_ref': vc_image_href,
            'vc_count': vc_count,
            'status': VsaState.CREATING,
        }
        LOG.info(_("Creating VSA: %s") % options)

        # create DB entry for VSA instance
        try:
            vsa_ref = self.db.vsa_create(context, options)
        except exception.Error:
            raise exception.ApiError(_(sys.exc_info()[1]))
        vsa_id = vsa_ref['id']
        vsa_name = vsa_ref['name']

        # check storage parameters
        try:
            volume_params = self._check_storage_parameters(
                context, vsa_name, storage, shared)
        except exception.ApiError:
            self.db.vsa_destroy(context, vsa_id)
            raise exception.ApiError(
                _("Error in storage parameters: %s") % storage)

        # after creating DB entry, re-check and set some defaults
        updates = {}
        if (not hasattr(vsa_ref, 'display_name')
                or vsa_ref.display_name is None or vsa_ref.display_name == ''):
            updates['display_name'] = display_name = vsa_name
        updates['vol_count'] = len(volume_params)
        vsa_ref = self.update(context, vsa_id, **updates)

        # create volumes
        if FLAGS.vsa_multi_vol_creation:
            if len(volume_params) > 0:
                request_spec = {
                    'num_volumes': len(volume_params),
                    'vsa_id': str(vsa_id),
                    'volumes': volume_params,
                }

                rpc.cast(
                    context, FLAGS.scheduler_topic, {
                        "method": "create_volumes",
                        "args": {
                            "topic": FLAGS.volume_topic,
                            "request_spec": request_spec,
                            "availability_zone": availability_zone
                        }
                    })
        else:
            # create BE volumes one-by-one
            for vol in volume_params:
                try:
                    vol_name = vol['name']
                    vol_size = vol['size']
                    vol_type_id = vol['volume_type_id']
                    LOG.debug(_("VSA ID %(vsa_id)d %(vsa_name)s: Create "\
                                "volume %(vol_name)s, %(vol_size)d GB, "\
                                "type %(vol_type_id)s"), locals())

                    vol_type = volume_types.get_volume_type(
                        context, vol['volume_type_id'])

                    vol_ref = self.volume_api.create(
                        context,
                        vol_size,
                        None,
                        vol_name,
                        vol['description'],
                        volume_type=vol_type,
                        metadata=dict(to_vsa_id=str(vsa_id)),
                        availability_zone=availability_zone)
                except Exception:
                    self.update_vsa_status(context,
                                           vsa_id,
                                           status=VsaState.PARTIAL)
                    raise

        if len(volume_params) == 0:
            # No BE volumes - ask VSA manager to start VCs
            rpc.cast(context, FLAGS.vsa_topic, {
                "method": "create_vsa",
                "args": {
                    "vsa_id": str(vsa_id)
                }
            })

        return vsa_ref