Ejemplo n.º 1
0
    def put(self, id, flavor_):
        flavor = flavor_.flavor
        context = pecan_request.context.get('octavia_context')
        self._auth_validate_action(context, context.project_id,
                                   constants.RBAC_PUT)
        if id == constants.NIL_UUID:
            raise exceptions.NotFound(resource='Flavor', id=constants.NIL_UUID)
        lock_session = db_api.get_session(autocommit=False)
        try:
            flavor_dict = flavor.to_dict(render_unsets=False)
            if flavor_dict:
                self.repositories.flavor.update(lock_session, id,
                                                **flavor_dict)
            lock_session.commit()
        except Exception:
            with excutils.save_and_reraise_exception():
                lock_session.rollback()

        # Force SQL alchemy to query the DB, otherwise we get inconsistent
        # results
        context.session.expire_all()
        db_flavor = self._get_db_flavor(context.session, id)
        result = self._convert_db_to_type(db_flavor,
                                          flavor_types.FlavorResponse)
        return flavor_types.FlavorRootResponse(flavor=result)
Ejemplo n.º 2
0
    def post(self, member_):
        """Creates a pool member on a pool."""
        member = member_.member
        context = pecan.request.context.get('octavia_context')

        validate.ip_not_reserved(member.address)

        # Validate member subnet
        if member.subnet_id and not validate.subnet_exists(member.subnet_id):
            raise exceptions.NotFound(resource='Subnet', id=member.subnet_id)
        pool = self.repositories.pool.get(context.session, id=self.pool_id)
        member.project_id, provider = self._get_lb_project_id_provider(
            context.session, pool.load_balancer_id)

        self._auth_validate_action(context, member.project_id,
                                   constants.RBAC_POST)

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

        lock_session = db_api.get_session(autocommit=False)
        try:
            if self.repositories.check_clusterquota_met(
                    lock_session, data_models.Member,
                    base_res_id=self.pool_id):
                raise exceptions.ClusterQuotaException(
                    resource=data_models.Member._name())
            if self.repositories.check_quota_met(context.session, lock_session,
                                                 data_models.Member,
                                                 member.project_id):
                raise exceptions.QuotaException(
                    resource=data_models.Member._name())

            member_dict = db_prepare.create_member(
                member.to_dict(render_unsets=True), self.pool_id,
                bool(pool.health_monitor))

            self._test_lb_and_listener_and_pool_statuses(lock_session)

            db_member = self._validate_create_member(lock_session, member_dict)

            # Prepare the data for the driver data model
            provider_member = (
                driver_utils.db_member_to_provider_member(db_member))

            # Dispatch to the driver
            LOG.info("Sending create Member %s to provider %s", db_member.id,
                     driver.name)
            driver_utils.call_provider(driver.name, driver.member_create,
                                       provider_member)

            lock_session.commit()
        except Exception:
            with excutils.save_and_reraise_exception():
                lock_session.rollback()

        db_member = self._get_db_member(context.session, db_member.id)
        result = self._convert_db_to_type(db_member,
                                          member_types.MemberResponse)
        return member_types.MemberRootResponse(member=result)
Ejemplo n.º 3
0
 def test_exception(self):
     try:
         raise exc.NotFound()
     except exc.NotFound:
         pass
     else:
         raise Exception()
Ejemplo n.º 4
0
    def put(self, name, availability_zone_):
        availability_zone = availability_zone_.availability_zone
        context = pecan_request.context.get('octavia_context')
        self._auth_validate_action(context, context.project_id,
                                   constants.RBAC_PUT)
        if name == constants.NIL_UUID:
            raise exceptions.NotFound(resource='Availability Zone',
                                      id=constants.NIL_UUID)
        lock_session = db_api.get_session(autocommit=False)
        try:
            availability_zone_dict = availability_zone.to_dict(
                render_unsets=False)
            if availability_zone_dict:
                self.repositories.availability_zone.update(
                    lock_session, name, **availability_zone_dict)
            lock_session.commit()
        except Exception:
            with excutils.save_and_reraise_exception():
                lock_session.rollback()

        # Force SQL alchemy to query the DB, otherwise we get inconsistent
        # results
        context.session.expire_all()
        db_availability_zone = self._get_db_availability_zone(
            context.session, name)
        result = self._convert_db_to_type(
            db_availability_zone,
            availability_zone_types.AvailabilityZoneResponse)
        return availability_zone_types.AvailabilityZoneRootResponse(
            availability_zone=result)
Ejemplo n.º 5
0
    def post(self, member_):
        """Creates a pool member on a pool."""
        member = member_.member
        context = pecan.request.context.get('octavia_context')
        # Validate member subnet
        if member.subnet_id and not validate.subnet_exists(member.subnet_id):
            raise exceptions.NotFound(resource='Subnet', id=member.subnet_id)
        pool = self.repositories.pool.get(context.session, id=self.pool_id)
        member.project_id = self._get_lb_project_id(context.session,
                                                    pool.load_balancer_id)

        self._auth_validate_action(context, member.project_id,
                                   constants.RBAC_POST)

        lock_session = db_api.get_session(autocommit=False)
        try:
            if self.repositories.check_quota_met(context.session, lock_session,
                                                 data_models.Member,
                                                 member.project_id):
                raise exceptions.QuotaException

            member_dict = db_prepare.create_member(
                member.to_dict(render_unsets=True), self.pool_id,
                bool(pool.health_monitor))

            self._test_lb_and_listener_and_pool_statuses(lock_session)

            db_member = self._validate_create_member(lock_session, member_dict)
            lock_session.commit()
        except Exception:
            with excutils.save_and_reraise_exception():
                lock_session.rollback()

        return self._send_member_to_handler(context.session, db_member)
Ejemplo n.º 6
0
 def _validate_pool(self, session, pool_id):
     """Validate pool given exists on same load balancer as listener."""
     db_pool = self.repositories.pool.get(
         session, load_balancer_id=self.load_balancer_id, id=pool_id)
     if not db_pool:
         raise exceptions.NotFound(resource=data_models.Pool._name(),
                                   id=pool_id)
Ejemplo n.º 7
0
def get_interface_name(ip_address, net_ns=None):
    """Gets the interface name from an IP address.

    :param ip_address: The IP address to lookup.
    :param net_ns: The network namespace to find the interface in.
    :returns: The interface name.
    :raises exceptions.InvalidIPAddress: Invalid IP address provided.
    :raises octavia.common.exceptions.NotFound: No interface was found.
    """
    # We need to normalize the address as IPv6 has multiple representations
    # fe80:0000:0000:0000:f816:3eff:fef2:2058 == fe80::f816:3eff:fef2:2058
    try:
        normalized_addr = ipaddress.ip_address(ip_address).compressed
    except ValueError as e:
        raise exceptions.InvalidIPAddress(ip_addr=ip_address) from e

    if net_ns:
        with pyroute2.NetNS(net_ns) as rtnl_api:
            interface = _find_interface(ip_address, rtnl_api, normalized_addr)
    else:
        with pyroute2.IPRoute() as rtnl_api:
            interface = _find_interface(ip_address, rtnl_api, normalized_addr)
    if interface is not None:
        return interface
    raise exceptions.NotFound(resource='IP address', id=ip_address)
Ejemplo n.º 8
0
 def delete(self, id):
     """Deletes a pool member."""
     session = db_api.get_session()
     db_member = self.repositories.member.get(session, id=id)
     if not db_member:
         LOG.info(_LI("Member %s not found"), id)
         raise exceptions.NotFound(resource=data_models.Member._name(),
                                   id=id)
     # Verify load balancer is in a mutable status.  If so it can be assumed
     # that the listener is also in a mutable status because a load balancer
     # will only be ACTIVE when all its listeners as ACTIVE.
     if not self.repositories.test_and_set_lb_and_listener_prov_status(
             session, self.load_balancer_id, self.listener_id,
             constants.PENDING_UPDATE, constants.PENDING_UPDATE):
         LOG.info(
             _LI("Member %s cannot be deleted because its Load "
                 "Balancer is in an immutable state."), id)
         lb_repo = self.repositories.load_balancer
         db_lb = lb_repo.get(session, id=self.load_balancer_id)
         raise exceptions.ImmutableObject(resource=db_lb._name(),
                                          id=self.load_balancer_id)
     db_member = self.repositories.member.get(session, id=id)
     try:
         LOG.info(_LI("Sending Deletion of Member %s to handler"),
                  db_member.id)
         self.handler.delete(db_member)
     except Exception:
         with excutils.save_and_reraise_exception(reraise=False):
             self.repositories.listener.update(
                 session,
                 self.listener_id,
                 operating_status=constants.ERROR)
     db_member = self.repositories.member.get(session, id=id)
     return self._convert_db_to_type(db_member, member_types.MemberResponse)
Ejemplo n.º 9
0
    def _lookup(self, lb_id, *remainder):
        """Overridden pecan _lookup method for custom routing.

        Verifies that the load balancer passed in the url exists, and if so
        decides which controller, if any, should control be passed.
        """
        context = pecan.request.context.get('octavia_context')

        possible_remainder = ('listeners', 'pools', 'delete_cascade', 'stats')
        if lb_id and len(remainder) and (remainder[0] in possible_remainder):
            controller = remainder[0]
            remainder = remainder[1:]
            db_lb = self.repositories.load_balancer.get(context.session,
                                                        id=lb_id)
            if not db_lb:
                LOG.info(_LI("Load Balancer %s was not found."), lb_id)
                raise exceptions.NotFound(
                    resource=data_models.LoadBalancer._name(), id=lb_id)
            if controller == 'listeners':
                return listener.ListenersController(
                    load_balancer_id=db_lb.id), remainder
            elif controller == 'pools':
                return pool.PoolsController(
                    load_balancer_id=db_lb.id), remainder
            elif (controller == 'delete_cascade'):
                return LBCascadeDeleteController(db_lb.id), ''
            elif (controller == 'stats'):
                return lb_stats.LoadBalancerStatisticsController(
                    loadbalancer_id=db_lb.id), remainder
Ejemplo n.º 10
0
    def _lookup(self, listener_id, *remainder):
        """Overridden pecan _lookup method for custom routing.

        Verifies that the listener passed in the url exists, and if so decides
        which controller, if any, should control be passed.
        """
        context = pecan.request.context.get('octavia_context')
        is_children = (
            listener_id and remainder
            and (remainder[0] == 'pools' or
                 (remainder[0] == 'l7policies' or remainder[0] == 'stats')))
        if is_children:
            controller = remainder[0]
            remainder = remainder[1:]
            db_listener = self.repositories.listener.get(context.session,
                                                         id=listener_id)
            if not db_listener:
                LOG.info("Listener %s not found.", listener_id)
                raise exceptions.NotFound(
                    resource=data_models.Listener._name(), id=listener_id)
            if controller == 'pools':
                return pool.PoolsController(
                    load_balancer_id=self.load_balancer_id,
                    listener_id=db_listener.id), remainder
            elif controller == 'l7policies':
                return l7policy.L7PolicyController(
                    load_balancer_id=self.load_balancer_id,
                    listener_id=db_listener.id), remainder
            elif controller == 'stats':
                return listener_statistics.ListenerStatisticsController(
                    listener_id=db_listener.id), remainder
        return None
Ejemplo n.º 11
0
 def _get_db_obj(session, repo, data_model, id):
     """Gets an object from the database and returns it."""
     db_obj = repo.get(session, id=id)
     if not db_obj:
         LOG.info(_LI("%s not found"), data_model._name() + id)
         raise exceptions.NotFound(resource=data_model._name(), id=id)
     return db_obj
Ejemplo n.º 12
0
 def _pool_check(self, session, pool_id, lb_id, project_id):
     """Sanity checks for the redirect_pool if specified."""
     pool_db = (session.query(models.Pool).filter_by(id=pool_id).filter_by(
         project_id=project_id).filter_by(load_balancer_id=lb_id).first())
     if not pool_db:
         raise exceptions.NotFound(resource=data_models.Pool._name(),
                                   id=pool_id)
Ejemplo n.º 13
0
    def update(self, session, id, **model_kwargs):
        with session.begin(subtransactions=True):
            l7rule_db = session.query(
                self.model_class).filter_by(id=id).first()
            if not l7rule_db:
                raise exceptions.NotFound(resource=data_models.L7Rule._name(),
                                          id=id)

            l7rule_dict = l7rule_db.to_data_model().to_dict()
            # Ignore values that are None
            for k, v in model_kwargs.items():
                if v is not None:
                    l7rule_dict.update({k: v})
            # Clear out the 'key' attribute for rule types that don't use it.
            if ('type' in l7rule_dict.keys() and l7rule_dict['type']
                    in (constants.L7RULE_TYPE_HOST_NAME,
                        constants.L7RULE_TYPE_PATH,
                        constants.L7RULE_TYPE_FILE_TYPE)):
                l7rule_dict['key'] = None
                model_kwargs.update({'key': None})
            validate.l7rule_data(self.model_class(**l7rule_dict))
            l7rule_db.update(model_kwargs)

        l7rule_db = self.get(session, id=id)
        return l7rule_db
Ejemplo n.º 14
0
 def put(self, id, load_balancer):
     """Updates a load balancer."""
     session = db_api.get_session()
     # Purely to make lines smaller length
     lb_repo = self.repositories.load_balancer
     db_lb = self.repositories.load_balancer.get(session, id=id)
     if not db_lb:
         LOG.info(_LI("Load Balancer %s was not found."), id)
         raise exceptions.NotFound(
             resource=data_models.LoadBalancer._name(), id=id)
     # Check load balancer is in a mutable status
     if not lb_repo.test_and_set_provisioning_status(
             session, id, constants.PENDING_UPDATE):
         LOG.info(_LI("Load Balancer %s is immutable."), id)
         raise exceptions.ImmutableObject(resource=db_lb._name(),
                                          id=id)
     try:
         LOG.info(_LI("Sending updated Load Balancer %s to the handler"),
                  id)
         self.handler.update(db_lb, load_balancer)
     except Exception:
         with excutils.save_and_reraise_exception(reraise=False):
             self.repositories.load_balancer.update(
                 session, id, provisioning_status=constants.ERROR)
     lb = self.repositories.load_balancer.get(session, id=id)
     return self._convert_db_to_type(lb, lb_types.LoadBalancerResponse)
Ejemplo n.º 15
0
    def _lookup(self, pool_id, *remainder):
        """Overriden pecan _lookup method for custom routing.

        Verifies that the pool passed in the url exists, and if so decides
        which controller, if any, should control be passed.
        """
        context = pecan.request.context.get('octavia_context')
        if pool_id and len(remainder) and (remainder[0] == 'members' or
                                           remainder[0] == 'healthmonitor'):
            controller = remainder[0]
            remainder = remainder[1:]
            db_pool = self.repositories.pool.get(context.session, id=pool_id)
            if not db_pool:
                LOG.info(_LI("Pool %s not found."), pool_id)
                raise exceptions.NotFound(resource=data_models.Pool._name(),
                                          id=pool_id)
            if controller == 'members':
                return member.MembersController(
                    load_balancer_id=self.load_balancer_id,
                    pool_id=db_pool.id,
                    listener_id=self.listener_id), remainder
            elif controller == 'healthmonitor':
                return health_monitor.HealthMonitorController(
                    load_balancer_id=self.load_balancer_id,
                    pool_id=db_pool.id,
                    listener_id=self.listener_id), remainder
Ejemplo n.º 16
0
 def get(self, id):
     """Gets a pool's details."""
     session = db_api.get_session()
     db_pool = self.repositories.pool.get(session, id=id)
     if not db_pool:
         LOG.info(_LI("Pool %s not found."), id)
         raise exceptions.NotFound(resource=data_models.Pool._name(), id=id)
     return self._convert_db_to_type(db_pool, pool_types.PoolResponse)
Ejemplo n.º 17
0
 def _get_db_amp(self, session, amp_id):
     """Gets the current amphora object from the database."""
     db_amp = self.repositories.amphora.get(session, id=amp_id)
     if not db_amp:
         LOG.info("Amphora %s was not found", amp_id)
         raise exceptions.NotFound(resource=data_models.Amphora._name(),
                                   id=amp_id)
     return db_amp
Ejemplo n.º 18
0
 def _get_db_hm(self, session, hm_id):
     """Gets the current health monitor object from the database."""
     db_hm = self.repositories.health_monitor.get(session, id=hm_id)
     if not db_hm:
         LOG.info(_LI("Health Monitor %s was not found"), hm_id)
         raise exceptions.NotFound(
             resource=data_models.HealthMonitor._name(), id=hm_id)
     return db_hm
Ejemplo n.º 19
0
 def _get_db_obj(session, repo, data_model, id):
     """Gets an object from the database and returns it."""
     db_obj = repo.get(session, id=id)
     if not db_obj:
         LOG.exception(
             _LE("{name} {id} not found").format(name=data_model._name(),
                                                 id=id))
         raise exceptions.NotFound(resource=data_model._name(), id=id)
     return db_obj
Ejemplo n.º 20
0
 def _get_db_listener(self, session, id):
     """Gets a listener object from the database."""
     db_listener = self.repositories.listener.get(
         session, load_balancer_id=self.load_balancer_id, id=id)
     if not db_listener:
         LOG.info(_LI("Listener %s not found."), id)
         raise exceptions.NotFound(resource=data_models.Listener._name(),
                                   id=id)
     return db_listener
Ejemplo n.º 21
0
 def get(self, id):
     """Gets a single pool member's details."""
     session = db_api.get_session()
     db_member = self.repositories.member.get(session, id=id)
     if not db_member:
         LOG.info(_LI("Member %s not found"), id)
         raise exceptions.NotFound(resource=data_models.Member._name(),
                                   id=id)
     return self._convert_db_to_type(db_member, member_types.MemberResponse)
Ejemplo n.º 22
0
 def _get_db_obj(session, repo, data_model, id):
     """Gets an object from the database and returns it."""
     db_obj = repo.get(session, id=id)
     if not db_obj:
         LOG.exception('%(name)s %(id)s not found',
                       {'name': data_model._name(), 'id': id})
         raise exceptions.NotFound(
             resource=data_model._name(), id=id)
     return db_obj
Ejemplo n.º 23
0
 def _get_db_availability_zone(self, session, name):
     """Get an availability zone from the database."""
     db_obj = self.repositories.availability_zone.get(session, name=name)
     if not db_obj:
         LOG.debug('%(obj_name)s %(name)s not found', {
             'obj_name': data_models.AvailabilityZone._name(),
             'name': name
         })
         raise exceptions.NotFound(
             resource=data_models.AvailabilityZone._name(), id=name)
     return db_obj
Ejemplo n.º 24
0
 def _get_db_ls(self, session):
     """Gets the current listener statistics object from the database."""
     db_ls = self.repositories.listener_stats.get(
         session, listener_id=self.listener_id)
     if not db_ls:
         LOG.info(_LI("Listener Statistics for Listener %s was not found"),
                  self.listener_id)
         raise exceptions.NotFound(
             resource=data_models.ListenerStatistics._name(),
             id=self.listener_id)
     return db_ls
Ejemplo n.º 25
0
 def get_one(self, id):
     """Gets a single load balancer's details."""
     session = db_api.get_session()
     load_balancer = self.repositories.load_balancer.get(
         session, id=id)
     if not load_balancer:
         LOG.info(_LI("Load Balancer %s was not found."), id)
         raise exceptions.NotFound(
             resource=data_models.LoadBalancer._name(), id=id)
     return self._convert_db_to_type(load_balancer,
                                     lb_types.LoadBalancerResponse)
Ejemplo n.º 26
0
    def delete(self, availability_zone_profile_id):
        """Deletes an Availability Zone Profile"""
        context = pecan_request.context.get('octavia_context')

        self._auth_validate_action(context, context.project_id,
                                   constants.RBAC_DELETE)
        if availability_zone_profile_id == constants.NIL_UUID:
            raise exceptions.NotFound(resource='Availability Zone Profile',
                                      id=constants.NIL_UUID)
        # Don't allow it to be deleted if it is in use by an availability zone
        if self.repositories.availability_zone.count(
                context.session,
                availability_zone_profile_id=availability_zone_profile_id) > 0:
            raise exceptions.ObjectInUse(object='Availability Zone Profile',
                                         id=availability_zone_profile_id)
        try:
            self.repositories.availability_zone_profile.delete(
                context.session, id=availability_zone_profile_id)
        except sa_exception.NoResultFound:
            raise exceptions.NotFound(resource='Availability Zone Profile',
                                      id=availability_zone_profile_id)
Ejemplo n.º 27
0
    def post(self, member):
        """Creates a pool member on a pool."""
        context = pecan.request.context.get('octavia_context')

        member.project_id = self._get_lb_project_id(context.session,
                                                    self.load_balancer_id)

        # Validate member subnet
        if member.subnet_id and not validate.subnet_exists(member.subnet_id):
            raise exceptions.NotFound(resource='Subnet', id=member.subnet_id)

        lock_session = db_api.get_session(autocommit=False)
        if self.repositories.check_quota_met(context.session, lock_session,
                                             data_models.Member,
                                             member.project_id):
            lock_session.rollback()
            raise exceptions.QuotaException

        try:
            member_dict = db_prepare.create_member(
                member.to_dict(render_unsets=True), self.pool_id)
            self._test_lb_and_listener_statuses(lock_session)

            db_member = self.repositories.member.create(
                lock_session, **member_dict)
            db_new_member = self._get_db_member(lock_session, db_member.id)
            lock_session.commit()
        except oslo_exc.DBDuplicateEntry as de:
            lock_session.rollback()
            if ['id'] == de.columns:
                raise exceptions.IDAlreadyExists()

            raise exceptions.DuplicateMemberEntry(
                ip_address=member_dict.get('ip_address'),
                port=member_dict.get('protocol_port'))
        except Exception:
            with excutils.save_and_reraise_exception():
                lock_session.rollback()

        try:
            LOG.info(_LI("Sending Creation of Member %s to handler"),
                     db_member.id)
            self.handler.create(db_member)
        except Exception:
            for listener_id in self._get_affected_listener_ids(
                    context.session):
                with excutils.save_and_reraise_exception(reraise=False):
                    self.repositories.listener.update(
                        context.session,
                        listener_id,
                        operating_status=constants.ERROR)
        return self._convert_db_to_type(db_new_member,
                                        member_types.MemberResponse)
Ejemplo n.º 28
0
 def _validate_pool(self, session, lb_id, pool_id, listener_protocol):
     """Validate pool given exists on same load balancer as listener."""
     db_pool = self.repositories.pool.get(
         session, load_balancer_id=lb_id, id=pool_id)
     if not db_pool:
         raise exceptions.NotFound(
             resource=data_models.Pool._name(), id=pool_id)
     if (db_pool.protocol == constants.PROTOCOL_UDP and
             db_pool.protocol != listener_protocol):
         msg = _("Listeners of type %s can only have pools of "
                 "type UDP.") % constants.PROTOCOL_UDP
         raise exceptions.ValidationException(detail=msg)
Ejemplo n.º 29
0
    def delete(self, flavor_profile_id):
        """Deletes a Flavor Profile"""
        context = pecan_request.context.get('octavia_context')

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

        if flavor_profile_id == constants.NIL_UUID:
            raise exceptions.NotFound(resource='Flavor profile',
                                      id=constants.NIL_UUID)

        # Don't allow it to be deleted if it is in use by a flavor
        if self.repositories.flavor.count(
                context.session, flavor_profile_id=flavor_profile_id) > 0:
            raise exceptions.ObjectInUse(object='Flavor profile',
                                         id=flavor_profile_id)
        try:
            self.repositories.flavor_profile.delete(context.session,
                                                    id=flavor_profile_id)
        except sa_exception.NoResultFound as e:
            raise exceptions.NotFound(
                resource='Flavor profile', id=flavor_profile_id) from e
Ejemplo n.º 30
0
    def delete(self, flavor_id):
        """Deletes a Flavor"""
        context = pecan.request.context.get('octavia_context')

        self._auth_validate_action(context, context.project_id,
                                   constants.RBAC_DELETE)
        try:
            self.repositories.flavor.delete(context.session, id=flavor_id)
        # Handle when load balancers still reference this flavor
        except odb_exceptions.DBReferenceError:
            raise exceptions.ObjectInUse(object='Flavor', id=flavor_id)
        except sa_exception.NoResultFound:
            raise exceptions.NotFound(resource='Flavor', id=flavor_id)