From c550649f27d091b4fb80bb6ff222429aaccf1c87 Mon Sep 17 00:00:00 2001 From: micafer Date: Thu, 23 Apr 2020 11:40:14 +0200 Subject: [PATCH 1/3] Add support to #1010 --- IM/connectors/OpenStack.py | 5 ++++- doc/source/client.rst | 3 +++ test/unit/connectors/OpenStack.py | 3 ++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/IM/connectors/OpenStack.py b/IM/connectors/OpenStack.py index 3f8aca0fb..a43cc72cb 100644 --- a/IM/connectors/OpenStack.py +++ b/IM/connectors/OpenStack.py @@ -117,7 +117,8 @@ def get_driver(self, auth_data): "image_url": None, "volume_url": None, "api_version": "2.0", - "domain": None} + "domain": None, + "tenant_domain_id": None} if 'username' in auth and 'password' in auth and 'tenant' in auth: username = auth['username'] @@ -161,6 +162,8 @@ def get_driver(self, auth_data): key = 'ex_force_%s' % key elif key == 'domain': key = 'ex_domain_name' + elif key == 'tenant_domain_id': + key = 'ex_tenant_domain_id' kwargs[key] = value # Workaround to OTC to enable to set service_name as None diff --git a/doc/source/client.rst b/doc/source/client.rst index f1c44b1dd..b57e5b64f 100644 --- a/doc/source/client.rst +++ b/doc/source/client.rst @@ -292,6 +292,9 @@ OpenStack has a set of additional fields to access a cloud site: flow involves hitting the auth service (Keystone) with the provided username and password and requesting an authentication token. +* ``tenant_domain_id`` tenant domain id to set to the identity service. Some cloud providers require the tenant + domain id to be provided at authentication time. Others will use a default tenant domain id if none is provided. + OpenID Connect OpenStack sites ++++++++++++++++++++++++++++++ diff --git a/test/unit/connectors/OpenStack.py b/test/unit/connectors/OpenStack.py index 001590764..e3b130f0e 100755 --- a/test/unit/connectors/OpenStack.py +++ b/test/unit/connectors/OpenStack.py @@ -786,7 +786,7 @@ def test_70_create_snapshot(self, get_driver): @patch('libcloud.compute.drivers.openstack.OpenStackNodeDriver') def test_80_delete_image(self, get_driver): - auth = Authentication([{'id': 'ost', 'type': 'OpenStack', 'username': 'user', + auth = Authentication([{'id': 'ost', 'type': 'OpenStack', 'username': 'user', 'tenant_domain_id': "tdi", 'password': 'pass', 'tenant': 'tenant', 'host': 'https://server.com:5000'}]) ost_cloud = self.get_ost_cloud() @@ -802,6 +802,7 @@ def test_80_delete_image(self, get_driver): self.assertTrue(success, msg="ERROR: deleting image. %s" % msg) self.assertEqual(driver.delete_image.call_args_list, [call(image)]) + self.assertEqual(get_driver.call_args_list[0][1]["ex_tenant_domain_id"], "tdi") self.assertNotIn("ERROR", self.log.getvalue(), msg="ERROR found in log: %s" % self.log.getvalue()) def test_get_networks(self): From d74268dd09e4d2f4184781bc5555f082959886df Mon Sep 17 00:00:00 2001 From: micafer Date: Tue, 28 Apr 2020 11:26:08 +0200 Subject: [PATCH 2/3] Use liblcloud from pip --- docker-py3/Dockerfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/docker-py3/Dockerfile b/docker-py3/Dockerfile index 9b30f5ecf..0280e13f5 100644 --- a/docker-py3/Dockerfile +++ b/docker-py3/Dockerfile @@ -14,8 +14,6 @@ RUN apt-get update && apt-get install --no-install-recommends -y git python3-pip pip3 install pip setuptools --upgrade && \ /usr/local/bin/pip3 install msrest msrestazure azure-common azure-mgmt-storage azure-mgmt-compute azure-mgmt-network azure-mgmt-resource azure-mgmt-dns azure-storage && \ /usr/local/bin/pip3 install pyOpenSSL cheroot xmltodict pymongo ansible==2.7.16 && \ - # Install github version until the v 3.0 is released - cd /tmp && git clone https://github.com/apache/libcloud && /usr/local/bin/pip3 install /tmp/libcloud && \ /usr/local/bin/pip3 install IM==1.9.2 && \ /usr/local/bin/pip3 uninstall pip -y && \ apt-get purge -y git python3-pip && \ From 333a15c7e06ac6b2b235e342670dff0ac99eeff4 Mon Sep 17 00:00:00 2001 From: micafer Date: Fri, 26 Jun 2020 13:07:19 +0200 Subject: [PATCH 3/3] OST detach from vols and SGs before node deletion --- IM/connectors/OpenStack.py | 27 +++++++++++++++++++++++++-- test/unit/connectors/OpenStack.py | 9 +++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) mode change 100755 => 100644 test/unit/connectors/OpenStack.py diff --git a/IM/connectors/OpenStack.py b/IM/connectors/OpenStack.py index a43cc72cb..657010a83 100644 --- a/IM/connectors/OpenStack.py +++ b/IM/connectors/OpenStack.py @@ -1304,6 +1304,21 @@ def finalize(self, vm, last, auth_data): success = [] msgs = [] if node: + # First try to detach the volumes and the SGs + for vol_id in vm.volumes: + try: + volume = node.driver.ex_get_volume(vol_id) + node.driver.detach_volume(volume) + except Exception as ex: + self.log_exception("Error dettaching volume %s." % vol_id) + + try: + for sg_name in self._get_security_names(vm.inf): + security_group = OpenStackSecurityGroup(None, None, sg_name, "", node.driver) + node.driver.ex_remove_security_group_from_node(security_group, node) + except Exception as ex: + self.log_exception("Error dettaching volume %s." % vol_id) + res = node.destroy() success.append(res) @@ -1361,9 +1376,9 @@ def finalize(self, vm, last, auth_data): return (all(success), "\n ".join(msgs)) - def delete_security_groups(self, driver, inf, timeout=180, delay=10): + def _get_security_names(self, inf): """ - Delete the SG of this inf + Get the list of SGs for this infra """ sg_names = ["im-%s" % inf.id] for net in inf.radl.networks: @@ -1372,6 +1387,14 @@ def delete_security_groups(self, driver, inf, timeout=180, delay=10): sg_name = "im-%s-%s" % (inf.id, net.id) sg_names.append(sg_name) + return sg_names + + def delete_security_groups(self, driver, inf, timeout=180, delay=10): + """ + Delete the SG of this inf + """ + sg_names = self._get_security_names(inf) + msg = "" deleted = True for sg_name in sg_names: diff --git a/test/unit/connectors/OpenStack.py b/test/unit/connectors/OpenStack.py old mode 100755 new mode 100644 index e3b130f0e..8874be310 --- a/test/unit/connectors/OpenStack.py +++ b/test/unit/connectors/OpenStack.py @@ -736,6 +736,11 @@ def test_60_finalize(self, sleep, get_driver): driver.ex_list_routers.return_value = [router] driver.ex_add_router_subnet.return_value = True + volume = MagicMock() + driver.ex_get_volume.return_value = volume + driver.detach_volume.return_value = True + driver.ex_remove_security_group_from_node.return_value = True + vm.volumes = ['volid'] success, _ = ost_cloud.finalize(vm, True, auth) @@ -743,6 +748,10 @@ def test_60_finalize(self, sleep, get_driver): self.assertNotIn("ERROR", self.log.getvalue(), msg="ERROR found in log: %s" % self.log.getvalue()) self.assertEqual(node.destroy.call_args_list, [call()]) + self.assertEqual(driver.detach_volume.call_args_list[0][0][0], volume) + self.assertEqual(driver.ex_remove_security_group_from_node.call_args_list[0][0][0].name, "im-infid") + self.assertEqual(driver.ex_remove_security_group_from_node.call_args_list[1][0][0].name, "im-infid-public") + self.assertEqual(driver.ex_remove_security_group_from_node.call_args_list[2][0][0].name, "im-infid-private") self.assertEqual(driver.ex_del_router_subnet.call_args_list[0][0][0], router) self.assertEqual(driver.ex_del_router_subnet.call_args_list[0][0][1].id, "subnet1") self.assertEqual(driver.ex_delete_network.call_args_list[0][0][0], net1)