diff --git a/octavia/api/v1/controllers/health_monitor.py b/octavia/api/v1/controllers/health_monitor.py index a20c0d5a34..e70f55dd3b 100644 --- a/octavia/api/v1/controllers/health_monitor.py +++ b/octavia/api/v1/controllers/health_monitor.py @@ -16,6 +16,7 @@ import logging from oslo_db import exception as odb_exceptions from oslo_utils import excutils +import pecan from wsmeext import pecan as wsme_pecan from octavia.api.v1.controllers import base @@ -23,7 +24,6 @@ from octavia.api.v1.types import health_monitor as hm_types from octavia.common import constants from octavia.common import data_models from octavia.common import exceptions -from octavia.db import api as db_api from octavia.i18n import _LI @@ -44,9 +44,9 @@ class HealthMonitorController(base.BaseController): """Gets a single health monitor's details.""" # NOTE(blogan): since a pool can only have one health monitor # we are using the get_all method to only get the single health monitor - session = db_api.get_session() + context = pecan.request.context.get('octavia_context') db_hm = self.repositories.health_monitor.get( - session, pool_id=self.pool_id) + context.session, pool_id=self.pool_id) if not db_hm: LOG.info(_LI("Health Monitor for Pool %s was not found"), self.pool_id) @@ -58,10 +58,10 @@ class HealthMonitorController(base.BaseController): body=hm_types.HealthMonitorPOST, status_code=202) def post(self, health_monitor): """Creates a health monitor on a pool.""" - session = db_api.get_session() + context = pecan.request.context.get('octavia_context') try: db_hm = self.repositories.health_monitor.get( - session, pool_id=self.pool_id) + context.session, pool_id=self.pool_id) if db_hm: raise exceptions.DuplicateHealthMonitor() except exceptions.NotFound: @@ -72,25 +72,26 @@ class HealthMonitorController(base.BaseController): # that the listener is also in a mutable status because a load balancer # will only be ACTIVE when all it's listeners as ACTIVE. if not self.repositories.test_and_set_lb_and_listener_prov_status( - session, self.load_balancer_id, self.listener_id, + context.session, self.load_balancer_id, self.listener_id, constants.PENDING_UPDATE, constants.PENDING_UPDATE): LOG.info(_LI("Health Monitor for Pool %s cannot be updated " "because the Load Balancer is immutable."), self.pool_id) lb_repo = self.repositories.load_balancer - db_lb = lb_repo.get(session, id=self.load_balancer_id) + db_lb = lb_repo.get(context.session, id=self.load_balancer_id) raise exceptions.ImmutableObject(resource=db_lb._name(), id=self.load_balancer_id) try: - db_hm = self.repositories.health_monitor.create(session, **hm_dict) + db_hm = self.repositories.health_monitor.create( + context.session, **hm_dict) except odb_exceptions.DBError: # Setting LB and Listener back to active because this is just a # validation failure self.repositories.load_balancer.update( - session, self.load_balancer_id, + context.session, self.load_balancer_id, provisioning_status=constants.ACTIVE) self.repositories.listener.update( - session, self.listener_id, + context.session, self.listener_id, provisioning_status=constants.ACTIVE) raise exceptions.InvalidOption(value=hm_dict.get('type'), option='type') @@ -101,10 +102,10 @@ class HealthMonitorController(base.BaseController): except Exception: with excutils.save_and_reraise_exception(reraise=False): self.repositories.listener.update( - session, self.listener_id, + context.session, self.listener_id, operating_status=constants.ERROR) db_hm = self.repositories.health_monitor.get( - session, pool_id=self.pool_id) + context.session, pool_id=self.pool_id) return self._convert_db_to_type(db_hm, hm_types.HealthMonitorResponse) @wsme_pecan.wsexpose(hm_types.HealthMonitorResponse, @@ -116,9 +117,9 @@ class HealthMonitorController(base.BaseController): monitor is allowed per pool so there is no need for a health monitor id. """ - session = db_api.get_session() + context = pecan.request.context.get('octavia_context') db_hm = self.repositories.health_monitor.get( - session, pool_id=self.pool_id) + context.session, pool_id=self.pool_id) if not db_hm: LOG.info(_LI("Health Monitor for Pool %s was not found"), self.pool_id) @@ -128,13 +129,13 @@ class HealthMonitorController(base.BaseController): # that the listener is also in a mutable status because a load balancer # will only be ACTIVE when all it's listeners as ACTIVE. if not self.repositories.test_and_set_lb_and_listener_prov_status( - session, self.load_balancer_id, self.listener_id, + context.session, self.load_balancer_id, self.listener_id, constants.PENDING_UPDATE, constants.PENDING_UPDATE): LOG.info(_LI("Health Monitor for Pool %s cannot be updated " "because the Load Balancer is immutable."), self.pool_id) lb_repo = self.repositories.load_balancer - db_lb = lb_repo.get(session, id=self.load_balancer_id) + db_lb = lb_repo.get(context.session, id=self.load_balancer_id) raise exceptions.ImmutableObject(resource=db_lb._name(), id=self.load_balancer_id) try: @@ -144,18 +145,18 @@ class HealthMonitorController(base.BaseController): except Exception: with excutils.save_and_reraise_exception(reraise=False): self.repositories.listener.update( - session, self.listener_id, + context.session, self.listener_id, operating_status=constants.ERROR) db_hm = self.repositories.health_monitor.get( - session, pool_id=self.pool_id) + context.session, pool_id=self.pool_id) return self._convert_db_to_type(db_hm, hm_types.HealthMonitorResponse) @wsme_pecan.wsexpose(None, status_code=202) def delete(self): """Deletes a health monitor.""" - session = db_api.get_session() + context = pecan.request.context.get('octavia_context') db_hm = self.repositories.health_monitor.get( - session, pool_id=self.pool_id) + context.session, pool_id=self.pool_id) if not db_hm: LOG.info(_LI("Health Monitor for Pool %s cannot be updated " "because the Load Balancer is immutable."), @@ -166,13 +167,13 @@ class HealthMonitorController(base.BaseController): # that the listener is also in a mutable status because a load balancer # will only be ACTIVE when all it's listeners as ACTIVE. if not self.repositories.test_and_set_lb_and_listener_prov_status( - session, self.load_balancer_id, self.listener_id, + context.session, self.load_balancer_id, self.listener_id, constants.PENDING_UPDATE, constants.PENDING_UPDATE): lb_repo = self.repositories.load_balancer - db_lb = lb_repo.get(session, id=self.load_balancer_id) + db_lb = lb_repo.get(context.session, id=self.load_balancer_id) raise exceptions.ImmutableObject(resource=db_lb._name(), id=self.load_balancer_id) - db_hm = self.repositories.health_monitor.get(session, + db_hm = self.repositories.health_monitor.get(context.session, pool_id=self.pool_id) try: LOG.info(_LI("Sending Deletion of Health Monitor for Pool %s to " @@ -181,8 +182,8 @@ class HealthMonitorController(base.BaseController): except Exception: with excutils.save_and_reraise_exception(reraise=False): self.repositories.listener.update( - session, self.listener_id, + context.session, self.listener_id, operating_status=constants.ERROR) db_hm = self.repositories.health_monitor.get( - session, pool_id=self.pool_id) + context.session, pool_id=self.pool_id) return self._convert_db_to_type(db_hm, hm_types.HealthMonitorResponse) diff --git a/octavia/api/v1/controllers/listener.py b/octavia/api/v1/controllers/listener.py index 6cccb387a9..7890f74473 100644 --- a/octavia/api/v1/controllers/listener.py +++ b/octavia/api/v1/controllers/listener.py @@ -49,9 +49,9 @@ class ListenersController(base.BaseController): @wsme_pecan.wsexpose(listener_types.ListenerResponse, wtypes.text) def get_one(self, id): """Gets a single listener's details.""" - session = db_api.get_session() + context = pecan.request.context.get('octavia_context') db_listener = self.repositories.listener.get( - session, load_balancer_id=self.load_balancer_id, id=id) + context.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( @@ -62,22 +62,23 @@ class ListenersController(base.BaseController): @wsme_pecan.wsexpose([listener_types.ListenerResponse]) def get_all(self): """Lists all listeners on a load balancer.""" - session = db_api.get_session() + context = pecan.request.context.get('octavia_context') db_listeners = self.repositories.listener.get_all( - session, load_balancer_id=self.load_balancer_id) + context.session, load_balancer_id=self.load_balancer_id) return self._convert_db_to_type(db_listeners, [listener_types.ListenerResponse]) - def _test_lb_status_post(self, session, lb_repo): + def _test_lb_status_post(self, context, lb_repo): """Verify load balancer is in a mutable status for post method.""" if not lb_repo.test_and_set_provisioning_status( - session, self.load_balancer_id, constants.PENDING_UPDATE): - db_lb = lb_repo.get(session, id=self.load_balancer_id) + context.session, self.load_balancer_id, + constants.PENDING_UPDATE): + db_lb = lb_repo.get(context.session, id=self.load_balancer_id) LOG.info(_LI("Load Balancer %s is immutable."), db_lb.id) raise exceptions.ImmutableObject(resource=db_lb._name(), id=self.load_balancer_id) - def _validate_listeners(self, session, lb_repo, listener_dict): + def _validate_listeners(self, context, lb_repo, listener_dict): """Validate listeners for wrong protocol or duplicate listeners Update the load balancer db when provisioning status changes. @@ -85,18 +86,18 @@ class ListenersController(base.BaseController): try: sni_container_ids = listener_dict.pop('sni_containers') db_listener = self.repositories.listener.create( - session, **listener_dict) + context.session, **listener_dict) if sni_container_ids is not None: for container_id in sni_container_ids: sni_dict = {'listener_id': db_listener.id, 'tls_container_id': container_id} - self.repositories.sni.create(session, **sni_dict) - db_listener = self.repositories.listener.get(session, + self.repositories.sni.create(context.session, **sni_dict) + db_listener = self.repositories.listener.get(context.session, id=db_listener.id) except odb_exceptions.DBDuplicateEntry as de: # Setting LB back to active because this is just a validation # failure - lb_repo.update(session, self.load_balancer_id, + lb_repo.update(context.session, self.load_balancer_id, provisioning_status=constants.ACTIVE) if ['id'] == de.columns: raise exceptions.IDAlreadyExists() @@ -106,7 +107,7 @@ class ListenersController(base.BaseController): except odb_exceptions.DBError: # Setting LB back to active because this is just a validation # failure - lb_repo.update(session, self.load_balancer_id, + lb_repo.update(context.session, self.load_balancer_id, provisioning_status=constants.ACTIVE) raise exceptions.InvalidOption(value=listener_dict.get('protocol'), option='protocol') @@ -117,10 +118,10 @@ class ListenersController(base.BaseController): except Exception: with excutils.save_and_reraise_exception(reraise=False): self.repositories.listener.update( - session, db_listener.id, + context.session, db_listener.id, provisioning_status=constants.ERROR) db_listener = self.repositories.listener.get( - session, id=db_listener.id) + context.session, id=db_listener.id) return self._convert_db_to_type(db_listener, listener_types.ListenerResponse) @@ -128,10 +129,10 @@ class ListenersController(base.BaseController): body=listener_types.ListenerPOST, status_code=202) def post(self, listener): """Creates a listener on a load balancer.""" + context = pecan.request.context.get('octavia_context') self._secure_data(listener) - session = db_api.get_session() lb_repo = self.repositories.load_balancer - self._test_lb_status_post(session, lb_repo) + self._test_lb_status_post(context, lb_repo) listener_dict = listener.to_dict() listener_dict['load_balancer_id'] = self.load_balancer_id listener_dict['provisioning_status'] = constants.PENDING_CREATE @@ -142,17 +143,17 @@ class ListenersController(base.BaseController): del listener_dict['tls_termination'] # This is the extra validation layer for wrong protocol or duplicate # listeners on the same load balancer. - return self._validate_listeners(session, lb_repo, listener_dict) + return self._validate_listeners(context, lb_repo, listener_dict) - def _test_lb_status_put(self, session, id): + def _test_lb_status_put(self, context, id): """Test load balancer status for put method.""" if not self.repositories.test_and_set_lb_and_listener_prov_status( - session, self.load_balancer_id, id, constants.PENDING_UPDATE, - constants.PENDING_UPDATE): + context.session, self.load_balancer_id, id, + constants.PENDING_UPDATE, constants.PENDING_UPDATE): LOG.info(_LI("Load Balancer %s is immutable."), self.load_balancer_id) lb_repo = self.repositories.load_balancer - db_lb = lb_repo.get(session, id=self.load_balancer_id) + db_lb = lb_repo.get(context.session, id=self.load_balancer_id) raise exceptions.ImmutableObject(resource=db_lb._name(), id=self.load_balancer_id) @@ -161,8 +162,8 @@ class ListenersController(base.BaseController): def put(self, id, listener): """Updates a listener on a load balancer.""" self._secure_data(listener) - session = db_api.get_session() - db_listener = self.repositories.listener.get(session, id=id) + context = pecan.request.context.get('octavia_context') + db_listener = self.repositories.listener.get(context.session, id=id) if not db_listener: LOG.info(_LI("Listener %s not found."), id) raise exceptions.NotFound( @@ -170,23 +171,23 @@ class ListenersController(base.BaseController): # 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 it's listeners as ACTIVE. - self._test_lb_status_put(session, id) + self._test_lb_status_put(context, id) try: LOG.info(_LI("Sending Update of Listener %s to handler"), id) self.handler.update(db_listener, listener) except Exception: with excutils.save_and_reraise_exception(reraise=False): self.repositories.listener.update( - session, id, provisioning_status=constants.ERROR) - db_listener = self.repositories.listener.get(session, id=id) + context.session, id, provisioning_status=constants.ERROR) + db_listener = self.repositories.listener.get(context.session, id=id) return self._convert_db_to_type(db_listener, listener_types.ListenerResponse) @wsme_pecan.wsexpose(None, wtypes.text, status_code=202) def delete(self, id): """Deletes a listener from a load balancer.""" - session = db_api.get_session() - db_listener = self.repositories.listener.get(session, id=id) + context = pecan.request.context.get('octavia_context') + db_listener = self.repositories.listener.get(context.session, id=id) if not db_listener: LOG.info(_LI("Listener %s not found."), id) raise exceptions.NotFound( @@ -195,13 +196,13 @@ class ListenersController(base.BaseController): # that the listener is also in a mutable status because a load balancer # will only be ACTIVE when all it's listeners as ACTIVE. if not self.repositories.test_and_set_lb_and_listener_prov_status( - session, self.load_balancer_id, id, constants.PENDING_UPDATE, - constants.PENDING_DELETE): + context.session, self.load_balancer_id, id, + constants.PENDING_UPDATE, constants.PENDING_DELETE): lb_repo = self.repositories.load_balancer - db_lb = lb_repo.get(session, id=self.load_balancer_id) + db_lb = lb_repo.get(context.session, id=self.load_balancer_id) raise exceptions.ImmutableObject(resource=db_lb._name(), id=self.load_balancer_id) - db_listener = self.repositories.listener.get(session, id=id) + db_listener = self.repositories.listener.get(context.session, id=id) try: LOG.info(_LI("Sending Deletion of Listener %s to handler"), db_listener.id) @@ -209,10 +210,10 @@ class ListenersController(base.BaseController): except Exception: with excutils.save_and_reraise_exception(reraise=False): self.repositories.listener.update( - session, db_listener.id, + context.session, db_listener.id, provisioning_status=constants.ERROR) db_listener = self.repositories.listener.get( - session, id=db_listener.id) + context.session, id=db_listener.id) return self._convert_db_to_type(db_listener, listener_types.ListenerResponse) diff --git a/octavia/api/v1/controllers/load_balancer.py b/octavia/api/v1/controllers/load_balancer.py index fce405c65c..d6e01f060b 100644 --- a/octavia/api/v1/controllers/load_balancer.py +++ b/octavia/api/v1/controllers/load_balancer.py @@ -41,9 +41,9 @@ class LoadBalancersController(base.BaseController): @wsme_pecan.wsexpose(lb_types.LoadBalancerResponse, wtypes.text) def get_one(self, id): """Gets a single load balancer's details.""" - session = db_api.get_session() + context = pecan.request.context.get('octavia_context') load_balancer = self.repositories.load_balancer.get( - session, id=id) + context.session, id=id) if not load_balancer: LOG.info(_LI("Load Balancer %s was not found."), id) raise exceptions.NotFound( @@ -58,10 +58,10 @@ class LoadBalancersController(base.BaseController): # NOTE(blogan): tenant_id and project_id are optional query parameters # tenant_id and project_id are the same thing. tenant_id will be kept # around for a short amount of time. - project_id = project_id or tenant_id - session = db_api.get_session() + context = pecan.request.context.get('octavia_context') + project_id = context.project_id or project_id or tenant_id load_balancers = self.repositories.load_balancer.get_all( - session, project_id=project_id) + context.session, project_id=project_id) return self._convert_db_to_type(load_balancers, [lb_types.LoadBalancerResponse]) @@ -69,14 +69,15 @@ class LoadBalancersController(base.BaseController): body=lb_types.LoadBalancerPOST, status_code=202) def post(self, load_balancer): """Creates a load balancer.""" - session = db_api.get_session() + context = pecan.request.context.get('octavia_context') lb_dict = load_balancer.to_dict() vip_dict = lb_dict.pop('vip') lb_dict['provisioning_status'] = constants.PENDING_CREATE lb_dict['operating_status'] = constants.OFFLINE + lb_dict['project_id'] = lb_dict.get('project_id') or context.project_id try: db_lb = self.repositories.create_load_balancer_and_vip( - session, lb_dict, vip_dict) + context.session, lb_dict, vip_dict) except odb_exceptions.DBDuplicateEntry: raise exceptions.IDAlreadyExists() # Handler will be responsible for sending to controller @@ -87,7 +88,8 @@ class LoadBalancersController(base.BaseController): except Exception: with excutils.save_and_reraise_exception(reraise=False): self.repositories.load_balancer.update( - session, db_lb.id, provisioning_status=constants.ERROR) + context.session, db_lb.id, + provisioning_status=constants.ERROR) return self._convert_db_to_type(db_lb, lb_types.LoadBalancerResponse) @wsme_pecan.wsexpose(lb_types.LoadBalancerResponse, @@ -95,17 +97,17 @@ class LoadBalancersController(base.BaseController): body=lb_types.LoadBalancerPUT) def put(self, id, load_balancer): """Updates a load balancer.""" - session = db_api.get_session() + context = pecan.request.context.get('octavia_context') # Purely to make lines smaller length lb_repo = self.repositories.load_balancer - db_lb = self.repositories.load_balancer.get(session, id=id) + db_lb = self.repositories.load_balancer.get(context.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): + context.session, id, constants.PENDING_UPDATE): LOG.info(_LI("Load Balancer %s is immutable."), id) raise exceptions.ImmutableObject(resource=db_lb._name(), id=id) @@ -116,28 +118,28 @@ class LoadBalancersController(base.BaseController): 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) + context.session, id, provisioning_status=constants.ERROR) + lb = self.repositories.load_balancer.get(context.session, id=id) return self._convert_db_to_type(lb, lb_types.LoadBalancerResponse) @wsme_pecan.wsexpose(None, wtypes.text, status_code=202) def delete(self, id): """Deletes a load balancer.""" - session = db_api.get_session() + context = pecan.request.context.get('octavia_context') # Purely to make lines smaller length lb_repo = self.repositories.load_balancer - db_lb = self.repositories.load_balancer.get(session, id=id) + db_lb = self.repositories.load_balancer.get(context.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_DELETE): + context.session, id, constants.PENDING_DELETE): LOG.info(_LI("Load Balancer %s is immutable."), id) raise exceptions.ImmutableObject(resource=db_lb._name(), id=id) - db_lb = self.repositories.load_balancer.get(session, id=id) + db_lb = self.repositories.load_balancer.get(context.session, id=id) try: LOG.info(_LI("Sending deleted Load Balancer %s to the handler"), db_lb.id) @@ -145,7 +147,8 @@ class LoadBalancersController(base.BaseController): except Exception: with excutils.save_and_reraise_exception(reraise=False): self.repositories.load_balancer.update( - session, db_lb.id, provisioning_status=constants.ERROR) + context.session, db_lb.id, + provisioning_status=constants.ERROR) return self._convert_db_to_type(db_lb, lb_types.LoadBalancerResponse) @pecan.expose() @@ -158,7 +161,8 @@ class LoadBalancersController(base.BaseController): session = db_api.get_session() if lb_id and len(remainder) and remainder[0] == 'listeners': remainder = remainder[1:] - db_lb = self.repositories.load_balancer.get(session, id=lb_id) + db_lb = self.repositories.load_balancer.get( + session, id=lb_id) if not db_lb: LOG.info(_LI("Load Balancer %s was not found."), lb_id) raise exceptions.NotFound( diff --git a/octavia/api/v1/controllers/member.py b/octavia/api/v1/controllers/member.py index 6bf4d731f7..37c20d2196 100644 --- a/octavia/api/v1/controllers/member.py +++ b/octavia/api/v1/controllers/member.py @@ -16,6 +16,7 @@ import logging import oslo_db.exception as oslo_exc from oslo_utils import excutils +import pecan from wsme import types as wtypes from wsmeext import pecan as wsme_pecan @@ -24,7 +25,6 @@ from octavia.api.v1.types import member as member_types from octavia.common import constants from octavia.common import data_models from octavia.common import exceptions -from octavia.db import api as db_api from octavia.i18n import _LI @@ -43,8 +43,8 @@ class MembersController(base.BaseController): @wsme_pecan.wsexpose(member_types.MemberResponse, wtypes.text) 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) + context = pecan.request.context.get('octavia_context') + db_member = self.repositories.member.get(context.session, id=id) if not db_member: LOG.info(_LI("Member %s not found"), id) raise exceptions.NotFound( @@ -54,9 +54,9 @@ class MembersController(base.BaseController): @wsme_pecan.wsexpose([member_types.MemberResponse]) def get_all(self): """Lists all pool members of a pool.""" - session = db_api.get_session() + context = pecan.request.context.get('octavia_context') db_members = self.repositories.member.get_all( - session, pool_id=self.pool_id) + context.session, pool_id=self.pool_id) return self._convert_db_to_type(db_members, [member_types.MemberResponse]) @@ -64,7 +64,7 @@ class MembersController(base.BaseController): body=member_types.MemberPOST, status_code=202) def post(self, member): """Creates a pool member on a pool.""" - session = db_api.get_session() + context = pecan.request.context.get('octavia_context') member_dict = member.to_dict() member_dict['pool_id'] = self.pool_id member_dict['operating_status'] = constants.OFFLINE @@ -72,24 +72,25 @@ class MembersController(base.BaseController): # 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, + context.session, self.load_balancer_id, self.listener_id, constants.PENDING_UPDATE, constants.PENDING_UPDATE): LOG.info(_LI("Member cannot be created because its Load " "Balancer is in an immutable state.")) lb_repo = self.repositories.load_balancer - db_lb = lb_repo.get(session, id=self.load_balancer_id) + db_lb = lb_repo.get(context.session, id=self.load_balancer_id) raise exceptions.ImmutableObject(resource=db_lb._name(), id=self.load_balancer_id) try: - db_member = self.repositories.member.create(session, **member_dict) + db_member = self.repositories.member.create( + context.session, **member_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( - session, self.load_balancer_id, + context.session, self.load_balancer_id, provisioning_status=constants.ACTIVE) self.repositories.listener.update( - session, self.listener_id, + context.session, self.listener_id, provisioning_status=constants.ACTIVE) if ['id'] == de.columns: raise exceptions.IDAlreadyExists() @@ -105,9 +106,10 @@ class MembersController(base.BaseController): except Exception: with excutils.save_and_reraise_exception(reraise=False): self.repositories.listener.update( - session, self.listener_id, + context.session, self.listener_id, operating_status=constants.ERROR) - db_member = self.repositories.member.get(session, id=db_member.id) + db_member = self.repositories.member.get(context.session, + id=db_member.id) return self._convert_db_to_type(db_member, member_types.MemberResponse) @wsme_pecan.wsexpose(member_types.MemberResponse, @@ -115,8 +117,8 @@ class MembersController(base.BaseController): status_code=202) def put(self, id, member): """Updates a pool member.""" - session = db_api.get_session() - db_member = self.repositories.member.get(session, id=id) + context = pecan.request.context.get('octavia_context') + db_member = self.repositories.member.get(context.session, id=id) if not db_member: LOG.info(_LI("Member %s cannot be updated because its Load " "Balancer is in an immutable state."), id) @@ -127,10 +129,10 @@ class MembersController(base.BaseController): # 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, + context.session, self.load_balancer_id, self.listener_id, constants.PENDING_UPDATE, constants.PENDING_UPDATE): lb_repo = self.repositories.load_balancer - db_lb = lb_repo.get(session, id=self.load_balancer_id) + db_lb = lb_repo.get(context.session, id=self.load_balancer_id) raise exceptions.ImmutableObject(resource=db_lb._name(), id=self.load_balancer_id) try: @@ -139,16 +141,16 @@ class MembersController(base.BaseController): except Exception: with excutils.save_and_reraise_exception(reraise=False): self.repositories.listener.update( - session, self.listener_id, + context.session, self.listener_id, operating_status=constants.ERROR) - db_member = self.repositories.member.get(session, id=id) + db_member = self.repositories.member.get(context.session, id=id) return self._convert_db_to_type(db_member, member_types.MemberResponse) @wsme_pecan.wsexpose(None, wtypes.text, status_code=202) def delete(self, id): """Deletes a pool member.""" - session = db_api.get_session() - db_member = self.repositories.member.get(session, id=id) + context = pecan.request.context.get('octavia_context') + db_member = self.repositories.member.get(context.session, id=id) if not db_member: LOG.info(_LI("Member %s not found"), id) raise exceptions.NotFound( @@ -157,15 +159,15 @@ class MembersController(base.BaseController): # 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, + context.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) + db_lb = lb_repo.get(context.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) + db_member = self.repositories.member.get(context.session, id=id) try: LOG.info(_LI("Sending Deletion of Member %s to handler"), db_member.id) @@ -173,7 +175,7 @@ class MembersController(base.BaseController): except Exception: with excutils.save_and_reraise_exception(reraise=False): self.repositories.listener.update( - session, self.listener_id, + context.session, self.listener_id, operating_status=constants.ERROR) - db_member = self.repositories.member.get(session, id=id) + db_member = self.repositories.member.get(context.session, id=id) return self._convert_db_to_type(db_member, member_types.MemberResponse) diff --git a/octavia/api/v1/controllers/pool.py b/octavia/api/v1/controllers/pool.py index 5331ab8784..10f6e90ca3 100644 --- a/octavia/api/v1/controllers/pool.py +++ b/octavia/api/v1/controllers/pool.py @@ -27,7 +27,6 @@ from octavia.api.v1.types import pool as pool_types from octavia.common import constants from octavia.common import data_models from octavia.common import exceptions -from octavia.db import api as db_api from octavia.i18n import _LI @@ -45,8 +44,8 @@ class PoolsController(base.BaseController): @wsme_pecan.wsexpose(pool_types.PoolResponse, wtypes.text) def get(self, id): """Gets a pool's details.""" - session = db_api.get_session() - db_pool = self.repositories.pool.get(session, id=id) + context = pecan.request.context.get('octavia_context') + db_pool = self.repositories.pool.get(context.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) @@ -55,9 +54,9 @@ class PoolsController(base.BaseController): @wsme_pecan.wsexpose([pool_types.PoolResponse]) def get_all(self): """Lists all pools on a listener.""" - session = db_api.get_session() + context = pecan.request.context.get('octavia_context') default_pool = self.repositories.listener.get( - session, id=self.listener_id).default_pool + context.session, id=self.listener_id).default_pool if default_pool: default_pool = [default_pool] else: @@ -123,19 +122,20 @@ class PoolsController(base.BaseController): is created, another cannot be created until the first one has been deleted. """ - session = db_api.get_session() - if self.repositories.listener.has_pool(session, self.listener_id): + context = pecan.request.context.get('octavia_context') + if self.repositories.listener.has_pool( + context.session, self.listener_id): raise exceptions.DuplicatePoolEntry() # 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 it's listeners as ACTIVE. - self._test_lb_status(session) + self._test_lb_status(context.session) pool_dict = pool.to_dict() sp_dict = pool_dict.pop('session_persistence', None) pool_dict['operating_status'] = constants.OFFLINE - return self._validate_create_pool(session, sp_dict, pool_dict) + return self._validate_create_pool(context.session, sp_dict, pool_dict) def _test_lb_status_put(self, session): """Verify load balancer is in a mutable status for put method.""" @@ -153,15 +153,15 @@ class PoolsController(base.BaseController): body=pool_types.PoolPUT, status_code=202) def put(self, id, pool): """Updates a pool on a listener.""" - session = db_api.get_session() - db_pool = self.repositories.pool.get(session, id=id) + context = pecan.request.context.get('octavia_context') + db_pool = self.repositories.pool.get(context.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) # 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 it's listeners as ACTIVE. - self._test_lb_status_put(session) + self._test_lb_status_put(context.session) try: LOG.info(_LI("Sending Update of Pool %s to handler"), id) @@ -169,16 +169,16 @@ class PoolsController(base.BaseController): except Exception: with excutils.save_and_reraise_exception(reraise=False): self.repositories.listener.update( - session, self.listener_id, + context.session, self.listener_id, operating_status=constants.ERROR) - db_pool = self.repositories.pool.get(session, id=id) + db_pool = self.repositories.pool.get(context.session, id=id) return self._convert_db_to_type(db_pool, pool_types.PoolResponse) @wsme_pecan.wsexpose(None, wtypes.text, status_code=202) def delete(self, id): """Deletes a pool from a listener.""" - session = db_api.get_session() - db_pool = self.repositories.pool.get(session, id=id) + context = pecan.request.context.get('octavia_context') + db_pool = self.repositories.pool.get(context.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) @@ -186,15 +186,15 @@ class PoolsController(base.BaseController): # that the listener is also in a mutable status because a load balancer # will only be ACTIVE when all it's listeners as ACTIVE. if not self.repositories.test_and_set_lb_and_listener_prov_status( - session, self.load_balancer_id, self.listener_id, + context.session, self.load_balancer_id, self.listener_id, constants.PENDING_UPDATE, constants.PENDING_UPDATE): LOG.info(_LI("Pool %s cannot be deleted because the 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) + db_lb = lb_repo.get(context.session, id=self.load_balancer_id) raise exceptions.ImmutableObject(resource=db_lb._name(), id=self.load_balancer_id) - db_pool = self.repositories.pool.get(session, id=id) + db_pool = self.repositories.pool.get(context.session, id=id) try: LOG.info(_LI("Sending Deletion of Pool %s to handler"), db_pool.id) @@ -202,12 +202,12 @@ class PoolsController(base.BaseController): except Exception: with excutils.save_and_reraise_exception(reraise=False): self.repositories.listener.update( - session, self.listener_id, + context.session, self.listener_id, operating_status=constants.ERROR) self.repositories.pool.update( - session, db_pool.id, + context.session, db_pool.id, operating_status=constants.ERROR) - db_pool = self.repositories.pool.get(session, id=db_pool.id) + db_pool = self.repositories.pool.get(context.session, id=db_pool.id) return self._convert_db_to_type(db_pool, pool_types.PoolResponse) @pecan.expose() @@ -217,10 +217,10 @@ class PoolsController(base.BaseController): Verifies that the pool passed in the url exists, and if so decides which controller, if any, should control be passed. """ - session = db_api.get_session() + context = pecan.request.context.get('octavia_context') if pool_id and len(remainder) and remainder[0] == 'members': remainder = remainder[1:] - db_pool = self.repositories.pool.get(session, id=pool_id) + 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(), @@ -231,7 +231,7 @@ class PoolsController(base.BaseController): pool_id=db_pool.id), remainder if pool_id and len(remainder) and remainder[0] == 'healthmonitor': remainder = remainder[1:] - db_pool = self.repositories.pool.get(session, id=pool_id) + 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(), diff --git a/octavia/api/v1/hooks.py b/octavia/api/v1/hooks.py index 52ebefaf94..23a0456691 100644 --- a/octavia/api/v1/hooks.py +++ b/octavia/api/v1/hooks.py @@ -18,14 +18,14 @@ from octavia.common import context class ContextHook(hooks.PecanHook): - @staticmethod - def on_route(state): + + def on_route(self, state): user_id = state.request.headers.get('X-User-Id') user_id = state.request.headers.get('X-User', user_id) project = state.request.headers.get('X-Tenant-Id') project = state.request.headers.get('X-Tenant', project) + project = state.request.headers.get('X-Project-Id', project) + project = state.request.headers.get('X-Project', project) auth_token = state.request.headers.get('X-Auth-Token') - - state.request.context = context.Context(user_id=user_id, - project_id=project, - auth_token=auth_token) + state.request.context['octavia_context'] = context.Context( + user_id=user_id, project_id=project, auth_token=auth_token) diff --git a/octavia/api/v1/types/health_monitor.py b/octavia/api/v1/types/health_monitor.py index 2f533bd0ef..45429fb5bb 100644 --- a/octavia/api/v1/types/health_monitor.py +++ b/octavia/api/v1/types/health_monitor.py @@ -28,6 +28,7 @@ class HealthMonitorResponse(base.BaseType): url_path = wtypes.wsattr(wtypes.text) expected_codes = wtypes.wsattr(wtypes.text) enabled = wtypes.wsattr(bool) + project_id = wtypes.wsattr(wtypes.UuidType()) class HealthMonitorPOST(base.BaseType): @@ -41,6 +42,7 @@ class HealthMonitorPOST(base.BaseType): url_path = wtypes.wsattr(wtypes.text) expected_codes = wtypes.wsattr(wtypes.text) enabled = wtypes.wsattr(bool, default=True) + project_id = wtypes.wsattr(wtypes.UuidType()) class HealthMonitorPUT(base.BaseType): diff --git a/octavia/api/v1/types/listener.py b/octavia/api/v1/types/listener.py index 0adf4c58fc..739af8873b 100644 --- a/octavia/api/v1/types/listener.py +++ b/octavia/api/v1/types/listener.py @@ -37,6 +37,7 @@ class ListenerResponse(base.BaseType): connection_limit = wtypes.wsattr(wtypes.IntegerType()) tls_certificate_id = wtypes.wsattr(wtypes.StringType(max_length=255)) sni_containers = [wtypes.StringType(max_length=255)] + project_id = wtypes.wsattr(wtypes.UuidType()) class ListenerPOST(base.BaseType): @@ -51,6 +52,7 @@ class ListenerPOST(base.BaseType): tls_certificate_id = wtypes.wsattr(wtypes.StringType(max_length=255)) tls_termination = wtypes.wsattr(TLSTermination) sni_containers = [wtypes.StringType(max_length=255)] + project_id = wtypes.wsattr(wtypes.UuidType()) class ListenerPUT(base.BaseType): diff --git a/octavia/api/v1/types/load_balancer.py b/octavia/api/v1/types/load_balancer.py index 80faad7bda..6dc5b38aa9 100644 --- a/octavia/api/v1/types/load_balancer.py +++ b/octavia/api/v1/types/load_balancer.py @@ -33,6 +33,7 @@ class LoadBalancerResponse(base.BaseType): operating_status = wtypes.wsattr(wtypes.StringType()) enabled = wtypes.wsattr(bool) vip = wtypes.wsattr(VIP) + project_id = wtypes.wsattr(wtypes.UuidType()) class LoadBalancerPOST(base.BaseType): @@ -42,10 +43,11 @@ class LoadBalancerPOST(base.BaseType): description = wtypes.wsattr(wtypes.StringType(max_length=255)) enabled = wtypes.wsattr(bool, default=True) vip = wtypes.wsattr(VIP, mandatory=True) + project_id = wtypes.wsattr(wtypes.UuidType()) class LoadBalancerPUT(base.BaseType): """Defines attributes that are acceptable of a PUT request.""" name = wtypes.wsattr(wtypes.StringType(max_length=255)) description = wtypes.wsattr(wtypes.StringType(max_length=255)) - enabled = wtypes.wsattr(bool) \ No newline at end of file + enabled = wtypes.wsattr(bool) diff --git a/octavia/api/v1/types/member.py b/octavia/api/v1/types/member.py index 3b7c934e82..7794b5a1bd 100644 --- a/octavia/api/v1/types/member.py +++ b/octavia/api/v1/types/member.py @@ -26,6 +26,7 @@ class MemberResponse(base.BaseType): protocol_port = wtypes.wsattr(wtypes.IntegerType()) weight = wtypes.wsattr(wtypes.IntegerType()) subnet_id = wtypes.wsattr(wtypes.UuidType()) + project_id = wtypes.wsattr(wtypes.UuidType()) class MemberPOST(base.BaseType): @@ -36,6 +37,7 @@ class MemberPOST(base.BaseType): protocol_port = wtypes.wsattr(wtypes.IntegerType(), mandatory=True) weight = wtypes.wsattr(wtypes.IntegerType(), default=1) subnet_id = wtypes.wsattr(wtypes.UuidType()) + project_id = wtypes.wsattr(wtypes.UuidType()) class MemberPUT(base.BaseType): diff --git a/octavia/api/v1/types/pool.py b/octavia/api/v1/types/pool.py index c011c1b5d9..4b5fe2bbc7 100644 --- a/octavia/api/v1/types/pool.py +++ b/octavia/api/v1/types/pool.py @@ -45,6 +45,7 @@ class PoolResponse(base.BaseType): protocol = wtypes.wsattr(wtypes.text) lb_algorithm = wtypes.wsattr(wtypes.text) session_persistence = wtypes.wsattr(SessionPersistenceResponse) + project_id = wtypes.wsattr(wtypes.UuidType()) class PoolPOST(base.BaseType): @@ -56,6 +57,7 @@ class PoolPOST(base.BaseType): protocol = wtypes.wsattr(wtypes.text, mandatory=True) lb_algorithm = wtypes.wsattr(wtypes.text, mandatory=True) session_persistence = wtypes.wsattr(SessionPersistencePOST) + project_id = wtypes.wsattr(wtypes.UuidType()) class PoolPUT(base.BaseType): diff --git a/octavia/common/context.py b/octavia/common/context.py index 504ab01906..cf3ff09ac2 100644 --- a/octavia/common/context.py +++ b/octavia/common/context.py @@ -22,6 +22,7 @@ class Context(common_context.RequestContext): super(Context, self).__init__(tenant=project_id, auth_token=auth_token, is_admin=is_admin, user=user_id) self._session = None + self.project_id = project_id @property def session(self): diff --git a/octavia/tests/functional/api/v1/test_health_monitor.py b/octavia/tests/functional/api/v1/test_health_monitor.py index 89ae10032c..72c27eb10c 100644 --- a/octavia/tests/functional/api/v1/test_health_monitor.py +++ b/octavia/tests/functional/api/v1/test_health_monitor.py @@ -12,6 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_utils import uuidutils + from octavia.common import constants from octavia.tests.functional.api.v1 import base @@ -74,6 +76,15 @@ class TestHealthMonitor(base.BaseAPITest): self.listener.get('id'), constants.ACTIVE, constants.ONLINE) + def test_create_with_project_id(self): + pid = uuidutils.generate_uuid() + api_hm = self.create_health_monitor(self.lb.get('id'), + self.listener.get('id'), + self.pool.get('id'), + constants.HEALTH_MONITOR_HTTP, + 1, 1, 1, 1, project_id=pid) + self.assertEqual(pid, api_hm.get('project_id')) + def test_bad_create(self): hm_json = {'name': 'test1'} self.post(self.hm_path, hm_json, status=400) diff --git a/octavia/tests/functional/api/v1/test_listener.py b/octavia/tests/functional/api/v1/test_listener.py index 6c75dffe16..05623e0e37 100644 --- a/octavia/tests/functional/api/v1/test_listener.py +++ b/octavia/tests/functional/api/v1/test_listener.py @@ -80,7 +80,8 @@ class TestListener(base.BaseAPITest): 'enabled': False, 'protocol': constants.PROTOCOL_HTTP, 'protocol_port': 80, 'connection_limit': 10, 'tls_certificate_id': uuidutils.generate_uuid(), - 'sni_containers': [sni1, sni2]} + 'sni_containers': [sni1, sni2], + 'project_id': uuidutils.generate_uuid()} lb_listener.update(optionals) response = self.post(self.listeners_path, lb_listener) listener_api = response.json @@ -108,6 +109,9 @@ class TestListener(base.BaseAPITest): def test_create_with_id(self): self.test_create(id=uuidutils.generate_uuid()) + def test_create_with_project_id(self): + self.test_create(project_id=uuidutils.generate_uuid()) + def test_create_with_duplicate_id(self): listener = self.create_listener(self.lb.get('id'), constants.PROTOCOL_HTTP, @@ -121,7 +125,7 @@ class TestListener(base.BaseAPITest): def test_create_defaults(self): defaults = {'name': None, 'description': None, 'enabled': True, 'connection_limit': None, 'tls_certificate_id': None, - 'sni_containers': []} + 'sni_containers': [], 'project_id': None} lb_listener = {'protocol': constants.PROTOCOL_HTTP, 'protocol_port': 80} response = self.post(self.listeners_path, lb_listener) diff --git a/octavia/tests/functional/api/v1/test_load_balancer.py b/octavia/tests/functional/api/v1/test_load_balancer.py index f62b07dc13..dc00a051b8 100644 --- a/octavia/tests/functional/api/v1/test_load_balancer.py +++ b/octavia/tests/functional/api/v1/test_load_balancer.py @@ -52,6 +52,9 @@ class TestLoadBalancer(base.BaseAPITest): lb_json = {'name': 'test1'} self.post(self.LB_PATH, lb_json, status=400) + def test_create_with_project_id(self): + self.test_create(project_id=uuidutils.generate_uuid()) + def test_get_all(self): lb1 = self.create_load_balancer({}, name='lb1') lb2 = self.create_load_balancer({}, name='lb2') @@ -64,6 +67,26 @@ class TestLoadBalancer(base.BaseAPITest): self.assertIn((lb2.get('id'), lb2.get('name')), lb_id_names) self.assertIn((lb3.get('id'), lb3.get('name')), lb_id_names) + def test_get_all_by_project_id(self): + project1_id = uuidutils.generate_uuid() + project2_id = uuidutils.generate_uuid() + lb1 = self.create_load_balancer({}, name='lb1', project_id=project1_id) + lb2 = self.create_load_balancer({}, name='lb2', project_id=project1_id) + lb3 = self.create_load_balancer({}, name='lb3', project_id=project2_id) + project1_path = "{0}?project_id={1}".format(self.LBS_PATH, project1_id) + response = self.get(project1_path) + lbs = response.json + lb_id_names = [(lb.get('id'), lb.get('name')) for lb in lbs] + self.assertEqual(2, len(lbs)) + self.assertIn((lb1.get('id'), lb1.get('name')), lb_id_names) + self.assertIn((lb2.get('id'), lb2.get('name')), lb_id_names) + project2_path = "{0}?project_id={1}".format(self.LBS_PATH, project2_id) + response = self.get(project2_path) + lbs = response.json + lb_id_names = [(lb.get('id'), lb.get('name')) for lb in lbs] + self.assertEqual(1, len(lbs)) + self.assertIn((lb3.get('id'), lb3.get('name')), lb_id_names) + def test_get(self): vip = {'ip_address': '10.0.0.1', 'port_id': uuidutils.generate_uuid(), diff --git a/octavia/tests/functional/api/v1/test_member.py b/octavia/tests/functional/api/v1/test_member.py index d97a271410..9e8f151575 100644 --- a/octavia/tests/functional/api/v1/test_member.py +++ b/octavia/tests/functional/api/v1/test_member.py @@ -109,6 +109,14 @@ class TestMember(base.BaseAPITest): '10.0.0.1', 80, id=mid) self.assertEqual(mid, api_member.get('id')) + def test_create_with_project_id(self): + pid = uuidutils.generate_uuid() + api_member = self.create_member(self.lb.get('id'), + self.listener.get('id'), + self.pool.get('id'), + '10.0.0.1', 80, project_id=pid) + self.assertEqual(pid, api_member.get('project_id')) + def test_create_with_duplicate_id(self): member = self.create_member(self.lb.get('id'), self.listener.get('id'), diff --git a/octavia/tests/functional/api/v1/test_pool.py b/octavia/tests/functional/api/v1/test_pool.py index 45c8155695..947b5acfba 100644 --- a/octavia/tests/functional/api/v1/test_pool.py +++ b/octavia/tests/functional/api/v1/test_pool.py @@ -96,6 +96,15 @@ class TestPool(base.BaseAPITest): id=pid) self.assertEqual(pid, api_pool.get('id')) + def test_create_with_project_id(self): + pid = uuidutils.generate_uuid() + api_pool = self.create_pool(self.lb.get('id'), + self.listener.get('id'), + constants.PROTOCOL_HTTP, + constants.LB_ALGORITHM_ROUND_ROBIN, + project_id=pid) + self.assertEqual(pid, api_pool.get('project_id')) + def test_create_with_duplicate_id(self): pool = self.create_pool(self.lb.get('id'), self.listener.get('id'),