Example #1
0
 def post(self, load_balancer):
     """Creates a load balancer."""
     context = pecan.request.context.get('octavia_context')
     if load_balancer.listeners:
         return self._create_load_balancer_graph(context, load_balancer)
     lb_dict = db_prepare.create_load_balancer(load_balancer.to_dict(
         render_unsets=True
     ))
     vip_dict = lb_dict.pop('vip', {})
     try:
         db_lb = self.repositories.create_load_balancer_and_vip(
             context.session, lb_dict, vip_dict)
     except odb_exceptions.DBDuplicateEntry:
         raise exceptions.IDAlreadyExists()
     # Handler will be responsible for sending to controller
     try:
         LOG.info(_LI("Sending created Load Balancer %s to the handler"),
                  db_lb.id)
         self.handler.create(db_lb)
     except Exception:
         with excutils.save_and_reraise_exception(reraise=False):
             self.repositories.load_balancer.update(
                 context.session, db_lb.id,
                 provisioning_status=constants.ERROR)
     return self._convert_db_to_type(db_lb, lb_types.LoadBalancerResponse)
Example #2
0
 def post(self, load_balancer):
     """Creates a load balancer."""
     context = pecan.request.context.get('octavia_context')
     if load_balancer.listeners:
         return self._create_load_balancer_graph(context, load_balancer)
     lb_dict = db_prepare.create_load_balancer(
         load_balancer.to_dict(render_unsets=True))
     vip_dict = lb_dict.pop('vip', {})
     try:
         db_lb = self.repositories.create_load_balancer_and_vip(
             context.session, lb_dict, vip_dict)
     except odb_exceptions.DBDuplicateEntry:
         raise exceptions.IDAlreadyExists()
     # Handler will be responsible for sending to controller
     try:
         LOG.info(_LI("Sending created Load Balancer %s to the handler"),
                  db_lb.id)
         self.handler.create(db_lb)
     except Exception:
         with excutils.save_and_reraise_exception(reraise=False):
             self.repositories.load_balancer.update(
                 context.session,
                 db_lb.id,
                 provisioning_status=constants.ERROR)
     return self._convert_db_to_type(db_lb, lb_types.LoadBalancerResponse)
Example #3
0
    def post(self, load_balancer):
        """Creates a load balancer."""
        load_balancer = load_balancer.loadbalancer
        context = pecan_request.context.get('octavia_context')

        if not load_balancer.project_id and context.project_id:
            load_balancer.project_id = context.project_id

        if not load_balancer.project_id:
            raise exceptions.ValidationException(detail=_(
                "Missing project ID in request where one is required. "
                "An administrator should check the keystone settings "
                "in the Octavia configuration."))

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

        self._validate_vip_request_object(load_balancer, context=context)

        self._validate_flavor(context.session, load_balancer)

        self._validate_availability_zone(context.session, load_balancer)

        provider = self._get_provider(context.session, load_balancer)

        # 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_quota_met(
                    context.session,
                    lock_session,
                    data_models.LoadBalancer,
                    load_balancer.project_id):
                raise exceptions.QuotaException(
                    resource=data_models.LoadBalancer._name())

            db_lb, db_pools, db_lists = None, None, None

            lb_dict = db_prepare.create_load_balancer(load_balancer.to_dict(
                render_unsets=False
            ))
            vip_dict = lb_dict.pop('vip', {})

            # Make sure we store the right provider in the DB
            lb_dict['provider'] = driver.name

            # NoneType can be weird here, have to force type a second time
            listeners = lb_dict.pop('listeners', []) or []
            pools = lb_dict.pop('pools', []) or []

            flavor_dict = self._apply_flavor_to_lb_dict(lock_session, driver,
                                                        lb_dict)

            az_dict = self._validate_and_return_az_dict(lock_session, driver,
                                                        lb_dict)
            # Validate the network as soon as we have the AZ data
            validate.network_allowed_by_config(
                load_balancer.vip_network_id,
                valid_networks=az_dict.get(constants.VALID_VIP_NETWORKS))

            db_lb = self.repositories.create_load_balancer_and_vip(
                lock_session, lb_dict, vip_dict)

            # Pass the flavor dictionary through for the provider drivers
            # This is a "virtual" lb_dict item that includes the expanded
            # flavor dict instead of just the flavor_id we store in the DB.
            lb_dict['flavor'] = flavor_dict

            # Do the same with the availability_zone dict
            lb_dict['availability_zone'] = az_dict

            # See if the provider driver wants to manage the VIP port
            # This will still be called if the user provided a port to
            # allow drivers to collect any required information about the
            # VIP port.
            octavia_owned = False
            try:
                provider_vip_dict = driver_utils.vip_dict_to_provider_dict(
                    vip_dict)
                vip_dict = driver_utils.call_provider(
                    driver.name, driver.create_vip_port, db_lb.id,
                    db_lb.project_id, provider_vip_dict)
                vip = driver_utils.provider_vip_dict_to_vip_obj(vip_dict)
            except exceptions.ProviderNotImplementedError:
                # create vip port if not exist, driver didn't want to create
                # the VIP port
                vip = self._create_vip_port_if_not_exist(db_lb)
                LOG.info('Created VIP port %s for provider %s.',
                         vip.port_id, driver.name)
                # If a port_id wasn't passed in and we made it this far
                # we created the VIP
                if 'port_id' not in vip_dict or not vip_dict['port_id']:
                    octavia_owned = True

            # Check if the driver claims octavia owns the VIP port.
            if vip.octavia_owned:
                octavia_owned = True

            self.repositories.vip.update(
                lock_session, db_lb.id, ip_address=vip.ip_address,
                port_id=vip.port_id, network_id=vip.network_id,
                subnet_id=vip.subnet_id, octavia_owned=octavia_owned)

            if listeners or pools:
                db_pools, db_lists = self._graph_create(
                    context.session, lock_session, db_lb, listeners, pools)

            # Prepare the data for the driver data model
            driver_lb_dict = driver_utils.lb_dict_to_provider_dict(
                lb_dict, vip, db_pools, db_lists)

            # Dispatch to the driver
            LOG.info("Sending create Load Balancer %s to provider %s",
                     db_lb.id, driver.name)
            driver_utils.call_provider(
                driver.name, driver.loadbalancer_create,
                driver_dm.LoadBalancer.from_dict(driver_lb_dict))

            lock_session.commit()
        except odb_exceptions.DBDuplicateEntry:
            lock_session.rollback()
            raise exceptions.IDAlreadyExists()
        except Exception:
            with excutils.save_and_reraise_exception():
                lock_session.rollback()

        db_lb = self._get_db_lb(context.session, db_lb.id)

        result = self._convert_db_to_type(
            db_lb, lb_types.LoadBalancerFullResponse)
        return lb_types.LoadBalancerFullRootResponse(loadbalancer=result)
Example #4
0
    def post(self, load_balancer):
        """Creates a load balancer."""
        load_balancer = load_balancer.loadbalancer
        context = pecan.request.context.get('octavia_context')

        project_id = context.project_id
        if context.is_admin or CONF.auth_strategy == constants.NOAUTH:
            if load_balancer.project_id:
                project_id = load_balancer.project_id

        if not project_id:
            raise exceptions.ValidationException(detail=_(
                "Missing project ID in request where one is required."))

        load_balancer.project_id = project_id

        if not (load_balancer.vip_port_id or load_balancer.vip_network_id
                or load_balancer.vip_subnet_id):
            raise exceptions.ValidationException(detail=_(
                "VIP must contain one of: port_id, network_id, subnet_id."))

        # Validate the port id
        if load_balancer.vip_port_id:
            port = validate.port_exists(port_id=load_balancer.vip_port_id)
            load_balancer.vip_network_id = port.network_id
        # If no port id, validate the network id (and subnet if provided)
        elif load_balancer.vip_network_id:
            self._validate_network_and_fill_or_validate_subnet(load_balancer)
        # Validate just the subnet id
        elif load_balancer.vip_subnet_id:
            subnet = validate.subnet_exists(
                subnet_id=load_balancer.vip_subnet_id)
            load_balancer.vip_network_id = subnet.network_id

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

        # TODO(blogan): lb graph, look at v1 code

        try:
            lb_dict = db_prepare.create_load_balancer(
                load_balancer.to_dict(render_unsets=True))
            vip_dict = lb_dict.pop('vip', {})

            db_lb = self.repositories.create_load_balancer_and_vip(
                lock_session, lb_dict, vip_dict)
            lock_session.commit()
        except odb_exceptions.DBDuplicateEntry:
            lock_session.rollback()
            raise exceptions.IDAlreadyExists()
        except Exception:
            with excutils.save_and_reraise_exception():
                lock_session.rollback()

        # Handler will be responsible for sending to controller
        try:
            LOG.info(_LI("Sending created Load Balancer %s to the handler"),
                     db_lb.id)
            self.handler.create(db_lb)
        except Exception:
            with excutils.save_and_reraise_exception(reraise=False):
                self.repositories.load_balancer.update(
                    context.session,
                    db_lb.id,
                    provisioning_status=constants.ERROR)
        result = self._convert_db_to_type(db_lb, lb_types.LoadBalancerResponse)
        return lb_types.LoadBalancerRootResponse(loadbalancer=result)
Example #5
0
    def post(self, load_balancer):
        """Creates a load balancer."""
        load_balancer = load_balancer.loadbalancer
        context = pecan.request.context.get('octavia_context')

        if not load_balancer.project_id and context.project_id:
            load_balancer.project_id = context.project_id

        if not load_balancer.project_id:
            raise exceptions.ValidationException(detail=_(
                "Missing project ID in request where one is required."))

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

        self._validate_vip_request_object(load_balancer)

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

        db_lb, db_pools, db_lists = None, None, None
        try:
            lb_dict = db_prepare.create_load_balancer(
                load_balancer.to_dict(render_unsets=False))
            vip_dict = lb_dict.pop('vip', {})

            # NoneType can be weird here, have to force type a second time
            listeners = lb_dict.pop('listeners', []) or []
            pools = lb_dict.pop('pools', []) or []

            # TODO(johnsom) Remove provider and flavor from the lb_dict
            # as they have not been implemented beyond the API yet.
            # Remove these lines as they are implemented.
            if 'provider' in lb_dict:
                del lb_dict['provider']
            if 'flavor' in lb_dict:
                del lb_dict['flavor']

            db_lb = self.repositories.create_load_balancer_and_vip(
                lock_session, lb_dict, vip_dict)

            # create vip port if not exist
            vip = self._create_vip_port_if_not_exist(db_lb)
            self.repositories.vip.update(lock_session,
                                         db_lb.id,
                                         ip_address=vip.ip_address,
                                         port_id=vip.port_id,
                                         network_id=vip.network_id,
                                         subnet_id=vip.subnet_id)

            if listeners or pools:
                db_pools, db_lists = self._graph_create(
                    context.session, lock_session, db_lb, listeners, pools)

            lock_session.commit()
        except odb_exceptions.DBDuplicateEntry:
            lock_session.rollback()
            raise exceptions.IDAlreadyExists()
        except Exception:
            with excutils.save_and_reraise_exception():
                lock_session.rollback()

        # Handler will be responsible for sending to controller
        try:
            LOG.info("Sending created Load Balancer %s to the handler",
                     db_lb.id)
            self.handler.create(db_lb)
        except Exception:
            with excutils.save_and_reraise_exception(reraise=False):
                self.repositories.load_balancer.update(
                    context.session,
                    db_lb.id,
                    provisioning_status=constants.ERROR)

        db_lb = self._get_db_lb(context.session, db_lb.id)

        result = self._convert_db_to_type(db_lb,
                                          lb_types.LoadBalancerFullResponse)
        return lb_types.LoadBalancerFullRootResponse(loadbalancer=result)
Example #6
0
    def post(self, load_balancer):
        """Creates a load balancer."""
        load_balancer = load_balancer.loadbalancer
        context = pecan.request.context.get('octavia_context')

        if not load_balancer.project_id and context.project_id:
            load_balancer.project_id = context.project_id

        if not load_balancer.project_id:
            raise exceptions.ValidationException(detail=_(
                "Missing project ID in request where one is required."))

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

        self._validate_vip_request_object(load_balancer)

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

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

            db_lb, db_pools, db_lists = None, None, None

            lb_dict = db_prepare.create_load_balancer(
                load_balancer.to_dict(render_unsets=False))
            vip_dict = lb_dict.pop('vip', {})

            # Make sure we store the right provider in the DB
            lb_dict['provider'] = driver.name

            # NoneType can be weird here, have to force type a second time
            listeners = lb_dict.pop('listeners', []) or []
            pools = lb_dict.pop('pools', []) or []

            # TODO(johnsom) Remove flavor from the lb_dict
            # as it has not been implemented beyond the API yet.
            # Remove this line when it is implemented.
            lb_dict.pop('flavor', None)

            db_lb = self.repositories.create_load_balancer_and_vip(
                lock_session, lb_dict, vip_dict)

            # See if the provider driver wants to create the VIP port
            try:
                provider_vip_dict = driver_utils.vip_dict_to_provider_dict(
                    vip_dict)
                vip_dict = driver_utils.call_provider(driver.name,
                                                      driver.create_vip_port,
                                                      db_lb.id,
                                                      db_lb.project_id,
                                                      provider_vip_dict)
                vip = driver_utils.provider_vip_dict_to_vip_obj(vip_dict)
            except exceptions.ProviderNotImplementedError:
                # create vip port if not exist, driver didn't want to create
                # the VIP port
                vip = self._create_vip_port_if_not_exist(db_lb)
                LOG.info('Created VIP port %s for provider %s.', vip.port_id,
                         driver.name)

            self.repositories.vip.update(lock_session,
                                         db_lb.id,
                                         ip_address=vip.ip_address,
                                         port_id=vip.port_id,
                                         network_id=vip.network_id,
                                         subnet_id=vip.subnet_id)

            if listeners or pools:
                db_pools, db_lists = self._graph_create(
                    context.session, lock_session, db_lb, listeners, pools)

            # Prepare the data for the driver data model
            driver_lb_dict = driver_utils.lb_dict_to_provider_dict(
                lb_dict, vip, db_pools, db_lists)

            # Dispatch to the driver
            LOG.info("Sending create Load Balancer %s to provider %s",
                     db_lb.id, driver.name)
            driver_utils.call_provider(
                driver.name, driver.loadbalancer_create,
                driver_dm.LoadBalancer.from_dict(driver_lb_dict))

            lock_session.commit()
        except odb_exceptions.DBDuplicateEntry:
            lock_session.rollback()
            raise exceptions.IDAlreadyExists()
        except Exception:
            with excutils.save_and_reraise_exception():
                lock_session.rollback()

        db_lb = self._get_db_lb(context.session, db_lb.id)

        result = self._convert_db_to_type(db_lb,
                                          lb_types.LoadBalancerFullResponse)
        return lb_types.LoadBalancerFullRootResponse(loadbalancer=result)
Example #7
0
    def post(self, load_balancer):
        """Creates a load balancer."""
        load_balancer = load_balancer.loadbalancer
        context = pecan.request.context.get('octavia_context')

        if not load_balancer.project_id and context.project_id:
            load_balancer.project_id = context.project_id

        if not load_balancer.project_id:
            raise exceptions.ValidationException(detail=_(
                "Missing project ID in request where one is required."))

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

        self._validate_vip_request_object(load_balancer)

        self._validate_flavor(context.session, load_balancer)

        provider = self._get_provider(context.session, load_balancer)

        # 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_quota_met(
                    context.session,
                    lock_session,
                    data_models.LoadBalancer,
                    load_balancer.project_id):
                raise exceptions.QuotaException(
                    resource=data_models.LoadBalancer._name())

            db_lb, db_pools, db_lists = None, None, None

            lb_dict = db_prepare.create_load_balancer(load_balancer.to_dict(
                render_unsets=False
            ))
            vip_dict = lb_dict.pop('vip', {})

            # Make sure we store the right provider in the DB
            lb_dict['provider'] = driver.name

            # NoneType can be weird here, have to force type a second time
            listeners = lb_dict.pop('listeners', []) or []
            pools = lb_dict.pop('pools', []) or []

            flavor_dict = self._apply_flavor_to_lb_dict(lock_session, driver,
                                                        lb_dict)

            db_lb = self.repositories.create_load_balancer_and_vip(
                lock_session, lb_dict, vip_dict)

            # Pass the flavor dictionary through for the provider drivers
            # This is a "virtual" lb_dict item that includes the expanded
            # flavor dict instead of just the flavor_id we store in the DB.
            lb_dict['flavor'] = flavor_dict

            # See if the provider driver wants to create the VIP port
            octavia_owned = False
            try:
                provider_vip_dict = driver_utils.vip_dict_to_provider_dict(
                    vip_dict)
                vip_dict = driver_utils.call_provider(
                    driver.name, driver.create_vip_port, db_lb.id,
                    db_lb.project_id, provider_vip_dict)
                vip = driver_utils.provider_vip_dict_to_vip_obj(vip_dict)
            except exceptions.ProviderNotImplementedError:
                # create vip port if not exist, driver didn't want to create
                # the VIP port
                vip = self._create_vip_port_if_not_exist(db_lb)
                LOG.info('Created VIP port %s for provider %s.',
                         vip.port_id, driver.name)
                # If a port_id wasn't passed in and we made it this far
                # we created the VIP
                if 'port_id' not in vip_dict or not vip_dict['port_id']:
                    octavia_owned = True

            self.repositories.vip.update(
                lock_session, db_lb.id, ip_address=vip.ip_address,
                port_id=vip.port_id, network_id=vip.network_id,
                subnet_id=vip.subnet_id, octavia_owned=octavia_owned)

            if listeners or pools:
                db_pools, db_lists = self._graph_create(
                    context.session, lock_session, db_lb, listeners, pools)

            # Prepare the data for the driver data model
            driver_lb_dict = driver_utils.lb_dict_to_provider_dict(
                lb_dict, vip, db_pools, db_lists)

            # Dispatch to the driver
            LOG.info("Sending create Load Balancer %s to provider %s",
                     db_lb.id, driver.name)
            driver_utils.call_provider(
                driver.name, driver.loadbalancer_create,
                driver_dm.LoadBalancer.from_dict(driver_lb_dict))

            lock_session.commit()
        except odb_exceptions.DBDuplicateEntry:
            lock_session.rollback()
            raise exceptions.IDAlreadyExists()
        except Exception:
            with excutils.save_and_reraise_exception():
                lock_session.rollback()

        db_lb = self._get_db_lb(context.session, db_lb.id)

        result = self._convert_db_to_type(
            db_lb, lb_types.LoadBalancerFullResponse)
        return lb_types.LoadBalancerFullRootResponse(loadbalancer=result)
Example #8
0
    def post(self, load_balancer):
        """Creates a load balancer."""
        context = pecan.request.context.get('octavia_context')

        project_id = context.project_id
        if context.is_admin or CONF.auth_strategy == constants.NOAUTH:
            if load_balancer.project_id:
                project_id = load_balancer.project_id

        if not project_id:
            raise exceptions.MissingAPIProjectID()

        load_balancer.project_id = project_id

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

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

        if load_balancer.listeners:
            try:
                db_lb = self._create_load_balancer_graph_db(
                    lock_session, load_balancer)
                lock_session.commit()
            except Exception:
                with excutils.save_and_reraise_exception():
                    lock_session.rollback()

            return self._load_balancer_graph_to_handler(context, db_lb)

        try:
            lb_dict = db_prepare.create_load_balancer(
                load_balancer.to_dict(render_unsets=True))
            vip_dict = lb_dict.pop('vip', {})

            db_lb = self.repositories.create_load_balancer_and_vip(
                lock_session, lb_dict, vip_dict)
            lock_session.commit()
        except odb_exceptions.DBDuplicateEntry:
            lock_session.rollback()
            raise exceptions.IDAlreadyExists()
        except Exception:
            with excutils.save_and_reraise_exception():
                lock_session.rollback()

        # Handler will be responsible for sending to controller
        try:
            LOG.info(_LI("Sending created Load Balancer %s to the handler"),
                     db_lb.id)
            self.handler.create(db_lb)
        except Exception:
            with excutils.save_and_reraise_exception(reraise=False):
                self.repositories.load_balancer.update(
                    context.session,
                    db_lb.id,
                    provisioning_status=constants.ERROR)
        return self._convert_db_to_type(db_lb, lb_types.LoadBalancerResponse)