diff --git a/devstack/lib/kuryr_kubernetes b/devstack/lib/kuryr_kubernetes index 275e0b231..bc1eb714e 100644 --- a/devstack/lib/kuryr_kubernetes +++ b/devstack/lib/kuryr_kubernetes @@ -696,3 +696,172 @@ function run_openshift_node { run_process openshift-node "sudo $command" fi } + +# lb_state +# Description: Returns the state of the load balancer +# Params: +# id - Id or name of the loadbalancer the state of which needs to be +# retrieved. +function lb_state { + local lb_id + + lb_id="$1" + # Checks Neutron lbaas for the Load balancer state + if is_service_enabled octavia; then + openstack loadbalancer show "$lb_id" | \ + awk '/provisioning_status/ {print $4}' + else + neutron lbaas-loadbalancer-show "$lb_id" | \ + awk '/provisioning_status/ {print $4}' + fi +} + +# create_load_balancer +# Description: Creates an OpenStack Load Balancer with either neutron LBaaS +# or Octavia +# Params: +# lb_name: Name to give to the load balancer. +# lb_vip: Virtual IP to give to the load balancer. +# lb_vip_subnet: Id or name of the subnet where lb_vip should be +# allocated. +function create_load_balancer { + local lb_name + local lb_vip + local lb_vip_subnet + + lb_name="$1" + lb_vip="$2" + lb_vip_subnet="$3" + if is_service_enabled octavia; then + openstack loadbalancer create --name "$lb_name" \ + --vip-address "$lb_vip" \ + --vip-subnet-id "$lb_vip_subnet" + else + neutron lbaas-loadbalancer-create --name "$lb_name" \ + --vip-address "$lb_vip" \ + "$lb_vip_subnet" + fi +} + +# create_load_balancer_listener +# Description: Creates an OpenStack Load Balancer Listener for the specified +# Load Balancer with either neutron LBaaS or Octavia +# Params: +# name: Name to give to the load balancer listener. +# protocol: Whether it is HTTP, HTTPS, TCP, etc. +# port: The TCP port number to listen to. +# lb: Id or name of the Load Balancer we want to add the Listener to. +function create_load_balancer_listener { + local name + local protocol + local port + local lb + + name="$1" + protocol="$2" + port="$3" + lb="$4" + + # Octavia needs the LB to be active for the listener + while [[ "$(lb_state $lb)" != "ACTIVE" ]]; do + sleep 1 + done + + if is_service_enabled octavia; then + openstack loadbalancer listener create --name "$name" \ + --protocol "$protocol" \ + --protocol-port "$port" \ + "$lb" + else + neutron lbaas-listener-create --name "$name" \ + --protocol "$protocol" \ + --protocol-port "$port" \ + --loadbalancer "$lb" + fi +} + +# create_load_balancer_pool +# Description: Creates an OpenStack Load Balancer Pool for the specified +# Load Balancer listener with either neutron LBaaS or Octavia +# Params: +# name: Name to give to the load balancer listener. +# protocol: Whether it is HTTP, HTTPS, TCP, etc. +# algorithm: Load Balancing algorithm to use. +# listener: Id or name of the Load Balancer Listener we want to add the +# pool to. +# lb: Id or name of the Load Balancer we want to add the pool to +# (optional). +function create_load_balancer_pool { + local name + local protocol + local algorithm + local listener + local lb + + name="$1" + protocol="$2" + algorithm="$3" + listener="$4" + lb="$5" + + # We must wait for the LB to be active before we can put a Pool for it + while [[ "$(lb_state $lb)" != "ACTIVE" ]]; do + sleep 1 + done + + if is_service_enabled octavia; then + openstack loadbalancer pool create --name "$name" \ + --listener "$listener" \ + --protocol "$protocol" \ + --lb-algorithm "$algorithm" + else + neutron lbaas-pool-create --name "$name" \ + --loadbalancer "$lb_name" \ + --listener "$listener" \ + --protocol "$protocol" \ + --lb-algorithm "$algorithm" + fi +} + +# create_load_balancer_member +# Description: Creates an OpenStack load balancer pool member +# Params: +# name: Name to give to the load balancer pool member. +# address: Whether it is HTTP, HTTPS, TCP, etc. +# port: Port number the pool member is listening on. +# pool: Id or name of the Load Balancer pool this member belongs to. +# subnet: Id or name of the subnet the member address belongs to. +# lb: Id or name of the load balancer the member belongs to. +function create_load_balancer_member { + local name + local address + local port + local pool + local subnet + local lb + + name="$1" + address="$2" + port="$3" + pool="$4" + subnet="$5" + lb="$6" + + # We must wait for the pool creation update before we can add members + while [[ "$(lb_state $lb)" != "ACTIVE" ]]; do + sleep 1 + done + + if is_service_enabled octavia; then + openstack loadbalancer member create --name "$name" \ + --address "$address" \ + --protocol-port "$port" \ + "$pool" + else + neutron lbaas-member-create --name "$name" \ + --subnet "$subnet" \ + --address "$address" \ + --protocol-port "$port" \ + "$pool" + fi +} diff --git a/devstack/local.conf.df.sample b/devstack/local.conf.df.sample index fb79d2839..205a99c48 100644 --- a/devstack/local.conf.df.sample +++ b/devstack/local.conf.df.sample @@ -81,11 +81,6 @@ if [[ "$KURYR_K8S_LBAAS_USE_OCTAVIA" == "True" ]]; then ### Glance enable_service g-api enable_service g-reg - ### Neutron-lbaas - #### In case Octavia is older than Pike, neutron-lbaas is needed - enable_plugin neutron-lbaas \ - git://git.openstack.org/openstack/neutron-lbaas - enable_service q-lbaasv2 else # LBaaSv2 service and Haproxy agent enable_plugin neutron-lbaas \ diff --git a/devstack/local.conf.openshift.sample b/devstack/local.conf.openshift.sample index 35e1b723f..10f57bc98 100644 --- a/devstack/local.conf.openshift.sample +++ b/devstack/local.conf.openshift.sample @@ -62,11 +62,6 @@ if [[ "$KURYR_K8S_LBAAS_USE_OCTAVIA" == "True" ]]; then ### Glance enable_service g-api enable_service g-reg - ### Neutron-lbaas - #### In case Octavia is older than Pike, neutron-lbaas is needed - enable_plugin neutron-lbaas \ - git://git.openstack.org/openstack/neutron-lbaas - enable_service q-lbaasv2 else # LBaaSv2 service and Haproxy agent enable_plugin neutron-lbaas \ diff --git a/devstack/local.conf.sample b/devstack/local.conf.sample index 4589b05f7..49328c5af 100644 --- a/devstack/local.conf.sample +++ b/devstack/local.conf.sample @@ -62,11 +62,6 @@ if [[ "$KURYR_K8S_LBAAS_USE_OCTAVIA" == "True" ]]; then ### Glance enable_service g-api enable_service g-reg - ### Neutron-lbaas - #### In case Octavia is older than Pike, neutron-lbaas is needed - enable_plugin neutron-lbaas \ - git://git.openstack.org/openstack/neutron-lbaas - enable_service q-lbaasv2 else # LBaaSv2 service and Haproxy agent enable_plugin neutron-lbaas \ diff --git a/devstack/plugin.sh b/devstack/plugin.sh index e8f4c3bc5..f8eb55902 100644 --- a/devstack/plugin.sh +++ b/devstack/plugin.sh @@ -188,11 +188,6 @@ function copy_tempest_kubeconfig { fi } -function _lb_state { - # Checks Neutron lbaas for the Load balancer state - neutron lbaas-loadbalancer-show "$1" | awk '/provisioning_status/ {print $4}' -} - function create_k8s_api_service { # This allows pods that need access to kubernetes API (like the # containerized kuryr controller or kube-dns) to talk to the K8s API @@ -211,34 +206,11 @@ function create_k8s_api_service { k8s_api_clusterip=$(_cidr_range "$service_cidr" | cut -f1) - neutron lbaas-loadbalancer-create --name "$lb_name" \ - --vip-address "$k8s_api_clusterip" \ + create_load_balancer "$lb_name" "$k8s_api_clusterip" \ "$KURYR_NEUTRON_DEFAULT_SERVICE_SUBNET" - - # Octavia needs the LB to be active for the listener - while [[ "$(_lb_state $lb_name)" != "ACTIVE" ]]; do - sleep 1 - done - - neutron lbaas-listener-create --loadbalancer "$lb_name" \ - --name default/kubernetes:443 \ - --protocol HTTPS \ - --protocol-port 443 - - # We must wait for the LB to be active before we can put a Pool for it - while [[ "$(_lb_state $lb_name)" != "ACTIVE" ]]; do - sleep 1 - done - - neutron lbaas-pool-create --loadbalancer "$lb_name" \ - --name default/kubernetes:443 \ - --listener default/kubernetes:443 \ - --protocol HTTPS \ - --lb-algorithm ROUND_ROBIN - # We must wait for the pending pool creation update - while [[ "$(_lb_state $lb_name)" != "ACTIVE" ]]; do - sleep 1 - done + create_load_balancer_listener default/kubernetes:443 HTTPS 443 "$lb_name" + create_load_balancer_pool default/kubernetes:443 HTTPS ROUND_ROBIN \ + default/kubernetes:443 "$lb_name" local api_port if is_service_enabled openshift-master; then @@ -246,10 +218,9 @@ function create_k8s_api_service { else api_port=6443 fi - neutron lbaas-member-create --subnet public-subnet \ - --address ${kubelet_iface_ip} \ - --protocol-port ${api_port} \ - default/kubernetes:443 + + create_load_balancer_member "$(hostname)" "$kubelet_iface_ip" "$api_port" \ + default/kubernetes:443 public-subnet "$lb_name" } function configure_neutron_defaults { diff --git a/kuryr_kubernetes/clients.py b/kuryr_kubernetes/clients.py index 9fb2d9f53..ca9006ecd 100644 --- a/kuryr_kubernetes/clients.py +++ b/kuryr_kubernetes/clients.py @@ -17,9 +17,11 @@ from kuryr.lib import utils from kuryr_kubernetes import config from kuryr_kubernetes import k8s_client +from neutronclient import client as n_client _clients = {} _NEUTRON_CLIENT = 'neutron-client' +_LB_CLIENT = 'load-balancer-client' _KUBERNETES_CLIENT = 'kubernetes-client' @@ -27,12 +29,17 @@ def get_neutron_client(): return _clients[_NEUTRON_CLIENT] +def get_loadbalancer_client(): + return _clients[_LB_CLIENT] + + def get_kubernetes_client(): return _clients[_KUBERNETES_CLIENT] def setup_clients(): setup_neutron_client() + setup_loadbalancer_client() setup_kubernetes_client() @@ -40,6 +47,24 @@ def setup_neutron_client(): _clients[_NEUTRON_CLIENT] = utils.get_neutron_client() +def setup_loadbalancer_client(): + neutron_client = get_neutron_client() + if any(ext['alias'] == 'lbaasv2' for + ext in neutron_client.list_extensions()['extensions']): + _clients[_LB_CLIENT] = neutron_client + else: + # Since Octavia is lbaasv2 API compatible (A superset of it) we'll just + # wire an extra neutron client instance to point to it + lbaas_client = utils.get_neutron_client() + conf_group = utils.kuryr_config.neutron_group.name + auth_plugin = utils.get_auth_plugin(conf_group) + octo_httpclient = n_client.construct_http_client( + session=utils.get_keystone_session(conf_group, auth_plugin), + service_type='load-balancer') + lbaas_client.httpclient = octo_httpclient + _clients[_LB_CLIENT] = lbaas_client + + def setup_kubernetes_client(): _clients[_KUBERNETES_CLIENT] = k8s_client.K8sClient( config.CONF.kubernetes.api_root) diff --git a/kuryr_kubernetes/controller/drivers/lbaasv2.py b/kuryr_kubernetes/controller/drivers/lbaasv2.py index c7504969e..e1fb99628 100644 --- a/kuryr_kubernetes/controller/drivers/lbaasv2.py +++ b/kuryr_kubernetes/controller/drivers/lbaasv2.py @@ -63,8 +63,9 @@ class LBaaSv2Driver(base.LBaaSDriver): def release_loadbalancer(self, endpoints, loadbalancer): neutron = clients.get_neutron_client() + lbaas = clients.get_loadbalancer_client() self._release(loadbalancer, loadbalancer, - neutron.delete_loadbalancer, loadbalancer.id) + lbaas.delete_loadbalancer, loadbalancer.id) sg_id = self._find_listeners_sg(loadbalancer) if sg_id: @@ -150,8 +151,9 @@ class LBaaSv2Driver(base.LBaaSDriver): def release_listener(self, endpoints, loadbalancer, listener): neutron = clients.get_neutron_client() + lbaas = clients.get_loadbalancer_client() self._release(loadbalancer, listener, - neutron.delete_listener, + lbaas.delete_listener, listener.id) sg_id = self._find_listeners_sg(loadbalancer) @@ -176,9 +178,9 @@ class LBaaSv2Driver(base.LBaaSDriver): self._find_pool) def release_pool(self, endpoints, loadbalancer, pool): - neutron = clients.get_neutron_client() + lbaas = clients.get_loadbalancer_client() self._release(loadbalancer, pool, - neutron.delete_lbaas_pool, + lbaas.delete_lbaas_pool, pool.id) def ensure_member(self, endpoints, loadbalancer, pool, @@ -196,9 +198,9 @@ class LBaaSv2Driver(base.LBaaSDriver): self._find_member) def release_member(self, endpoints, loadbalancer, member): - neutron = clients.get_neutron_client() + lbaas = clients.get_loadbalancer_client() self._release(loadbalancer, member, - neutron.delete_lbaas_member, + lbaas.delete_lbaas_member, member.id, member.pool_id) def _get_vip_port_id(self, loadbalancer): @@ -217,11 +219,10 @@ class LBaaSv2Driver(base.LBaaSDriver): return None def _create_loadbalancer(self, loadbalancer): - neutron = clients.get_neutron_client() - response = neutron.create_loadbalancer({'loadbalancer': { + lbaas = clients.get_loadbalancer_client() + response = lbaas.create_loadbalancer({'loadbalancer': { 'name': loadbalancer.name, 'project_id': loadbalancer.project_id, - 'tenant_id': loadbalancer.project_id, 'vip_address': str(loadbalancer.ip), 'vip_subnet_id': loadbalancer.subnet_id}}) loadbalancer.id = response['loadbalancer']['id'] @@ -230,11 +231,10 @@ class LBaaSv2Driver(base.LBaaSDriver): return loadbalancer def _find_loadbalancer(self, loadbalancer): - neutron = clients.get_neutron_client() - response = neutron.list_loadbalancers( + lbaas = clients.get_loadbalancer_client() + response = lbaas.list_loadbalancers( name=loadbalancer.name, project_id=loadbalancer.project_id, - tenant_id=loadbalancer.project_id, vip_address=str(loadbalancer.ip), vip_subnet_id=loadbalancer.subnet_id) @@ -248,11 +248,10 @@ class LBaaSv2Driver(base.LBaaSDriver): return loadbalancer def _create_listener(self, listener): - neutron = clients.get_neutron_client() - response = neutron.create_listener({'listener': { + lbaas = clients.get_loadbalancer_client() + response = lbaas.create_listener({'listener': { 'name': listener.name, 'project_id': listener.project_id, - 'tenant_id': listener.project_id, 'loadbalancer_id': listener.loadbalancer_id, 'protocol': listener.protocol, 'protocol_port': listener.port}}) @@ -260,11 +259,10 @@ class LBaaSv2Driver(base.LBaaSDriver): return listener def _find_listener(self, listener): - neutron = clients.get_neutron_client() - response = neutron.list_listeners( + lbaas = clients.get_loadbalancer_client() + response = lbaas.list_listeners( name=listener.name, project_id=listener.project_id, - tenant_id=listener.project_id, loadbalancer_id=listener.loadbalancer_id, protocol=listener.protocol, protocol_port=listener.port) @@ -279,12 +277,11 @@ class LBaaSv2Driver(base.LBaaSDriver): def _create_pool(self, pool): # TODO(ivc): make lb_algorithm configurable lb_algorithm = 'ROUND_ROBIN' - neutron = clients.get_neutron_client() + lbaas = clients.get_loadbalancer_client() try: - response = neutron.create_lbaas_pool({'pool': { + response = lbaas.create_lbaas_pool({'pool': { 'name': pool.name, 'project_id': pool.project_id, - 'tenant_id': pool.project_id, 'listener_id': pool.listener_id, 'loadbalancer_id': pool.loadbalancer_id, 'protocol': pool.protocol, @@ -293,14 +290,14 @@ class LBaaSv2Driver(base.LBaaSDriver): return pool except n_exc.StateInvalidClient: with excutils.save_and_reraise_exception(): - self._cleanup_bogus_pool(neutron, pool, lb_algorithm) + self._cleanup_bogus_pool(lbaas, pool, lb_algorithm) - def _cleanup_bogus_pool(self, neutron, pool, lb_algorithm): + def _cleanup_bogus_pool(self, lbaas, pool, lb_algorithm): # REVISIT(ivc): LBaaSv2 creates pool object despite raising an # exception. The created pool is not bound to listener, but # it is bound to loadbalancer and will cause an error on # 'release_loadbalancer'. - pools = neutron.list_lbaas_pools( + pools = lbaas.list_lbaas_pools( name=pool.name, project_id=pool.project_id, loadbalancer_id=pool.loadbalancer_id, protocol=pool.protocol, lb_algorithm=lb_algorithm) @@ -310,16 +307,15 @@ class LBaaSv2Driver(base.LBaaSDriver): try: LOG.debug("Removing bogus pool %(id)s %(pool)s", { 'id': pool_id, 'pool': pool}) - neutron.delete_lbaas_pool(pool_id) + lbaas.delete_lbaas_pool(pool_id) except (n_exc.NotFound, n_exc.StateInvalidClient): pass def _find_pool(self, pool): - neutron = clients.get_neutron_client() - response = neutron.list_lbaas_pools( + lbaas = clients.get_loadbalancer_client() + response = lbaas.list_lbaas_pools( name=pool.name, project_id=pool.project_id, - tenant_id=pool.project_id, loadbalancer_id=pool.loadbalancer_id, protocol=pool.protocol) @@ -333,11 +329,10 @@ class LBaaSv2Driver(base.LBaaSDriver): return pool def _create_member(self, member): - neutron = clients.get_neutron_client() - response = neutron.create_lbaas_member(member.pool_id, {'member': { + lbaas = clients.get_loadbalancer_client() + response = lbaas.create_lbaas_member(member.pool_id, {'member': { 'name': member.name, 'project_id': member.project_id, - 'tenant_id': member.project_id, 'subnet_id': member.subnet_id, 'address': str(member.ip), 'protocol_port': member.port}}) @@ -345,12 +340,11 @@ class LBaaSv2Driver(base.LBaaSDriver): return member def _find_member(self, member): - neutron = clients.get_neutron_client() - response = neutron.list_lbaas_members( + lbaas = clients.get_loadbalancer_client() + response = lbaas.list_lbaas_members( member.pool_id, name=member.name, project_id=member.project_id, - tenant_id=member.project_id, subnet_id=member.subnet_id, address=member.ip, protocol_port=member.port) @@ -398,10 +392,10 @@ class LBaaSv2Driver(base.LBaaSDriver): raise k_exc.ResourceNotReady(obj) def _wait_for_provisioning(self, loadbalancer, timeout): - neutron = clients.get_neutron_client() + lbaas = clients.get_loadbalancer_client() for remaining in self._provisioning_timer(timeout): - response = neutron.show_loadbalancer(loadbalancer.id) + response = lbaas.show_loadbalancer(loadbalancer.id) status = response['loadbalancer']['provisioning_status'] if status == 'ACTIVE': LOG.debug("Provisioning complete for %(lb)s", { diff --git a/kuryr_kubernetes/tests/unit/controller/drivers/test_lbaasv2.py b/kuryr_kubernetes/tests/unit/controller/drivers/test_lbaasv2.py index f8249df62..c9a966ede 100644 --- a/kuryr_kubernetes/tests/unit/controller/drivers/test_lbaasv2.py +++ b/kuryr_kubernetes/tests/unit/controller/drivers/test_lbaasv2.py @@ -73,7 +73,8 @@ class TestLBaaSv2Driver(test_base.TestCase): sg_ids, 'ClusterIP') def test_release_loadbalancer(self): - neutron = self.useFixture(k_fix.MockNeutronClient()).client + self.useFixture(k_fix.MockNeutronClient()).client + lbaas = self.useFixture(k_fix.MockLBaaSClient()).client cls = d_lbaasv2.LBaaSv2Driver m_driver = mock.Mock(spec=d_lbaasv2.LBaaSv2Driver) endpoints = mock.sentinel.endpoints @@ -82,7 +83,7 @@ class TestLBaaSv2Driver(test_base.TestCase): cls.release_loadbalancer(m_driver, endpoints, loadbalancer) m_driver._release.assert_called_once_with(loadbalancer, loadbalancer, - neutron.delete_loadbalancer, + lbaas.delete_loadbalancer, loadbalancer.id) def test_ensure_listener(self): @@ -121,6 +122,7 @@ class TestLBaaSv2Driver(test_base.TestCase): def test_release_listener(self): neutron = self.useFixture(k_fix.MockNeutronClient()).client + lbaas = self.useFixture(k_fix.MockLBaaSClient()).client neutron.list_security_group_rules.return_value = { 'security_group_rules': []} cls = d_lbaasv2.LBaaSv2Driver @@ -132,7 +134,7 @@ class TestLBaaSv2Driver(test_base.TestCase): cls.release_listener(m_driver, endpoints, loadbalancer, listener) m_driver._release.assert_called_once_with(loadbalancer, listener, - neutron.delete_listener, + lbaas.delete_listener, listener.id) def test_ensure_pool(self): @@ -162,7 +164,7 @@ class TestLBaaSv2Driver(test_base.TestCase): self.assertEqual(expected_resp, resp) def test_release_pool(self): - neutron = self.useFixture(k_fix.MockNeutronClient()).client + lbaas = self.useFixture(k_fix.MockLBaaSClient()).client cls = d_lbaasv2.LBaaSv2Driver m_driver = mock.Mock(spec=d_lbaasv2.LBaaSv2Driver) endpoints = mock.sentinel.endpoints @@ -172,7 +174,7 @@ class TestLBaaSv2Driver(test_base.TestCase): cls.release_pool(m_driver, endpoints, loadbalancer, pool) m_driver._release.assert_called_once_with(loadbalancer, pool, - neutron.delete_lbaas_pool, + lbaas.delete_lbaas_pool, pool.id) def test_ensure_member(self): @@ -207,7 +209,7 @@ class TestLBaaSv2Driver(test_base.TestCase): self.assertEqual(expected_resp, resp) def test_release_member(self): - neutron = self.useFixture(k_fix.MockNeutronClient()).client + lbaas = self.useFixture(k_fix.MockLBaaSClient()).client cls = d_lbaasv2.LBaaSv2Driver m_driver = mock.Mock(spec=d_lbaasv2.LBaaSv2Driver) endpoints = mock.sentinel.endpoints @@ -217,11 +219,11 @@ class TestLBaaSv2Driver(test_base.TestCase): cls.release_member(m_driver, endpoints, loadbalancer, member) m_driver._release.assert_called_once_with(loadbalancer, member, - neutron.delete_lbaas_member, + lbaas.delete_lbaas_member, member.id, member.pool_id) def test_create_loadbalancer(self): - neutron = self.useFixture(k_fix.MockNeutronClient()).client + lbaas = self.useFixture(k_fix.MockLBaaSClient()).client cls = d_lbaasv2.LBaaSv2Driver m_driver = mock.Mock(spec=d_lbaasv2.LBaaSv2Driver) loadbalancer = obj_lbaas.LBaaSLoadBalancer( @@ -232,22 +234,21 @@ class TestLBaaSv2Driver(test_base.TestCase): req = {'loadbalancer': { 'name': loadbalancer.name, 'project_id': loadbalancer.project_id, - 'tenant_id': loadbalancer.project_id, 'vip_address': str(loadbalancer.ip), 'vip_subnet_id': loadbalancer.subnet_id, }} resp = {'loadbalancer': {'id': loadbalancer_id, 'provider': 'haproxy'}} - neutron.create_loadbalancer.return_value = resp + lbaas.create_loadbalancer.return_value = resp ret = cls._create_loadbalancer(m_driver, loadbalancer) - neutron.create_loadbalancer.assert_called_once_with(req) + lbaas.create_loadbalancer.assert_called_once_with(req) for attr in loadbalancer.obj_fields: self.assertEqual(getattr(loadbalancer, attr), getattr(ret, attr)) self.assertEqual(loadbalancer_id, ret.id) def test_find_loadbalancer(self): - neutron = self.useFixture(k_fix.MockNeutronClient()).client + lbaas = self.useFixture(k_fix.MockLBaaSClient()).client cls = d_lbaasv2.LBaaSv2Driver m_driver = mock.Mock(spec=d_lbaasv2.LBaaSv2Driver) loadbalancer = obj_lbaas.LBaaSLoadBalancer( @@ -257,13 +258,12 @@ class TestLBaaSv2Driver(test_base.TestCase): loadbalancer_id = '00EE9E11-91C2-41CF-8FD4-7970579E5C4C' resp = {'loadbalancers': [{'id': loadbalancer_id, 'provider': 'haproxy'}]} - neutron.list_loadbalancers.return_value = resp + lbaas.list_loadbalancers.return_value = resp ret = cls._find_loadbalancer(m_driver, loadbalancer) - neutron.list_loadbalancers.assert_called_once_with( + lbaas.list_loadbalancers.assert_called_once_with( name=loadbalancer.name, project_id=loadbalancer.project_id, - tenant_id=loadbalancer.project_id, vip_address=str(loadbalancer.ip), vip_subnet_id=loadbalancer.subnet_id) for attr in loadbalancer.obj_fields: @@ -272,26 +272,25 @@ class TestLBaaSv2Driver(test_base.TestCase): self.assertEqual(loadbalancer_id, ret.id) def test_find_loadbalancer_not_found(self): - neutron = self.useFixture(k_fix.MockNeutronClient()).client + lbaas = self.useFixture(k_fix.MockLBaaSClient()).client cls = d_lbaasv2.LBaaSv2Driver m_driver = mock.Mock(spec=d_lbaasv2.LBaaSv2Driver) loadbalancer = obj_lbaas.LBaaSLoadBalancer( name='TEST_NAME', project_id='TEST_PROJECT', ip='1.2.3.4', subnet_id='D3FA400A-F543-4B91-9CD3-047AF0CE42D1') resp = {'loadbalancers': []} - neutron.list_loadbalancers.return_value = resp + lbaas.list_loadbalancers.return_value = resp ret = cls._find_loadbalancer(m_driver, loadbalancer) - neutron.list_loadbalancers.assert_called_once_with( + lbaas.list_loadbalancers.assert_called_once_with( name=loadbalancer.name, project_id=loadbalancer.project_id, - tenant_id=loadbalancer.project_id, vip_address=str(loadbalancer.ip), vip_subnet_id=loadbalancer.subnet_id) self.assertIsNone(ret) def test_create_listener(self): - neutron = self.useFixture(k_fix.MockNeutronClient()).client + lbaas = self.useFixture(k_fix.MockLBaaSClient()).client cls = d_lbaasv2.LBaaSv2Driver m_driver = mock.Mock(spec=d_lbaasv2.LBaaSv2Driver) listener = obj_lbaas.LBaaSListener( @@ -301,22 +300,21 @@ class TestLBaaSv2Driver(test_base.TestCase): req = {'listener': { 'name': listener.name, 'project_id': listener.project_id, - 'tenant_id': listener.project_id, 'loadbalancer_id': listener.loadbalancer_id, 'protocol': listener.protocol, 'protocol_port': listener.port}} resp = {'listener': {'id': listener_id}} - neutron.create_listener.return_value = resp + lbaas.create_listener.return_value = resp ret = cls._create_listener(m_driver, listener) - neutron.create_listener.assert_called_once_with(req) + lbaas.create_listener.assert_called_once_with(req) for attr in listener.obj_fields: self.assertEqual(getattr(listener, attr), getattr(ret, attr)) self.assertEqual(listener_id, ret.id) def test_find_listener(self): - neutron = self.useFixture(k_fix.MockNeutronClient()).client + lbaas = self.useFixture(k_fix.MockLBaaSClient()).client cls = d_lbaasv2.LBaaSv2Driver m_driver = mock.Mock(spec=d_lbaasv2.LBaaSv2Driver) listener = obj_lbaas.LBaaSListener( @@ -324,13 +322,12 @@ class TestLBaaSv2Driver(test_base.TestCase): port=1234, loadbalancer_id='00EE9E11-91C2-41CF-8FD4-7970579E5C4C') listener_id = 'A57B7771-6050-4CA8-A63C-443493EC98AB' resp = {'listeners': [{'id': listener_id}]} - neutron.list_listeners.return_value = resp + lbaas.list_listeners.return_value = resp ret = cls._find_listener(m_driver, listener) - neutron.list_listeners.assert_called_once_with( + lbaas.list_listeners.assert_called_once_with( name=listener.name, project_id=listener.project_id, - tenant_id=listener.project_id, loadbalancer_id=listener.loadbalancer_id, protocol=listener.protocol, protocol_port=listener.port) @@ -340,27 +337,26 @@ class TestLBaaSv2Driver(test_base.TestCase): self.assertEqual(listener_id, ret.id) def test_find_listener_not_found(self): - neutron = self.useFixture(k_fix.MockNeutronClient()).client + lbaas = self.useFixture(k_fix.MockLBaaSClient()).client cls = d_lbaasv2.LBaaSv2Driver m_driver = mock.Mock(spec=d_lbaasv2.LBaaSv2Driver) listener = obj_lbaas.LBaaSListener( name='TEST_NAME', project_id='TEST_PROJECT', protocol='TCP', port=1234, loadbalancer_id='00EE9E11-91C2-41CF-8FD4-7970579E5C4C') resp = {'listeners': []} - neutron.list_listeners.return_value = resp + lbaas.list_listeners.return_value = resp ret = cls._find_listener(m_driver, listener) - neutron.list_listeners.assert_called_once_with( + lbaas.list_listeners.assert_called_once_with( name=listener.name, project_id=listener.project_id, - tenant_id=listener.project_id, loadbalancer_id=listener.loadbalancer_id, protocol=listener.protocol, protocol_port=listener.port) self.assertIsNone(ret) def test_create_pool(self): - neutron = self.useFixture(k_fix.MockNeutronClient()).client + lbaas = self.useFixture(k_fix.MockLBaaSClient()).client cls = d_lbaasv2.LBaaSv2Driver m_driver = mock.Mock(spec=d_lbaasv2.LBaaSv2Driver) lb_algorithm = 'ROUND_ROBIN' @@ -372,23 +368,22 @@ class TestLBaaSv2Driver(test_base.TestCase): req = {'pool': { 'name': pool.name, 'project_id': pool.project_id, - 'tenant_id': pool.project_id, 'listener_id': pool.listener_id, 'loadbalancer_id': pool.loadbalancer_id, 'protocol': pool.protocol, 'lb_algorithm': lb_algorithm}} resp = {'pool': {'id': pool_id}} - neutron.create_lbaas_pool.return_value = resp + lbaas.create_lbaas_pool.return_value = resp ret = cls._create_pool(m_driver, pool) - neutron.create_lbaas_pool.assert_called_once_with(req) + lbaas.create_lbaas_pool.assert_called_once_with(req) for attr in pool.obj_fields: self.assertEqual(getattr(pool, attr), getattr(ret, attr)) self.assertEqual(pool_id, ret.id) def test_create_pool_conflict(self): - neutron = self.useFixture(k_fix.MockNeutronClient()).client + lbaas = self.useFixture(k_fix.MockLBaaSClient()).client cls = d_lbaasv2.LBaaSv2Driver m_driver = mock.Mock(spec=d_lbaasv2.LBaaSv2Driver) lb_algorithm = 'ROUND_ROBIN' @@ -399,17 +394,16 @@ class TestLBaaSv2Driver(test_base.TestCase): req = {'pool': { 'name': pool.name, 'project_id': pool.project_id, - 'tenant_id': pool.project_id, 'listener_id': pool.listener_id, 'loadbalancer_id': pool.loadbalancer_id, 'protocol': pool.protocol, 'lb_algorithm': lb_algorithm}} - neutron.create_lbaas_pool.side_effect = n_exc.StateInvalidClient + lbaas.create_lbaas_pool.side_effect = n_exc.StateInvalidClient self.assertRaises(n_exc.StateInvalidClient, cls._create_pool, m_driver, pool) - neutron.create_lbaas_pool.assert_called_once_with(req) - m_driver._cleanup_bogus_pool.assert_called_once_with(neutron, pool, + lbaas.create_lbaas_pool.assert_called_once_with(req) + m_driver._cleanup_bogus_pool.assert_called_once_with(lbaas, pool, lb_algorithm) def test_cleanup_bogus_pool(self): @@ -417,7 +411,7 @@ class TestLBaaSv2Driver(test_base.TestCase): self.skipTest("not implemented") def test_find_pool(self): - neutron = self.useFixture(k_fix.MockNeutronClient()).client + lbaas = self.useFixture(k_fix.MockLBaaSClient()).client cls = d_lbaasv2.LBaaSv2Driver m_driver = mock.Mock(spec=d_lbaasv2.LBaaSv2Driver) pool = obj_lbaas.LBaaSPool( @@ -427,13 +421,12 @@ class TestLBaaSv2Driver(test_base.TestCase): pool_id = 'D4F35594-27EB-4F4C-930C-31DD40F53B77' resp = {'pools': [{'id': pool_id, 'listeners': [{'id': pool.listener_id}]}]} - neutron.list_lbaas_pools.return_value = resp + lbaas.list_lbaas_pools.return_value = resp ret = cls._find_pool(m_driver, pool) - neutron.list_lbaas_pools.assert_called_once_with( + lbaas.list_lbaas_pools.assert_called_once_with( name=pool.name, project_id=pool.project_id, - tenant_id=pool.project_id, loadbalancer_id=pool.loadbalancer_id, protocol=pool.protocol) for attr in pool.obj_fields: @@ -442,7 +435,7 @@ class TestLBaaSv2Driver(test_base.TestCase): self.assertEqual(pool_id, ret.id) def test_find_pool_not_found(self): - neutron = self.useFixture(k_fix.MockNeutronClient()).client + lbaas = self.useFixture(k_fix.MockLBaaSClient()).client cls = d_lbaasv2.LBaaSv2Driver m_driver = mock.Mock(spec=d_lbaasv2.LBaaSv2Driver) pool = obj_lbaas.LBaaSPool( @@ -450,19 +443,18 @@ class TestLBaaSv2Driver(test_base.TestCase): listener_id='A57B7771-6050-4CA8-A63C-443493EC98AB', loadbalancer_id='00EE9E11-91C2-41CF-8FD4-7970579E5C4C') resp = {'pools': []} - neutron.list_lbaas_pools.return_value = resp + lbaas.list_lbaas_pools.return_value = resp ret = cls._find_pool(m_driver, pool) - neutron.list_lbaas_pools.assert_called_once_with( + lbaas.list_lbaas_pools.assert_called_once_with( name=pool.name, project_id=pool.project_id, - tenant_id=pool.project_id, loadbalancer_id=pool.loadbalancer_id, protocol=pool.protocol) self.assertIsNone(ret) def test_create_member(self): - neutron = self.useFixture(k_fix.MockNeutronClient()).client + lbaas = self.useFixture(k_fix.MockLBaaSClient()).client cls = d_lbaasv2.LBaaSv2Driver m_driver = mock.Mock(spec=d_lbaasv2.LBaaSv2Driver) member = obj_lbaas.LBaaSMember( @@ -473,15 +465,14 @@ class TestLBaaSv2Driver(test_base.TestCase): req = {'member': { 'name': member.name, 'project_id': member.project_id, - 'tenant_id': member.project_id, 'subnet_id': member.subnet_id, 'address': str(member.ip), 'protocol_port': member.port}} resp = {'member': {'id': member_id}} - neutron.create_lbaas_member.return_value = resp + lbaas.create_lbaas_member.return_value = resp ret = cls._create_member(m_driver, member) - neutron.create_lbaas_member.assert_called_once_with( + lbaas.create_lbaas_member.assert_called_once_with( member.pool_id, req) for attr in member.obj_fields: self.assertEqual(getattr(member, attr), @@ -489,7 +480,7 @@ class TestLBaaSv2Driver(test_base.TestCase): self.assertEqual(member_id, ret.id) def test_find_member(self): - neutron = self.useFixture(k_fix.MockNeutronClient()).client + lbaas = self.useFixture(k_fix.MockLBaaSClient()).client cls = d_lbaasv2.LBaaSv2Driver m_driver = mock.Mock(spec=d_lbaasv2.LBaaSv2Driver) member = obj_lbaas.LBaaSMember( @@ -498,14 +489,13 @@ class TestLBaaSv2Driver(test_base.TestCase): pool_id='D4F35594-27EB-4F4C-930C-31DD40F53B77') member_id = '3A70CEC0-392D-4BC1-A27C-06E63A0FD54F' resp = {'members': [{'id': member_id}]} - neutron.list_lbaas_members.return_value = resp + lbaas.list_lbaas_members.return_value = resp ret = cls._find_member(m_driver, member) - neutron.list_lbaas_members.assert_called_once_with( + lbaas.list_lbaas_members.assert_called_once_with( member.pool_id, name=member.name, project_id=member.project_id, - tenant_id=member.project_id, subnet_id=member.subnet_id, address=member.ip, protocol_port=member.port) @@ -515,7 +505,7 @@ class TestLBaaSv2Driver(test_base.TestCase): self.assertEqual(member_id, ret.id) def test_find_member_not_found(self): - neutron = self.useFixture(k_fix.MockNeutronClient()).client + lbaas = self.useFixture(k_fix.MockLBaaSClient()).client cls = d_lbaasv2.LBaaSv2Driver m_driver = mock.Mock(spec=d_lbaasv2.LBaaSv2Driver) member = obj_lbaas.LBaaSMember( @@ -523,14 +513,13 @@ class TestLBaaSv2Driver(test_base.TestCase): port=1234, subnet_id='D3FA400A-F543-4B91-9CD3-047AF0CE42D1', pool_id='D4F35594-27EB-4F4C-930C-31DD40F53B77') resp = {'members': []} - neutron.list_lbaas_members.return_value = resp + lbaas.list_lbaas_members.return_value = resp ret = cls._find_member(m_driver, member) - neutron.list_lbaas_members.assert_called_once_with( + lbaas.list_lbaas_members.assert_called_once_with( member.pool_id, name=member.name, project_id=member.project_id, - tenant_id=member.project_id, subnet_id=member.subnet_id, address=member.ip, protocol_port=member.port) @@ -670,7 +659,7 @@ class TestLBaaSv2Driver(test_base.TestCase): self.assertEqual(call_count, m_delete.call_count) def test_wait_for_provisioning(self): - neutron = self.useFixture(k_fix.MockNeutronClient()).client + lbaas = self.useFixture(k_fix.MockLBaaSClient()).client cls = d_lbaasv2.LBaaSv2Driver m_driver = mock.Mock(spec=d_lbaasv2.LBaaSv2Driver) loadbalancer = mock.Mock() @@ -678,14 +667,14 @@ class TestLBaaSv2Driver(test_base.TestCase): timer = [mock.sentinel.t0, mock.sentinel.t1] m_driver._provisioning_timer.return_value = timer resp = {'loadbalancer': {'provisioning_status': 'ACTIVE'}} - neutron.show_loadbalancer.return_value = resp + lbaas.show_loadbalancer.return_value = resp cls._wait_for_provisioning(m_driver, loadbalancer, timeout) - neutron.show_loadbalancer.assert_called_once_with(loadbalancer.id) + lbaas.show_loadbalancer.assert_called_once_with(loadbalancer.id) def test_wait_for_provisioning_not_ready(self): - neutron = self.useFixture(k_fix.MockNeutronClient()).client + lbaas = self.useFixture(k_fix.MockLBaaSClient()).client cls = d_lbaasv2.LBaaSv2Driver m_driver = mock.Mock(spec=d_lbaasv2.LBaaSv2Driver) loadbalancer = mock.Mock() @@ -693,12 +682,12 @@ class TestLBaaSv2Driver(test_base.TestCase): timer = [mock.sentinel.t0, mock.sentinel.t1] m_driver._provisioning_timer.return_value = timer resp = {'loadbalancer': {'provisioning_status': 'NOT_ACTIVE'}} - neutron.show_loadbalancer.return_value = resp + lbaas.show_loadbalancer.return_value = resp self.assertRaises(k_exc.ResourceNotReady, cls._wait_for_provisioning, m_driver, loadbalancer, timeout) - self.assertEqual(len(timer), neutron.show_loadbalancer.call_count) + self.assertEqual(len(timer), lbaas.show_loadbalancer.call_count) def test_provisioning_timer(self): # REVISIT(ivc): add test if _provisioning_timer is to stay diff --git a/kuryr_kubernetes/tests/unit/kuryr_fixtures.py b/kuryr_kubernetes/tests/unit/kuryr_fixtures.py index 6cf57e80a..c9a40c2da 100644 --- a/kuryr_kubernetes/tests/unit/kuryr_fixtures.py +++ b/kuryr_kubernetes/tests/unit/kuryr_fixtures.py @@ -33,3 +33,11 @@ class MockNeutronClient(fixtures.Fixture): self.useFixture(fixtures.MockPatch( 'kuryr_kubernetes.clients.get_neutron_client', lambda: self.client)) + + +class MockLBaaSClient(fixtures.Fixture): + def _setUp(self): + self.client = mock.Mock() + self.useFixture(fixtures.MockPatch( + 'kuryr_kubernetes.clients.get_loadbalancer_client', + lambda: self.client)) diff --git a/kuryr_kubernetes/tests/unit/test_clients.py b/kuryr_kubernetes/tests/unit/test_clients.py index 5dfaab515..f3e89d620 100644 --- a/kuryr_kubernetes/tests/unit/test_clients.py +++ b/kuryr_kubernetes/tests/unit/test_clients.py @@ -24,18 +24,57 @@ class TestK8sClient(test_base.TestCase): @mock.patch('kuryr_kubernetes.config.CONF') @mock.patch('kuryr_kubernetes.k8s_client.K8sClient') @mock.patch('kuryr.lib.utils.get_neutron_client') - def test_setup_clients(self, m_neutron, m_k8s, m_cfg): + def test_setup_clients_lbaasv2(self, m_neutron, m_k8s, m_cfg): k8s_api_root = 'http://127.0.0.1:1234' - neutron_dummy = object() + neutron_mock = mock.Mock() k8s_dummy = object() + neutron_mock.list_extensions.return_value = { + 'extensions': [ + {'alias': 'lbaasv2', + 'description': 'Provides Load Balancing', + 'links': [], + 'name': 'Load Balancing v2', + 'updated': '2017-11-28T09:00:00-00:00'}]} + m_cfg.kubernetes.api_root = k8s_api_root - m_neutron.return_value = neutron_dummy + m_neutron.return_value = neutron_mock m_k8s.return_value = k8s_dummy clients.setup_clients() m_k8s.assert_called_with(k8s_api_root) self.assertIs(k8s_dummy, clients.get_kubernetes_client()) - self.assertIs(neutron_dummy, clients.get_neutron_client()) + self.assertIs(neutron_mock, clients.get_neutron_client()) + self.assertIs(neutron_mock, clients.get_loadbalancer_client()) + + @mock.patch('neutronclient.client.construct_http_client') + @mock.patch('kuryr.lib.utils.get_auth_plugin') + @mock.patch('kuryr_kubernetes.config.CONF') + @mock.patch('kuryr_kubernetes.k8s_client.K8sClient') + @mock.patch('kuryr.lib.utils.get_neutron_client') + def test_setup_clients_octavia(self, m_neutron, m_k8s, m_cfg, + m_auth_plugin, m_construct_http_client): + k8s_api_root = 'http://127.0.0.1:1234' + + neutron_mock = mock.Mock() + k8s_dummy = object() + + neutron_mock.list_extensions.return_value = { + 'extensions': []} + + octavia_httpclient = mock.sentinel.octavia_httpclient + m_construct_http_client.return_value = octavia_httpclient + m_auth_plugin.return_value = mock.sentinel.auth_plugin + m_cfg.kubernetes.api_root = k8s_api_root + m_neutron.return_value = neutron_mock + m_k8s.return_value = k8s_dummy + + clients.setup_clients() + + m_k8s.assert_called_with(k8s_api_root) + self.assertIs(k8s_dummy, clients.get_kubernetes_client()) + self.assertIs(neutron_mock, clients.get_neutron_client()) + self.assertIs(octavia_httpclient, + clients.get_loadbalancer_client().httpclient) diff --git a/playbooks/tempest-kuryr-kubernetes-base/run.yaml b/playbooks/tempest-kuryr-kubernetes-base/run.yaml index 484a17a88..1fa01642c 100644 --- a/playbooks/tempest-kuryr-kubernetes-base/run.yaml +++ b/playbooks/tempest-kuryr-kubernetes-base/run.yaml @@ -75,11 +75,12 @@ fi # Kuryr watcher enable_service kuryr-kubernetes - # LBaaS service - ENABLED_SERVICES+=,q-lbaasv2 - enable_plugin neutron-lbaas git://git.openstack.org/openstack/neutron-lbaas if [ "{{ loadbalancer }}" == "lbaasv2" ]; then + # LBaaS service + ENABLED_SERVICES+=,q-lbaasv2 + + enable_plugin neutron-lbaas git://git.openstack.org/openstack/neutron-lbaas # Haproxy agent NEUTRON_LBAAS_SERVICE_PROVIDERV2=LOADBALANCERV2:Haproxy:neutron_lbaas.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default elif [ "{{ loadbalancer }}" == "octavia" ]; then @@ -87,6 +88,7 @@ enable_plugin octavia https://git.openstack.org/openstack/octavia enable_plugin barbican https://git.openstack.org/openstack/barbican ENABLED_SERVICES+=,octavia,o-api,o-cw,o-hk,o-hm + LIBS_FROM_GIT+=,python-octaviaclient fi if [ "{{ kuryr_daemon }}" == "True" ]; then