Esempio n. 1
0
    def put(self, id, l7policy):
        """Updates a l7policy."""
        l7policy_dict = validate.sanitize_l7policy_api_args(
            l7policy.to_dict(render_unsets=False))
        context = pecan.request.context.get('octavia_context')
        # Make sure any specified redirect_pool_id exists
        if l7policy_dict.get('redirect_pool_id'):
            self._get_db_pool(context.session,
                              l7policy_dict['redirect_pool_id'])
        db_l7policy = self._get_db_l7policy(context.session, id)
        self._test_lb_and_listener_statuses(context.session)

        try:
            LOG.info(_LI("Sending Update of L7Policy %s to handler"), id)
            self.handler.update(db_l7policy,
                                l7policy_types.L7PolicyPUT(**l7policy_dict))
        except Exception:
            with excutils.save_and_reraise_exception(reraise=False):
                self.repositories.listener.update(
                    context.session,
                    self.listener_id,
                    operating_status=constants.ERROR)
        db_l7policy = self._get_db_l7policy(context.session, id)
        return self._convert_db_to_type(db_l7policy,
                                        l7policy_types.L7PolicyResponse)
Esempio n. 2
0
def create_l7policy(l7policy_dict, lb_id, listener_id):
    l7policy_dict = validate.sanitize_l7policy_api_args(l7policy_dict,
                                                        create=True)
    l7policy_dict['provisioning_status'] = constants.PENDING_CREATE
    l7policy_dict['operating_status'] = constants.OFFLINE
    if not l7policy_dict.get('id'):
        l7policy_dict['id'] = uuidutils.generate_uuid()
    l7policy_dict['listener_id'] = listener_id
    if l7policy_dict.get('redirect_pool'):
        pool_dict = l7policy_dict.pop('redirect_pool')
        prepped_pool = create_pool(pool_dict, lb_id)
        l7policy_dict['redirect_pool'] = prepped_pool
        l7policy_dict['redirect_pool_id'] = prepped_pool['id']
    rules = l7policy_dict.pop('rules', None)
    if rules:
        l7policy_dict['l7rules'] = rules
    if l7policy_dict.get('l7rules'):
        if (len(l7policy_dict.get('l7rules')) >
                constants.MAX_L7RULES_PER_L7POLICY):
            raise exceptions.TooManyL7RulesOnL7Policy(id=l7policy_dict['id'])
        prepped_l7rules = []
        for l7rule_dict in l7policy_dict.get('l7rules'):
            try:
                validate.l7rule_data(l7rule.L7RulePOST(**l7rule_dict))
            except Exception as e:
                raise exceptions.L7RuleValidation(error=e)
            prepped_l7rule = create_l7rule(l7rule_dict, l7policy_dict['id'])
            prepped_l7rules.append(prepped_l7rule)
    return l7policy_dict
Esempio n. 3
0
    def put(self, id, l7policy_):
        """Updates a l7policy."""
        l7policy = l7policy_.l7policy
        l7policy_dict = validate.sanitize_l7policy_api_args(
            l7policy.to_dict(render_unsets=False))
        # Reset renamed attributes
        for attr, val in l7policy_types.L7PolicyPUT._type_to_model_map.items():
            if val in l7policy_dict:
                l7policy_dict[attr] = l7policy_dict.pop(val)
        sanitized_l7policy = l7policy_types.L7PolicyPUT(**l7policy_dict)
        context = pecan.request.context.get('octavia_context')
        # Make sure any specified redirect_pool_id exists
        if l7policy_dict.get('redirect_pool_id'):
            self._get_db_pool(context.session,
                              l7policy_dict['redirect_pool_id'])
        db_l7policy = self._get_db_l7policy(context.session,
                                            id,
                                            show_deleted=False)
        load_balancer_id, listener_id = self._get_listener_and_loadbalancer_id(
            db_l7policy)
        project_id, provider = self._get_lb_project_id_provider(
            context.session, load_balancer_id)

        self._auth_validate_action(context, project_id, constants.RBAC_PUT)

        # Load the driver early as it also provides validation
        driver = driver_factory.get_driver(provider)

        with db_api.get_lock_session() as lock_session:

            self._test_lb_and_listener_statuses(lock_session,
                                                lb_id=load_balancer_id,
                                                listener_ids=[listener_id])

            # Prepare the data for the driver data model
            l7policy_dict = sanitized_l7policy.to_dict(render_unsets=False)
            l7policy_dict['id'] = id
            provider_l7policy_dict = (
                driver_utils.l7policy_dict_to_provider_dict(l7policy_dict))

            # Dispatch to the driver
            LOG.info("Sending update L7 Policy %s to provider %s", id,
                     driver.name)
            driver_utils.call_provider(
                driver.name, driver.l7policy_update,
                driver_dm.L7Policy.from_dict(provider_l7policy_dict))

            # Update the database to reflect what the driver just accepted
            sanitized_l7policy.provisioning_status = constants.PENDING_UPDATE
            db_l7policy_dict = sanitized_l7policy.to_dict(render_unsets=False)
            self.repositories.l7policy.update(lock_session, id,
                                              **db_l7policy_dict)

        # Force SQL alchemy to query the DB, otherwise we get inconsistent
        # results
        context.session.expire_all()
        db_l7policy = self._get_db_l7policy(context.session, id)
        result = self._convert_db_to_type(db_l7policy,
                                          l7policy_types.L7PolicyResponse)
        return l7policy_types.L7PolicyRootResponse(l7policy=result)
Esempio n. 4
0
 def test_sanitize_l7policy_api_args_action_rdr_pool_id(self):
     l7p = {'action': constants.L7POLICY_ACTION_REDIRECT_TO_POOL,
            'redirect_url': 'http://www.example.com/',
            'redirect_pool_id': 'test-pool',
            'redirect_pool': {
                'protocol': constants.PROTOCOL_HTTP,
                'lb_algorithm': constants.LB_ALGORITHM_ROUND_ROBIN}}
     s_l7p = validate.sanitize_l7policy_api_args(l7p)
     self.assertIsNone(s_l7p['redirect_url'])
     self.assertNotIn('redirect_pool', s_l7p.keys())
     self.assertIn('redirect_pool_id', s_l7p.keys())
Esempio n. 5
0
 def test_sanitize_l7policy_api_args_rdr_url(self):
     l7p = {'redirect_pool_id': None,
            'redirect_url': 'http://www.example.com/',
            'redirect_pool': None}
     s_l7p = validate.sanitize_l7policy_api_args(l7p)
     self.assertIsNone(s_l7p['redirect_pool_id'])
     self.assertNotIn('redirect_pool', s_l7p.keys())
     self.assertIn('redirect_url', s_l7p.keys())
     self.assertIn('action', s_l7p.keys())
     self.assertEqual(constants.L7POLICY_ACTION_REDIRECT_TO_URL,
                      s_l7p['action'])
Esempio n. 6
0
    def put(self, id, l7policy_):
        """Updates a l7policy."""
        l7policy = l7policy_.l7policy
        l7policy_dict = validate.sanitize_l7policy_api_args(
            l7policy.to_dict(render_unsets=False))
        # Reset renamed attributes
        for attr, val in l7policy_types.L7PolicyPUT._type_to_model_map.items():
            if val in l7policy_dict:
                l7policy_dict[attr] = l7policy_dict.pop(val)
        sanitized_l7policy = l7policy_types.L7PolicyPUT(**l7policy_dict)
        context = pecan.request.context.get('octavia_context')
        # Make sure any specified redirect_pool_id exists
        if l7policy_dict.get('redirect_pool_id'):
            self._get_db_pool(context.session,
                              l7policy_dict['redirect_pool_id'])
        db_l7policy = self._get_db_l7policy(context.session,
                                            id,
                                            show_deleted=False)
        load_balancer_id, listener_id = self._get_listener_and_loadbalancer_id(
            db_l7policy)

        self._auth_validate_action(context, db_l7policy.project_id,
                                   constants.RBAC_PUT)

        self._test_lb_and_listener_statuses(context.session,
                                            lb_id=load_balancer_id,
                                            listener_ids=[listener_id])
        self.repositories.l7policy.update(
            context.session,
            db_l7policy.id,
            provisioning_status=constants.PENDING_UPDATE)

        try:
            LOG.info("Sending Update of L7Policy %s to handler", id)
            self.handler.update(db_l7policy, sanitized_l7policy)
        except Exception:
            with excutils.save_and_reraise_exception(
                    reraise=False), db_api.get_lock_session() as lock_session:
                self._reset_lb_and_listener_statuses(
                    lock_session,
                    lb_id=load_balancer_id,
                    listener_id=db_l7policy.listener_id)
                # L7Policy now goes to ERROR
                self.repositories.l7policy.update(
                    lock_session,
                    db_l7policy.id,
                    provisioning_status=constants.ERROR)
        db_l7policy = self._get_db_l7policy(context.session, id)
        result = self._convert_db_to_type(db_l7policy,
                                          l7policy_types.L7PolicyResponse)
        return l7policy_types.L7PolicyRootResponse(l7policy=result)
Esempio n. 7
0
    def update(self, session, id, **model_kwargs):
        with session.begin(subtransactions=True):
            l7policy_db = session.query(self.model_class).filter_by(
                id=id).first()
            if not l7policy_db:
                raise exceptions.NotFound(
                    resource=data_models.L7Policy._name(), id=id)

            # Necessary to work around unexpected / idiotic behavior of
            # the SQLAlchemy Orderinglist extension if the position changes.
            position = model_kwargs.pop('position', None)
            if position == l7policy_db.position:
                position = None

            model_kwargs.update(listener_id=l7policy_db.listener_id)
            l7policy = self.model_class(
                **validate.sanitize_l7policy_api_args(model_kwargs))
            self._validate_l7policy_pool_data(session, l7policy)

            if l7policy.action:
                model_kwargs.update(action=l7policy.action)
                if l7policy.action == constants.L7POLICY_ACTION_REJECT:
                    model_kwargs.update(redirect_url=None)
                    model_kwargs.update(redirect_pool_id=None)
                elif (l7policy.action ==
                        constants.L7POLICY_ACTION_REDIRECT_TO_URL):
                    model_kwargs.update(redirect_pool_id=None)
                elif (l7policy.action ==
                        constants.L7POLICY_ACTION_REDIRECT_TO_POOL):
                    model_kwargs.update(redirect_url=None)

            l7policy_db.update(model_kwargs)

        # Position manipulation must happen outside the other alterations
        # in the previous transaction
        if position is not None:
            listener = (session.query(models.Listener).
                        filter_by(id=l7policy_db.listener_id).first())
            # Immediate refresh, as we have found that sqlalchemy will
            # sometimes cache the above query
            session.refresh(listener)
            with session.begin(subtransactions=True):
                l7policy_db = listener.l7policies.pop(l7policy_db.position - 1)
                listener.l7policies.insert(position - 1, l7policy_db)
            listener.l7policies.reorder()

        return self.get(session, id=l7policy.id)
Esempio n. 8
0
    def update(self, session, id, **model_kwargs):
        with session.begin(subtransactions=True):
            l7policy_db = session.query(
                self.model_class).filter_by(id=id).first()
            if not l7policy_db:
                raise exceptions.NotFound(
                    resource=data_models.L7Policy._name(), id=id)

            # Necessary to work around unexpected / idiotic behavior of
            # the SQLAlchemy Orderinglist extension if the position changes.
            position = model_kwargs.pop('position', None)
            if position == l7policy_db.position:
                position = None

            model_kwargs.update(listener_id=l7policy_db.listener_id)
            l7policy = self.model_class(
                **validate.sanitize_l7policy_api_args(model_kwargs))
            self._validate_l7policy_pool_data(session, l7policy)

            if l7policy.action:
                model_kwargs.update(action=l7policy.action)
                if l7policy.action == constants.L7POLICY_ACTION_REJECT:
                    model_kwargs.update(redirect_url=None)
                    model_kwargs.update(redirect_pool_id=None)
                elif (l7policy.action ==
                      constants.L7POLICY_ACTION_REDIRECT_TO_URL):
                    model_kwargs.update(redirect_pool_id=None)
                elif (l7policy.action ==
                      constants.L7POLICY_ACTION_REDIRECT_TO_POOL):
                    model_kwargs.update(redirect_url=None)

            l7policy_db.update(model_kwargs)

        # Position manipulation must happen outside the other alterations
        # in the previous transaction
        if position is not None:
            listener = (session.query(
                models.Listener).filter_by(id=l7policy_db.listener_id).first())
            # Immediate refresh, as we have found that sqlalchemy will
            # sometimes cache the above query
            session.refresh(listener)
            with session.begin(subtransactions=True):
                l7policy_db = listener.l7policies.pop(l7policy_db.position - 1)
                listener.l7policies.insert(position - 1, l7policy_db)
            listener.l7policies.reorder()

        return self.get(session, id=l7policy.id)
Esempio n. 9
0
    def post(self, l7policy):
        """Creates a l7policy on a listener."""
        context = pecan.request.context.get('octavia_context')

        l7policy_dict = validate.sanitize_l7policy_api_args(
            l7policy.to_dict(render_unsets=True), create=True)
        # Make sure any pool specified by redirect_pool_id exists
        if l7policy_dict.get('redirect_pool_id'):
            self._get_db_pool(context.session,
                              l7policy_dict['redirect_pool_id'])
        l7policy_dict = db_prepare.create_l7policy(l7policy_dict,
                                                   self.load_balancer_id,
                                                   self.listener_id)
        self._test_lb_and_listener_statuses(context.session)

        try:
            db_l7policy = self.repositories.l7policy.create(
                context.session, **l7policy_dict)
        except oslo_exc.DBDuplicateEntry as de:
            # Setting LB and Listener back to active because this is just a
            # validation failure
            self.repositories.load_balancer.update(
                context.session,
                self.load_balancer_id,
                provisioning_status=constants.ACTIVE)
            self.repositories.listener.update(
                context.session,
                self.listener_id,
                provisioning_status=constants.ACTIVE)
            if ['id'] == de.columns:
                raise exceptions.IDAlreadyExists()
        try:
            LOG.info(_LI("Sending Creation of L7Policy %s to handler"),
                     db_l7policy.id)
            self.handler.create(db_l7policy)
        except Exception:
            with excutils.save_and_reraise_exception(reraise=False):
                self.repositories.listener.update(
                    context.session,
                    self.listener_id,
                    operating_status=constants.ERROR)
        db_l7policy = self._get_db_l7policy(context.session, db_l7policy.id)
        return self._convert_db_to_type(db_l7policy,
                                        l7policy_types.L7PolicyResponse)
Esempio n. 10
0
    def post(self, l7policy):
        """Creates a l7policy on a listener."""
        context = pecan.request.context.get('octavia_context')
        l7policy_dict = validate.sanitize_l7policy_api_args(
            l7policy.to_dict(render_unsets=True), create=True)
        # Make sure any pool specified by redirect_pool_id exists
        if l7policy_dict.get('redirect_pool_id'):
            self._get_db_pool(
                context.session, l7policy_dict['redirect_pool_id'])
        l7policy_dict = db_prepare.create_l7policy(l7policy_dict,
                                                   self.load_balancer_id,
                                                   self.listener_id)
        self._test_lb_and_listener_statuses(context.session)

        try:
            db_l7policy = self.repositories.l7policy.create(context.session,
                                                            **l7policy_dict)
        except oslo_exc.DBDuplicateEntry as de:
            # Setting LB and Listener back to active because this is just a
            # validation failure
            self.repositories.load_balancer.update(
                context.session, self.load_balancer_id,
                provisioning_status=constants.ACTIVE)
            self.repositories.listener.update(
                context.session, self.listener_id,
                provisioning_status=constants.ACTIVE)
            if ['id'] == de.columns:
                raise exceptions.IDAlreadyExists()
        try:
            LOG.info(_LI("Sending Creation of L7Policy %s to handler"),
                     db_l7policy.id)
            self.handler.create(db_l7policy)
        except Exception:
            with excutils.save_and_reraise_exception(reraise=False):
                self.repositories.listener.update(
                    context.session, self.listener_id,
                    operating_status=constants.ERROR)
        db_l7policy = self._get_db_l7policy(context.session, db_l7policy.id)
        return self._convert_db_to_type(db_l7policy,
                                        l7policy_types.L7PolicyResponse)
Esempio n. 11
0
    def create(self, session, **model_kwargs):
        with session.begin(subtransactions=True):
            # We must append the new policy to the end of the collection. We
            # later re-insert it wherever it was requested to appear in order.
            # This is to work around unexpected / idiotic behavior of the
            # SQLAlchemy orderinglist extension.
            position = model_kwargs.pop('position', None)
            model_kwargs.update(position=constants.MAX_POLICY_POSITION)
            if not model_kwargs.get('id'):
                model_kwargs.update(id=uuidutils.generate_uuid())
            if model_kwargs.get('redirect_pool_id'):
                pool_db = session.query(models.Pool).filter_by(
                    id=model_kwargs.get('redirect_pool_id')).first()
                model_kwargs.update(redirect_pool=pool_db)
            l7policy = self.model_class(
                **validate.sanitize_l7policy_api_args(model_kwargs,
                                                      create=True))
            self._validate_l7policy_pool_data(session, l7policy)
            session.add(l7policy)
            session.flush()

        # Must be done outside the transaction which creates the L7Policy
        listener = (session.query(models.Listener).
                    filter_by(id=l7policy.listener_id).first())
        # Immediate refresh, as we have found that sqlalchemy will sometimes
        # cache the above query
        session.refresh(listener)
        session.refresh(l7policy)

        if position is not None and position < len(listener.l7policies) + 1:
            with session.begin(subtransactions=True):
                # New L7Policy will always be at the end of the list
                l7policy_db = listener.l7policies.pop()
                listener.l7policies.insert(position - 1, l7policy_db)

        listener.l7policies.reorder()
        return self.get(session, id=l7policy.id)
Esempio n. 12
0
    def put(self, id, l7policy):
        """Updates a l7policy."""
        l7policy_dict = validate.sanitize_l7policy_api_args(
            l7policy.to_dict(render_unsets=False))
        context = pecan.request.context.get('octavia_context')
        # Make sure any specified redirect_pool_id exists
        if l7policy_dict.get('redirect_pool_id'):
            self._get_db_pool(
                context.session, l7policy_dict['redirect_pool_id'])
        db_l7policy = self._get_db_l7policy(context.session, id)
        self._test_lb_and_listener_statuses(context.session)

        try:
            LOG.info(_LI("Sending Update of L7Policy %s to handler"), id)
            self.handler.update(
                db_l7policy, l7policy_types.L7PolicyPUT(**l7policy_dict))
        except Exception:
            with excutils.save_and_reraise_exception(reraise=False):
                self.repositories.listener.update(
                    context.session, self.listener_id,
                    operating_status=constants.ERROR)
        db_l7policy = self._get_db_l7policy(context.session, id)
        return self._convert_db_to_type(db_l7policy,
                                        l7policy_types.L7PolicyResponse)
Esempio n. 13
0
def create_l7policy(l7policy_dict, lb_id, listener_id):
    l7policy_dict = validate.sanitize_l7policy_api_args(l7policy_dict,
                                                        create=True)
    if not l7policy_dict.get('id'):
        l7policy_dict['id'] = uuidutils.generate_uuid()
    l7policy_dict['listener_id'] = listener_id
    if l7policy_dict.get('redirect_pool'):
        pool_dict = l7policy_dict.pop('redirect_pool')
        prepped_pool = create_pool(pool_dict, lb_id)
        l7policy_dict['redirect_pool'] = prepped_pool
        l7policy_dict['redirect_pool_id'] = prepped_pool['id']
    if l7policy_dict.get('l7rules'):
        if (len(l7policy_dict.get('l7rules')) >
                constants.MAX_L7RULES_PER_L7POLICY):
            raise exceptions.TooManyL7RulesOnL7Policy(id=l7policy_dict['id'])
        prepped_l7rules = []
        for l7rule_dict in l7policy_dict.get('l7rules'):
            try:
                validate.l7rule_data(l7rule.L7RulePOST(**l7rule_dict))
            except Exception as e:
                raise exceptions.L7RuleValidation(error=e)
            prepped_l7rule = create_l7rule(l7rule_dict, l7policy_dict['id'])
            prepped_l7rules.append(prepped_l7rule)
    return l7policy_dict
Esempio n. 14
0
    def create(self, session, **model_kwargs):
        with session.begin(subtransactions=True):
            # We must append the new policy to the end of the collection. We
            # later re-insert it wherever it was requested to appear in order.
            # This is to work around unexpected / idiotic behavior of the
            # SQLAlchemy orderinglist extension.
            position = model_kwargs.pop('position', None)
            model_kwargs.update(position=constants.MAX_POLICY_POSITION)
            if not model_kwargs.get('id'):
                model_kwargs.update(id=uuidutils.generate_uuid())
            if model_kwargs.get('redirect_pool_id'):
                pool_db = session.query(models.Pool).filter_by(
                    id=model_kwargs.get('redirect_pool_id')).first()
                model_kwargs.update(redirect_pool=pool_db)
            l7policy = self.model_class(**validate.sanitize_l7policy_api_args(
                model_kwargs, create=True))
            self._validate_l7policy_pool_data(session, l7policy)
            session.add(l7policy)
            session.flush()

        # Must be done outside the transaction which creates the L7Policy
        listener = (session.query(
            models.Listener).filter_by(id=l7policy.listener_id).first())
        # Immediate refresh, as we have found that sqlalchemy will sometimes
        # cache the above query
        session.refresh(listener)
        session.refresh(l7policy)

        if position is not None and position < len(listener.l7policies) + 1:
            with session.begin(subtransactions=True):
                # New L7Policy will always be at the end of the list
                l7policy_db = listener.l7policies.pop()
                listener.l7policies.insert(position - 1, l7policy_db)

        listener.l7policies.reorder()
        return self.get(session, id=l7policy.id)
Esempio n. 15
0
    def put(self, id, l7policy_):
        """Updates a l7policy."""
        l7policy = l7policy_.l7policy
        l7policy_dict = validate.sanitize_l7policy_api_args(
            l7policy.to_dict(render_unsets=False))
        # Reset renamed attributes
        for attr, val in l7policy_types.L7PolicyPUT._type_to_model_map.items():
            if val in l7policy_dict:
                l7policy_dict[attr] = l7policy_dict.pop(val)
        sanitized_l7policy = l7policy_types.L7PolicyPUT(**l7policy_dict)
        context = pecan.request.context.get('octavia_context')
        # Make sure any specified redirect_pool_id exists
        if l7policy_dict.get('redirect_pool_id'):
            db_pool = self._get_db_pool(
                context.session, l7policy_dict['redirect_pool_id'])
            self._escape_l7policy_udp_pool_request(db_pool)
        db_l7policy = self._get_db_l7policy(context.session, id,
                                            show_deleted=False)
        load_balancer_id, listener_id = self._get_listener_and_loadbalancer_id(
            db_l7policy)
        project_id, provider = self._get_lb_project_id_provider(
            context.session, load_balancer_id)

        self._auth_validate_action(context, project_id, constants.RBAC_PUT)

        # Load the driver early as it also provides validation
        driver = driver_factory.get_driver(provider)

        with db_api.get_lock_session() as lock_session:

            self._test_lb_and_listener_statuses(lock_session,
                                                lb_id=load_balancer_id,
                                                listener_ids=[listener_id])

            # Prepare the data for the driver data model
            l7policy_dict = sanitized_l7policy.to_dict(render_unsets=False)
            l7policy_dict['id'] = id
            provider_l7policy_dict = (
                driver_utils.l7policy_dict_to_provider_dict(l7policy_dict))

            # Also prepare the baseline object data
            old_provider_l7policy = (
                driver_utils.db_l7policy_to_provider_l7policy(db_l7policy))

            # Dispatch to the driver
            LOG.info("Sending update L7 Policy %s to provider %s",
                     id, driver.name)
            driver_utils.call_provider(
                driver.name, driver.l7policy_update,
                old_provider_l7policy,
                driver_dm.L7Policy.from_dict(provider_l7policy_dict))

            # Update the database to reflect what the driver just accepted
            sanitized_l7policy.provisioning_status = constants.PENDING_UPDATE
            db_l7policy_dict = sanitized_l7policy.to_dict(render_unsets=False)
            self.repositories.l7policy.update(lock_session, id,
                                              **db_l7policy_dict)

        # Force SQL alchemy to query the DB, otherwise we get inconsistent
        # results
        context.session.expire_all()
        db_l7policy = self._get_db_l7policy(context.session, id)
        result = self._convert_db_to_type(db_l7policy,
                                          l7policy_types.L7PolicyResponse)
        return l7policy_types.L7PolicyRootResponse(l7policy=result)