Ejemplo n.º 1
0
    def get_cluster_by_id(self, context, cluster_id):
        query = model_query(context, models.Cluster).filter_by(id=cluster_id)
        try:
            cluster = query.one()
        except db_exception.DBError:
            # Todo(dagnello): User input will be validated from REST API and
            # not from DB transactions.
            raise exception.Invalid(_("badly formed cluster_id UUID string"))
        except sql_exception.NoResultFound:
            raise exception.NotFound(_("Cluster was not found"))

        return cluster
Ejemplo n.º 2
0
    def create_broker_metadata(self, context, metadata_values):

        broker_query = (model_query(
            context, models.Broker).filter_by(id=metadata_values['broker_id']))
        try:
            # check to see if the broker_id exists
            broker_query.one()
            broker_metadata = models.BrokerMetadata()
            broker_metadata.update(metadata_values)
            db_session = get_session()
            broker_metadata.save(db_session)
        except db_exception.DBError:
            raise exception.Invalid(_("Badly formed broker_id UUID string"))
        except sql_exception.NoResultFound:
            raise exception.NotFound(_("Broker was not found"))

        return broker_metadata
Ejemplo n.º 3
0
    def _validate_flavor(self, image_id, cluster_flavor):
        """Checks if flavor satisfies minimum requirement of image metadata.

        :param image_id: image id of the broker.
        :param cluster_flavor: flavor id of the cluster.
        :raises: exception.ConfigurationError
        :raises: exception.InternalServerError
        :raises: exception.Invalid
        """
        nova_client = client.nova_client()

        # get image metadata
        try:
            image_metadata = nova_client.images.get(image_id)
            image_minRam = image_metadata.minRam
            image_minDisk = image_metadata.minDisk
        except nova_exc.ClientException as ex:
            if ex.http_status == 404:
                raise exception.ConfigurationError(
                    _('Invalid image %s '
                      'configured') % image_id)
            else:
                raise exception.InternalServerError

        # get flavor metadata
        try:
            flavor_metadata = nova_client.flavors.get(cluster_flavor)
            flavor_ram = flavor_metadata.ram
            flavor_disk = flavor_metadata.disk
        except nova_exc.ClientException as ex:
            if ex.http_status == 404:
                raise exception.Invalid(
                    _('Invalid flavor %s provided') % cluster_flavor)
            else:
                raise exception.InternalServerError

        # validate flavor with broker image metadata
        if (flavor_disk < image_minDisk):
            raise exception.Invalid(
                _("Flavor disk is smaller than the "
                  "minimum %s required for broker") % image_minDisk)
        elif (flavor_ram < image_minRam):
            raise exception.Invalid(
                _("Flavor ram is smaller than the "
                  "minimum %s required for broker") % image_minRam)
Ejemplo n.º 4
0
    def delete(self, cluster_id):
        """Delete this Cluster."""
        # validate cluster_id is of type Uuid
        try:
            wtypes.UuidType().validate(cluster_id)
        except ValueError:
            raise exception.Invalid(_("Invalid cluster ID format provided"))

        context = pecan.request.context
        delete_complete_cluster(context, cluster_id)
Ejemplo n.º 5
0
def check(rule, ctxt, target=None, do_raise=True, exc=exception.NotAuthorized):
    #creds = ctxt.to_dict()
    target = target or {}

    try:
        result = _ENFORCER.enforce(rule, target, ctxt, do_raise, exc)
    except Exception:
        result = False
        raise
    else:
        return result
    finally:
        extra = {'policy': {'rule': rule, 'target': target}}

        if result:
            LOG.info(_("Policy check succeeded for rule '%(rule)s' "
                       "on target %(target)s") %
                     {'rule': rule, 'target': repr(target)}, extra=extra)
        else:
            LOG.info(_("Policy check failed for rule '%(rule)s' "
                       "on target %(target)s") %
                     {'rule': rule, 'target': repr(target)}, extra=extra)
Ejemplo n.º 6
0
    def update_cluster_deleting(self, context, cluster_id):
        values = {'status': models.Status.DELETING}

        cluster_query = (model_query(context,
                                     models.Cluster).filter_by(id=cluster_id))

        try:
            cluster_query.one()
        except db_exception.DBError:
            # Todo(dagnello): User input will be validated from REST API and
            # not from DB transactions.
            raise exception.Invalid(_("badly formed cluster_id UUID string"))
        except sql_exception.NoResultFound:
            raise exception.NotFound(_("Cluster was not found"))

        db_session = get_session()

        with db_session.begin():
            cluster_query.update(values)
            nodes_query = model_query(
                context, models.Node).filter_by(cluster_id=cluster_id)
            nodes_query.update(values)
Ejemplo n.º 7
0
    def __init__(self, app, conf, public_api_routes=[]):
        route_pattern_tpl = '%s(\.json|\.xml)?$'

        try:
            self.public_api_routes = [re.compile(route_pattern_tpl % route_tpl)
                                      for route_tpl in public_api_routes]
        except re.error as e:
            msg = _('Cannot compile public API routes: %s') % e

            LOG.error(msg)
            raise exception.ConfigInvalid(error_msg=msg)

        super(AuthTokenMiddleware, self).__init__(app, conf)
Ejemplo n.º 8
0
def datetime_or_none(dt):
    """Validate a datetime or None value."""
    if dt is None:
        return None
    elif isinstance(dt, datetime.datetime):
        if dt.utcoffset() is None:
            # NOTE(danms): Legacy objects from sqlalchemy are stored in UTC,
            # but are returned without a timezone attached.
            # As a transitional aid, assume a tz-naive object is in UTC.
            return dt.replace(tzinfo=iso8601.iso8601.Utc())
        else:
            return dt
    raise ValueError(_("A datetime.datetime is required here"))
Ejemplo n.º 9
0
def check(rule, ctxt, target=None, do_raise=True, exc=exception.NotAuthorized):
    creds = ctxt.to_dict()
    target = target or {}

    try:
        result = _ENFORCER.enforce(rule, target, creds, do_raise, exc)
    except Exception:
        result = False
        raise
    else:
        return result
    finally:
        extra = {'policy': {'rule': rule, 'target': target}}

        if result:
            LOG.info(_("Policy check succeeded for rule '%(rule)s' "
                       "on target %(target)s") %
                     {'rule': rule, 'target': repr(target)}, extra=extra)
        else:
            LOG.info(_("Policy check failed for rule '%(rule)s' "
                       "on target %(target)s") %
                     {'rule': rule, 'target': repr(target)}, extra=extra)
Ejemplo n.º 10
0
    def get_one(self, cluster_id):
        """Return this cluster."""
        # validate cluster_id is of type Uuid
        try:
            wtypes.UuidType().validate(cluster_id)
        except ValueError:
            raise exception.Invalid(_("Invalid cluster ID format provided"))

        context = pecan.request.context

        cluster = get_complete_cluster(context, cluster_id)

        cluster.unset_empty_fields()
        return cluster
Ejemplo n.º 11
0
class CueException(Exception):
    """Base Cue Exception

    To correctly use this class, inherit from it and define
    a 'message' property. That message will get printf'd
    with the keyword arguments provided to the constructor.

    """
    message = _("An unknown exception occurred.")
    code = 500
    headers = {}
    safe = False

    def __init__(self, message=None, **kwargs):
        self.kwargs = kwargs

        if 'code' not in self.kwargs:
            try:
                self.kwargs['code'] = self.code
            except AttributeError:  # pragma: no cover
                pass

        if not message:
            try:
                message = self.message % kwargs

            except Exception as e:
                # kwargs doesn't match a variable in the message
                # log the issue and the kwargs
                LOG.exception(_LE('Exception in string format operation'))
                for name, value in kwargs.items():
                    LOG.error("%s: %s" % (name, value))

                if CONF.fatal_exception_format_errors:
                    raise e
                else:
                    # at least get the core message out if something happened
                    message = self.message

        super(CueException, self).__init__(message)

    def format_message(self):
        if self.__class__.__name__.endswith('_Remote'):
            return self.args[0]
        else:
            return six.text_type(self)
Ejemplo n.º 12
0
 def replacement_start_response(status, headers, exc_info=None):
     """Overrides the default response to make errors parsable."""
     try:
         status_code = int(status.split(' ')[0])
         state['status_code'] = status_code
     except (ValueError, TypeError):  # pragma: nocover
         raise Exception(_(
             'ErrorDocumentMiddleware received an invalid '
             'status %s') % status)
     else:
         if (state['status_code'] // 100) not in (2, 3):
             # Remove some headers so we can replace them later
             # when we have the full error message and can
             # compute the length.
             headers = [(h, v)
                        for (h, v) in headers
                        if h not in ('Content-Length', 'Content-Type')
                        ]
         # Save the headers in case we need to modify them.
         state['headers'] = headers
         return start_response(status, headers, exc_info)
Ejemplo n.º 13
0
 def replacement_start_response(status, headers, exc_info=None):
     """Overrides the default response to make errors parsable."""
     try:
         status_code = int(status.split(' ')[0])
         state['status_code'] = status_code
     except (ValueError, TypeError):  # pragma: nocover
         raise Exception(_(
             'ErrorDocumentMiddleware received an invalid '
             'status %s') % status)
     else:
         if (state['status_code'] // 100) not in (2, 3):
             # Remove some headers so we can replace them later
             # when we have the full error message and can
             # compute the length.
             headers = [(h, v)
                        for (h, v) in headers
                        if h not in ('Content-Length', 'Content-Type')
                        ]
         # Save the headers in case we need to modify them.
         state['headers'] = headers
         return start_response(status, headers, exc_info)
Ejemplo n.º 14
0
    def get_image_id_by_broker_name(self, context, broker_name):

        broker_query = model_query(
            context,
            models.Broker).filter_by(active=True).filter_by(name=broker_name)

        try:
            selected_broker_id = broker_query.one().id

            # select the recently created image id
            metadata_query = (model_query(
                context,
                models.BrokerMetadata).filter_by(key='IMAGE').filter_by(
                    broker_id=selected_broker_id).order_by(
                        (models.BrokerMetadata.created_at.desc())).limit(1))
            selected_image = metadata_query.one()

        except sql_exception.NoResultFound:
            raise exception.NotFound(_("Broker was not found"))

        image_id = selected_image['value']
        return image_id
Ejemplo n.º 15
0
def ssh_connect(connection):
    """Method to connect to a remote system using ssh protocol.

    :param connection: a dict of connection parameters.
    :returns: paramiko.SSHClient -- an active ssh connection.
    :raises: SSHConnectFailed

    """
    try:
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        key_contents = connection.get('key_contents')
        if key_contents:
            data = six.moves.StringIO(key_contents)
            if "BEGIN RSA PRIVATE" in key_contents:
                pkey = paramiko.RSAKey.from_private_key(data)
            elif "BEGIN DSA PRIVATE" in key_contents:
                pkey = paramiko.DSSKey.from_private_key(data)
            else:
                # Can't include the key contents - secure material.
                raise ValueError(_("Invalid private key"))
        else:
            pkey = None
        ssh.connect(connection.get('host'),
                    username=connection.get('username'),
                    password=connection.get('password'),
                    port=connection.get('port', 22),
                    pkey=pkey,
                    key_filename=connection.get('key_filename'),
                    timeout=connection.get('timeout', 10))

        # send TCP keepalive packets every 20 seconds
        ssh.get_transport().set_keepalive(20)
    except Exception as e:
        LOG.debug("SSH connect failed: %s" % e)
        raise exception.SSHConnectFailed(host=connection.get('host'))

    return ssh
    def add_metadata(self, broker_id, image_id, sec_group):
        """Add broker metadata - image and sec group for the given broker_id.

        """
        if image_id is not None:
            metadata_value = {
                'key': models.MetadataKey.IMAGE,
                'value': image_id,
                'broker_id': broker_id
            }
            metadata = objects.BrokerMetadata(**metadata_value)
            metadata.create_broker_metadata(self.context)

        if sec_group is not None:
            metadata_value = {
                'key': models.MetadataKey.SEC_GROUP,
                'value': sec_group,
                'broker_id': broker_id
            }
            metadata = objects.BrokerMetadata(**metadata_value)
            metadata.create_broker_metadata(self.context)

        if image_id is None and sec_group is None:
            raise exception.Invalid(_("Requires atleast one argument"))
Ejemplo n.º 17
0
class Conflict(CueException):
    message = _('Conflict.')
    code = 409
Ejemplo n.º 18
0
class RequestEntityTooLarge(CueException):
    message = _('Request too large for server.')
    code = 413
Ejemplo n.º 19
0
class TemporaryFailure(CueException):
    message = _("Resource temporarily unavailable, please retry.")
    code = 503
Ejemplo n.º 20
0
class InvalidState(Conflict):
    message = _("Invalid resource state.")
Ejemplo n.º 21
0
class NodeAlreadyExists(Conflict):
    message = _("A node with UUID %(uuid)s already exists.")
Ejemplo n.º 22
0
class VmErrorException(CueException):
    message = _("VM is not in a building state")
Ejemplo n.º 23
0
class MissingKwargException(exception.CueException):
    message = _("%s %s")  # noqa
Ejemplo n.º 24
0
class NotFound(CueException):
    message = _("Not Found")
    code = 404
Ejemplo n.º 25
0
class InternalServerError(CueException):
    message = _("Internal Server Error")
    code = 500
Ejemplo n.º 26
0
 def test_remote_exception(self):
     e = Exception_Remote()
     msg = e.format_message()
     self.assertEqual(_("Remote Error"), msg)
Ejemplo n.º 27
0
class Exception_Remote(exception.CueException):
    message = _("Remote Error")
Ejemplo n.º 28
0
class OperationNotPermitted(NotAuthorized):
    message = _("Operation not permitted.")
Ejemplo n.º 29
0
    def post(self, data):
        """Create a new Cluster.

        :param data: cluster parameters within the request body.
        """
        context = pecan.request.context
        request_data = data.as_dict()
        cluster_flavor = request_data['flavor']

        if data.size <= 0:
            raise exception.Invalid(_("Invalid cluster size provided"))
        elif data.size > CONF.api.max_cluster_size:
            raise exception.RequestEntityTooLarge(
                _("Invalid cluster size, max size is: %d") %
                CONF.api.max_cluster_size)

        if len(data.network_id) > 1:
            raise exception.Invalid(_("Invalid number of network_id's"))

        # extract username/password
        if (data.authentication and data.authentication.type
                and data.authentication.token):
            auth_validator = auth_validate.AuthTokenValidator.validate_token(
                auth_type=data.authentication.type,
                token=data.authentication.token)
            if not auth_validator or not auth_validator.validate():
                raise exception.Invalid(
                    _("Invalid broker authentication "
                      "parameter(s)"))
        else:
            raise exception.Invalid(
                _("Missing broker authentication "
                  "parameter(s)"))

        default_rabbit_user = data.authentication.token['username']
        default_rabbit_pass = data.authentication.token['password']

        broker_name = CONF.default_broker_name

        # get the image id of default broker
        image_id = objects.BrokerMetadata.get_image_id_by_broker_name(
            context, broker_name)

        # validate cluster flavor
        self._validate_flavor(image_id, cluster_flavor)

        # convert 'network_id' from list to string type for objects/cluster
        # compatibility
        request_data['network_id'] = request_data['network_id'][0]

        # create new cluster object with required data from user
        new_cluster = objects.Cluster(**request_data)

        # create new cluster with node related data from user
        new_cluster.create(context)

        # retrieve cluster data
        cluster = get_complete_cluster(context, new_cluster.id)

        nodes = objects.Node.get_nodes_by_cluster_id(context, cluster.id)

        # create list with node id's for create cluster flow
        node_ids = [node.id for node in nodes]

        # prepare and post cluster create job to backend
        flow_kwargs = {
            'cluster_id': cluster.id,
            'node_ids': node_ids,
            'user_network_id': cluster.network_id[0],
            'management_network_id': CONF.management_network_id,
        }

        # generate unique erlang cookie to be used by all nodes in the new
        # cluster, erlang cookies are strings of up to 255 characters
        erlang_cookie = uuidutils.generate_uuid()

        job_args = {
            'tenant_id': new_cluster.project_id,
            'flavor': cluster.flavor,
            'image': image_id,
            'volume_size': cluster.volume_size,
            'port': '5672',
            'context': context.to_dict(),
            # TODO(sputnik13: this needs to come from the create request
            # and default to a configuration value rather than always using
            # config value
            'security_groups': [CONF.os_security_group],
            'port': CONF.rabbit_port,
            'key_name': CONF.openstack.os_key_name,
            'erlang_cookie': erlang_cookie,
            'default_rabbit_user': default_rabbit_user,
            'default_rabbit_pass': default_rabbit_pass,
        }
        job_client = task_flow_client.get_client_instance()
        # TODO(dagnello): might be better to use request_id for job_uuid
        job_uuid = uuidutils.generate_uuid()
        job_client.post(create_cluster,
                        job_args,
                        flow_kwargs=flow_kwargs,
                        tx_uuid=job_uuid)

        LOG.info(
            _LI('Create Cluster Request Cluster ID %(cluster_id)s '
                'Cluster size %(size)s network ID %(network_id)s '
                'Job ID %(job_id)s Broker name %(broker_name)s') %
            ({
                "cluster_id": cluster.id,
                "size": cluster.size,
                "network_id": cluster.network_id,
                "job_id": job_uuid,
                "broker_name": broker_name
            }))

        cluster.additional_information = []
        cluster.additional_information.append(
            dict(def_rabbit_user=default_rabbit_user))
        cluster.additional_information.append(
            dict(def_rabbit_pass=default_rabbit_pass))

        cluster.unset_empty_fields()
        return cluster
Ejemplo n.º 30
0
class VmBuildingException(CueException):
    message = _("VM is in building state")
Ejemplo n.º 31
0
class Invalid(CueException):
    message = _("Unacceptable parameters.")
    code = 400
Ejemplo n.º 32
0
class ConfigurationError(CueException):
    message = _("Configuration Error")
Ejemplo n.º 33
0
class NotAuthorized(CueException):
    message = _("Not authorized.")
    code = 403
Ejemplo n.º 34
0
 def validator(val, objclass=objclass):
     if val is None or isinstance(val, objclass):
         return val
     raise ValueError(
         _("An object of class %s is required here") % objclass)