From 2fc6dc189c29d67edda93feb6f29e2d0bbf989b4 Mon Sep 17 00:00:00 2001 From: micafer Date: Tue, 20 Apr 2021 11:40:37 +0200 Subject: [PATCH 1/5] Implements #1155 --- IM/AppDB.py | 21 ++++ IM/connectors/EGI.py | 126 +++++++++++++++++++ IM/connectors/__init__.py | 4 +- test/unit/connectors/EGI.py | 237 ++++++++++++++++++++++++++++++++++++ 4 files changed, 386 insertions(+), 2 deletions(-) create mode 100644 IM/connectors/EGI.py create mode 100644 test/unit/connectors/EGI.py diff --git a/IM/AppDB.py b/IM/AppDB.py index 539c7e986..a9113b466 100644 --- a/IM/AppDB.py +++ b/IM/AppDB.py @@ -161,3 +161,24 @@ def get_image_id_from_uri(site_id, image_mp_uri): return image_basename return None + + @staticmethod + def get_project_ids(site_id): + projects = {} + # Until it is on the prod instance use the Devel one + + data = AppDB.appdb_call('/rest/1.0/va_providers/%s' % site_id) + if (data and 'virtualization:provider' in data and data['virtualization:provider'] and + 'provider:shares' in data['virtualization:provider'] and + data['virtualization:provider']['provider:shares'] and + 'vo:vo' in data['virtualization:provider']['provider:shares'] and + data['virtualization:provider']['provider:shares']['vo:vo']): + if isinstance(data['virtualization:provider']['provider:shares']['vo:vo'], list): + shares = data['virtualization:provider']['provider:shares']['vo:vo'] + else: + shares = [data['virtualization:provider']['provider:shares']['vo:vo']] + + for vo in shares: + projects[vo["#text"]] = vo['@projectid'] + + return projects \ No newline at end of file diff --git a/IM/connectors/EGI.py b/IM/connectors/EGI.py new file mode 100644 index 000000000..3185d4bba --- /dev/null +++ b/IM/connectors/EGI.py @@ -0,0 +1,126 @@ +# IM - Infrastructure Manager +# Copyright (C) 2011 - GRyCAP - Universitat Politecnica de Valencia +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +from IM.connectors.OpenStack import OpenStackCloudConnector +from IM.AppDB import AppDB +from IM.auth import Authentication +from IM.CloudInfo import CloudInfo +try: + from urlparse import urlparse +except ImportError: + from urllib.parse import urlparse + +class EGICloudConnector(OpenStackCloudConnector): + """ + Cloud Launcher to EGI using LibCloud + """ + + type = "EGI" + """str with the name of the provider.""" + + def get_driver(self, auth_data): + """ + Get the driver from the auth data + + Arguments: + - auth(Authentication): parsed authentication tokens. + + Returns: a :py:class:`libcloud.compute.base.NodeDriver` or None in case of error + """ + auths = auth_data.getAuthInfo(self.type, self.cloud.server) + if not auths: + raise Exception("No auth data has been specified to EGI.") + else: + auth = auths[0] + + if 'host' in auth and 'vo' in auth and 'token' in auth: + ost_auth = {'id': auth['id'], 'type': 'OpenStack', 'username': 'egi.eu', 'tenant': 'openid', + 'password': auth['token'], 'auth_version': '3.x_oidc_access_token'} + site_id = AppDB.get_site_id(auth["host"]) + site_url = AppDB.get_site_url(site_id) + ost_auth['host'] = site_url + projects = AppDB.get_project_ids(site_id) + # If the VO does not appear in the project IDs + if auth['vo'] in projects: + ost_auth['domain'] = projects[auth['vo']] + else: + # let's use the VO name directly + ost_auth['domain'] = auth['vo'] + + new_auth = Authentication([ost_auth]) + + orig_cloud = self.cloud + self.cloud = CloudInfo.get_cloud_list(new_auth)[0] + self.type = OpenStackCloudConnector.type + driver = OpenStackCloudConnector.get_driver(self, new_auth) + self.type = EGICloudConnector.type + self.cloud = orig_cloud + return driver + else: + self.log_error("No correct auth data has been specified to EGI: host, vo, and token") + raise Exception("No correct auth data has been specified to EG: host, vo, and token") + + def concrete_system(self, radl_system, str_url, auth_data): + url = urlparse(str_url) + protocol = url[0] + src_host = url[1].split(':')[0] + + if protocol == "appdb": + site_url, image_id, msg = AppDB.get_image_data(str_url, "openstack") + if not image_id or not site_url: + self.log_error(msg) + return None + + protocol = "ost" + url = urlparse(site_url) + src_host = url[1].split(':')[0] + + if protocol == "ost" and self.cloud.server and not self.cloud.protocol: + site_url = AppDB.get_site_url(self.cloud.server) + site_host = urlparse(str_url)[1].split(':')[0] + + if protocol == "ost" and site_host == src_host: + driver = self.get_driver(auth_data) + + res_system = radl_system.clone() + instance_type = self.get_instance_type(driver, res_system) + self.update_system_info_from_instance(res_system, instance_type) + + username = res_system.getValue('disk.0.os.credentials.username') + if not username: + res_system.setValue('disk.0.os.credentials.username', self.DEFAULT_USER) + + return res_system + else: + return None + else: + return None + + @staticmethod + def _get_tenant_id(driver, auth): + """ + Workaround function to get tenant id from tenant name + """ + if 'auth_version' in auth and auth['auth_version'] == '3.x_oidc_access_token': + return auth['domain'] + else: + if 'tenant_id' in auth: + return auth['tenant_id'] + else: + return auth['tenant'] + + return None diff --git a/IM/connectors/__init__.py b/IM/connectors/__init__.py index 38a749b17..321979449 100644 --- a/IM/connectors/__init__.py +++ b/IM/connectors/__init__.py @@ -15,5 +15,5 @@ # along with this program. If not, see . -__all__ = ['CloudConnector', 'EC2', 'OCCI', 'OpenNebula', 'OpenStack', 'AzureClassic', 'Docker', 'GCE', - 'FogBow', 'Azure', 'DeployedNode', 'Kubernetes', 'Dummy', 'vSphere', 'CloudStack', 'Linode', 'Orange'] +__all__ = ['CloudConnector', 'EC2', 'OCCI', 'OpenNebula', 'OpenStack', 'AzureClassic', 'Docker', 'GCE', 'FogBow', + 'Azure', 'DeployedNode', 'Kubernetes', 'Dummy', 'vSphere', 'CloudStack', 'Linode', 'Orange', 'EGI'] diff --git a/test/unit/connectors/EGI.py b/test/unit/connectors/EGI.py new file mode 100644 index 000000000..a76ea5b4a --- /dev/null +++ b/test/unit/connectors/EGI.py @@ -0,0 +1,237 @@ +#! /usr/bin/env python +# +# IM - Infrastructure Manager +# Copyright (C) 2011 - GRyCAP - Universitat Politecnica de Valencia +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import sys +import unittest + +sys.path.append(".") +sys.path.append("..") +from .CloudConn import TestCloudConnectorBase +from IM.CloudInfo import CloudInfo +from IM.auth import Authentication +from radl import radl_parse +from IM.VirtualMachine import VirtualMachine +from IM.InfrastructureInfo import InfrastructureInfo +from IM.connectors.EGI import EGICloudConnector +from mock import patch, MagicMock, call + + +class TestEGIConnector(TestCloudConnectorBase): + """ + Class to test the IM connectors + """ + + def setUp(self): + self.error_in_create = True + TestCloudConnectorBase.setUp(self) + + @staticmethod + def get_egi_cloud(): + cloud_info = CloudInfo() + cloud_info.type = "EGI" + cloud_info.server = "CESGA" + inf = MagicMock() + inf.id = "1" + one_cloud = EGICloudConnector(cloud_info, inf) + return one_cloud + + @patch('libcloud.compute.drivers.openstack.OpenStackNodeDriver') + @patch('IM.connectors.EGI.AppDB') + def test_10_concrete(self, appdb, get_driver): + radl_data = """ + network net () + system test ( + cpu.arch='x86_64' and + cpu.count>=1 and + memory.size>=512m and + net_interface.0.connection = 'net' and + net_interface.0.dns_name = 'test' and + disk.0.os.name = 'linux' and + disk.0.image.url = 'ost://site.com/image-id' and + disk.0.os.credentials.username = 'user' + )""" + radl = radl_parse.parse_radl(radl_data) + radl_system = radl.systems[0] + + auth = Authentication([{'id': 'egi1', 'type': 'EGI', 'host': 'CESGA', + 'vo': 'vo.access.egi.eu', 'token': 'access_token'}]) + egi_cloud = self.get_egi_cloud() + + driver = MagicMock() + get_driver.return_value = driver + + appdb.get_site_id.return_value = "site1" + appdb.get_site_url.return_value = "https://site.com:5000/v3" + appdb.get_project_ids.return_value = {"vo.access.egi.eu": "projectid"} + + node_size = MagicMock() + node_size.id = '1' + node_size.ram = 512 + node_size.price = 1 + node_size.disk = 1 + node_size.vcpus = 1 + node_size.name = "g.small" + node_size.extra = {'pci_passthrough:alias': 'GPU:2,FPGA:1'} + node_size2 = MagicMock() + node_size.id = '2' + node_size2.ram = 512 + node_size2.price = 1 + node_size2.disk = 1 + node_size2.vcpus = 1 + node_size2.name = "small" + node_size2.extra = {} + driver.list_sizes.return_value = [node_size, node_size2] + driver.ex_get_size_extra_specs.return_value = {} + + concrete = egi_cloud.concreteSystem(radl_system, auth) + self.assertEqual(len(concrete), 1) + self.assertEqual(concrete[0].getValue("instance_type"), "small") + self.assertNotIn("ERROR", self.log.getvalue(), msg="ERROR found in log: %s" % self.log.getvalue()) + + def create_node(self, **kwargs): + """ + Create VMs returning error only first time + """ + if self.error_in_create: + self.error_in_create = False + raise Exception("Error creating VM") + else: + node = MagicMock() + node.id = "ost1" + node.name = "ost1name" + return node + + @patch('libcloud.compute.drivers.openstack.OpenStackNodeDriver') + @patch('IM.InfrastructureList.InfrastructureList.save_data') + @patch('IM.AppDB.AppDB.get_image_data') + @patch('IM.connectors.EGI.AppDB') + def test_20_launch(self, appdb, get_image_data, save_data, get_driver): + radl_data = """ + network net1 (outbound = 'yes' and provider_id = 'public' and + outports = '8080,9000:9100' and sg_name= 'test') + network net2 (dnsserver='1.1.1.1' and create = 'yes') + system test ( + cpu.arch='x86_64' and + cpu.count=1 and + memory.size=512m and + instance_tags='key=value,key1=value2' and + net_interface.1.connection = 'net1' and + net_interface.0.connection = 'net2' and + disk.0.os.name = 'linux' and + disk.0.image.url = 'ost://server.com/ami-id' and + disk.0.os.credentials.username = 'user' and + disk.1.size=1GB and + disk.1.device='hdb' and + disk.2.image.url = 'ost://server.com/vol-id' and + disk.2.device='hdc' + )""" + radl = radl_parse.parse_radl(radl_data) + radl.check() + + auth = Authentication([{'id': 'egi1', 'type': 'EGI', 'host': 'CESGA', + 'vo': 'vo.access.egi.eu', 'token': 'access_token'}, + {'type': 'InfrastructureManager', 'username': 'user', + 'password': 'pass'}]) + egi_cloud = self.get_egi_cloud() + + driver = MagicMock() + get_driver.return_value = driver + + appdb.get_site_id.return_value = "site1" + appdb.get_site_url.return_value = "https://site.com:5000/v3" + appdb.get_project_ids.return_value = {"vo.access.egi.eu": "projectid"} + + node_size = MagicMock() + node_size.ram = 512 + node_size.price = 1 + node_size.disk = 1 + node_size.vcpus = 1 + node_size.name = "small" + driver.list_sizes.return_value = [node_size] + + net1 = MagicMock() + net1.name = "public" + net1.id = "net1id" + net1.extra = {'router:external': True} + net1.cidr = None + net2 = MagicMock() + net2.name = "private" + net2.id = "net2id" + net2.cidr = "10.0.0.0/24" + driver.ex_list_networks.return_value = [net2, net1] + + sg = MagicMock() + sg.name = "sg" + driver.ex_create_security_group.return_value = sg + driver.ex_list_security_groups.return_value = [] + driver.ex_create_security_group_rule.return_value = True + + driver.features = {'create_node': ['ssh_key']} + + driver.create_node.side_effect = self.create_node + + driver.ex_create_network.return_value = net2 + subnet1 = MagicMock() + driver.ex_create_subnet.return_value = subnet1 + + router = MagicMock() + router.id = "id" + router.name = "name" + router.extra = {'external_gateway_info': {'network_id': net1.id}} + driver.ex_list_routers.return_value = [router] + driver.ex_add_router_subnet.return_value = True + + image = MagicMock() + image.id = 'imageid' + driver.get_image.return_value = image + vol = MagicMock() + vol.id = 'volid' + driver.ex_get_volume.return_value = vol + + inf = InfrastructureInfo() + inf.radl = radl + inf.auth = auth + res = egi_cloud.launch_with_retry(inf, radl, radl, 1, auth, 2, 1) + success, _ = res[0] + self.assertTrue(success, msg="ERROR: launching a VM.") + self.assertEqual(driver.create_node.call_args_list[0][1]['networks'], [net1]) + mappings = [ + {'source_type': 'image', + 'uuid': 'imageid', + 'boot_index': 0, + 'delete_on_termination': False, + 'device_name': 'vda'}, + {'guest_format': 'ext3', + 'boot_index': 1, + 'volume_size': 1, + 'device_name': 'vdb', + 'source_type': 'blank', + 'destination_type': 'volume', + 'delete_on_termination': True}, + {'boot_index': 2, + 'delete_on_termination': False, + 'destination_type': 'volume', + 'device_name': 'vdc', + 'source_type': 'volume', + 'uuid': 'volid'} + ] + self.assertEqual(driver.create_node.call_args_list[0][1]['ex_blockdevicemappings'], mappings) + self.assertEqual(driver.ex_create_subnet.call_args_list[0][0][2], "10.0.1.0/24") + +if __name__ == '__main__': + unittest.main() From c944a307109788c5ab26fc33e6c7e86932189b4a Mon Sep 17 00:00:00 2001 From: micafer Date: Wed, 21 Apr 2021 17:10:26 +0200 Subject: [PATCH 2/5] Fix errors --- IM/AppDB.py | 6 ++- IM/connectors/EGI.py | 88 +++++++++++++++++++++---------------- IM/connectors/OpenStack.py | 12 ++++- test/unit/connectors/EGI.py | 1 + 4 files changed, 65 insertions(+), 42 deletions(-) diff --git a/IM/AppDB.py b/IM/AppDB.py index a9113b466..59cf30898 100644 --- a/IM/AppDB.py +++ b/IM/AppDB.py @@ -102,7 +102,7 @@ def get_image_id(site_id, image_name, vo_name): return None @staticmethod - def get_image_data(str_url, stype="occi"): + def get_image_data(str_url, stype="occi", vo=None): """ The url has this format: appdb://UPV-GRyCAP/egi.docker.ubuntu.16.04?fedcloud.egi.eu or this one appdb://UPV-GRyCAP/83d5e854-a128-5b1f-9457-d32e10a720a6:8135 @@ -130,6 +130,8 @@ def get_image_data(str_url, stype="occi"): return None, None, "No image ID returned from EGI AppDB for image: %s/%s." % (site_id, image_name) else: + if not vo_name: + vo_name = vo image_id = AppDB.get_image_id(site_id, image_name, vo_name) if not image_id: return None, None, "No image ID returned from EGI AppDB for image: %s/%s/%s." % (site_id, @@ -181,4 +183,4 @@ def get_project_ids(site_id): for vo in shares: projects[vo["#text"]] = vo['@projectid'] - return projects \ No newline at end of file + return projects diff --git a/IM/connectors/EGI.py b/IM/connectors/EGI.py index 3185d4bba..a86ec03b5 100644 --- a/IM/connectors/EGI.py +++ b/IM/connectors/EGI.py @@ -24,6 +24,7 @@ except ImportError: from urllib.parse import urlparse + class EGICloudConnector(OpenStackCloudConnector): """ Cloud Launcher to EGI using LibCloud @@ -32,6 +33,10 @@ class EGICloudConnector(OpenStackCloudConnector): type = "EGI" """str with the name of the provider.""" + def __init__(self, cloud_info, inf): + self.egi_auth = None + OpenStackCloudConnector.__init__(self, cloud_info, inf) + def get_driver(self, auth_data): """ Get the driver from the auth data @@ -47,53 +52,58 @@ def get_driver(self, auth_data): else: auth = auths[0] - if 'host' in auth and 'vo' in auth and 'token' in auth: - ost_auth = {'id': auth['id'], 'type': 'OpenStack', 'username': 'egi.eu', 'tenant': 'openid', - 'password': auth['token'], 'auth_version': '3.x_oidc_access_token'} - site_id = AppDB.get_site_id(auth["host"]) - site_url = AppDB.get_site_url(site_id) - ost_auth['host'] = site_url - projects = AppDB.get_project_ids(site_id) - # If the VO does not appear in the project IDs - if auth['vo'] in projects: - ost_auth['domain'] = projects[auth['vo']] - else: - # let's use the VO name directly - ost_auth['domain'] = auth['vo'] - - new_auth = Authentication([ost_auth]) - - orig_cloud = self.cloud - self.cloud = CloudInfo.get_cloud_list(new_auth)[0] - self.type = OpenStackCloudConnector.type - driver = OpenStackCloudConnector.get_driver(self, new_auth) - self.type = EGICloudConnector.type - self.cloud = orig_cloud - return driver + if self.driver and self.egi_auth.compare(auth_data, self.type, self.cloud.server): + return self.driver else: - self.log_error("No correct auth data has been specified to EGI: host, vo, and token") - raise Exception("No correct auth data has been specified to EG: host, vo, and token") + self.egi_auth = auth_data + + if 'host' in auth and 'vo' in auth and 'token' in auth: + ost_auth = {'id': auth['id'], 'type': 'OpenStack', 'username': 'egi.eu', 'tenant': 'openid', + 'password': auth['token'], 'auth_version': '3.x_oidc_access_token', 'vo': auth['vo']} + site_id = AppDB.get_site_id(auth["host"], stype="openstack") + site_url = AppDB.get_site_url(site_id) + if not site_url: + raise Exception("Invalid site name '%s'. Not found at AppDB." % auth['host']) + ost_auth['host'] = site_url + projects = AppDB.get_project_ids(site_id) + # If the VO does not appear in the project IDs + if auth['vo'] in projects: + ost_auth['domain'] = projects[auth['vo']] + else: + # let's use the VO name directly + ost_auth['domain'] = auth['vo'] + + if 'api_version' in auth: + ost_auth['api_version'] = auth['api_version'] + + new_auth = Authentication([ost_auth]) + + orig_cloud = self.cloud + self.cloud = CloudInfo.get_cloud_list(new_auth)[0] + self.type = OpenStackCloudConnector.type + driver = OpenStackCloudConnector.get_driver(self, new_auth) + self.type = EGICloudConnector.type + self.cloud = orig_cloud + + self.driver = driver + return driver + else: + self.log_error("No correct auth data has been specified to EGI: host, vo, and token") + raise Exception("No correct auth data has been specified to EG: host, vo, and token") def concrete_system(self, radl_system, str_url, auth_data): url = urlparse(str_url) protocol = url[0] src_host = url[1].split(':')[0] - if protocol == "appdb": - site_url, image_id, msg = AppDB.get_image_data(str_url, "openstack") - if not image_id or not site_url: - self.log_error(msg) - return None - - protocol = "ost" - url = urlparse(site_url) - src_host = url[1].split(':')[0] - - if protocol == "ost" and self.cloud.server and not self.cloud.protocol: - site_url = AppDB.get_site_url(self.cloud.server) - site_host = urlparse(str_url)[1].split(':')[0] + if protocol in ["ost", "appdb"] and self.cloud.server and not self.cloud.protocol: + site_host = "" + if protocol == "ost": + site_url = AppDB.get_site_url(self.cloud.server) + site_host = urlparse(site_url)[1].split(':')[0] - if protocol == "ost" and site_host == src_host: + if ((protocol == "ost" and site_host == src_host) or + (protocol == "appdb" and src_host == self.cloud.server)): driver = self.get_driver(auth_data) res_system = radl_system.clone() diff --git a/IM/connectors/OpenStack.py b/IM/connectors/OpenStack.py index 030c86b63..4d5fd13ee 100644 --- a/IM/connectors/OpenStack.py +++ b/IM/connectors/OpenStack.py @@ -1052,6 +1052,15 @@ def get_volumes(driver, image, radl): return res + def get_vo_name(self, auth_data): + """Get vo field from auth data if present""" + auths = auth_data.getAuthInfo(self.type, self.cloud.server) + if auths: + auth = auths[0] + if 'vo' in auth and auth['vo']: + return auth['vo'] + return None + def launch(self, inf, radl, requested_radl, num_vm, auth_data): driver = self.get_driver(auth_data) @@ -1059,7 +1068,8 @@ def launch(self, inf, radl, requested_radl, num_vm, auth_data): image_url = system.getValue("disk.0.image.url") if urlparse(image_url)[0] == "appdb": - _, image_id, msg = AppDB.get_image_data(image_url, "openstack") + vo = self.get_vo_name(auth_data) + _, image_id, msg = AppDB.get_image_data(image_url, "openstack", vo) if not image_id: self.log_error(msg) raise Exception("Error in appdb image: %s" % msg) diff --git a/test/unit/connectors/EGI.py b/test/unit/connectors/EGI.py index a76ea5b4a..8e6457aac 100644 --- a/test/unit/connectors/EGI.py +++ b/test/unit/connectors/EGI.py @@ -233,5 +233,6 @@ def test_20_launch(self, appdb, get_image_data, save_data, get_driver): self.assertEqual(driver.create_node.call_args_list[0][1]['ex_blockdevicemappings'], mappings) self.assertEqual(driver.ex_create_subnet.call_args_list[0][0][2], "10.0.1.0/24") + if __name__ == '__main__': unittest.main() From 396cd94e0ed8907f85133d5913d63fe60ab2f0e5 Mon Sep 17 00:00:00 2001 From: micafer Date: Wed, 21 Apr 2021 17:18:31 +0200 Subject: [PATCH 3/5] Add documentation --- doc/source/client.rst | 13 +++++++++++-- doc/source/manual.rst | 2 +- doc/source/radl.rst | 4 ++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/doc/source/client.rst b/doc/source/client.rst index 540b12a58..d1be1a969 100644 --- a/doc/source/client.rst +++ b/doc/source/client.rst @@ -204,7 +204,7 @@ The available keys are: * ``type`` indicates the service that refers the credential. The services supported are ``InfrastructureManager``, ``VMRC``, ``OpenNebula``, ``EC2``,, ``FogBow``, ``OpenStack``, ``OCCI``, ``LibCloud``, ``Docker``, ``GCE``, ``Azure``, ``AzureClassic``, - ``Kubernetes``, ``vSphere``, ``Linode`` and ``Orange``. + ``Kubernetes``, ``vSphere``, ``Linode``, ``Orange`` and ``EGI``. * ``username`` indicates the user name associated to the credential. In EC2 it refers to the *Access Key ID*. In GCE it refers to *Service Account’s Email Address*. @@ -220,6 +220,7 @@ The available keys are: This field is only used in the OpenStack and Orange plugins. * ``host`` indicates the address of the access point to the cloud provider. + In case of EGI connector it indicates the site name. This field is not used in IM, GCE, Azure, and EC2 credentials. * ``proxy`` indicates the content of the proxy file associated to the credential. @@ -247,7 +248,10 @@ The available keys are: plugin check the documentation of the Azure python SDK: `here `_ -* ``token`` indicates the OpenID token associated to the credential. This field is used in the OCCI plugin (from version 1.6.2). +* ``token`` indicates the OpenID token associated to the credential. This field is used in the EGI and OCCI plugins. + +* ``vo`` indicates the VO name associated to the credential. This field is used in the EGI plugin. + OpenStack additional fields ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -341,6 +345,9 @@ So the auth line will be like that:: id = ost; type = OpenStack; host = https://ostserver:5000; username = egi.eu; tenant = openid; password = egi_aai_token_value; auth_version = 3.x_oidc_access_token; domain = project_name +From IM version 1.10.2 the EGI connector is available and you can use this kind of auth line:: + + id = egi; type = EGI; host = CESGA; vo = vo.access.egi.eu; token = egi_aai_token_value Open Telekom Cloud ++++++++++++++++++ @@ -397,6 +404,8 @@ An example of the auth file:: id = linode; type = Linode; username = apikey # Orange Flexible Cloud auth data id = orange; type = Orange; username = usern; password = pass; domain = DOMAIN; region = region; tenant = tenant + # EGI auth data + id = egi; type = EGI; host = SITE_NAME; vo = vo_name; token = egi_aai_token_value IM Server does not store the credentials used in the creation of infrastructures. Then the user has to provide them in every call of diff --git a/doc/source/manual.rst b/doc/source/manual.rst index d49617f9e..4820d6f9e 100644 --- a/doc/source/manual.rst +++ b/doc/source/manual.rst @@ -77,7 +77,7 @@ Optional Packages In newer versions (9.0 and later) the functionality has been moved `the cheroot library`_ it can be installed using pip. * `apache-libcloud `_ 3.0 or later is used in the - LibCloud, OpenStack and GCE connectors. + LibCloud, OpenStack, EGI and GCE connectors. * `boto `_ 2.29.0 or later is used as interface to Amazon EC2. It is available as package named ``python-boto`` in Debian based distributions. It can also be downloaded from `boto GitHub repository `_. diff --git a/doc/source/radl.rst b/doc/source/radl.rst index 4595e0280..7f17a53f1 100644 --- a/doc/source/radl.rst +++ b/doc/source/radl.rst @@ -302,7 +302,7 @@ machine. The supported features are: * ``one://:/``, for OpenNebula; * ``one://:/``, for OpenNebula; - * ``ost://:/``, for OpenStack; + * ``ost://:/``, for OpenStack or EGI; * ``aws:///``, for Amazon Web Service; * ``aws:///``, for Amazon Web Service; * ``aws:///``, for Amazon Web Service; @@ -311,7 +311,7 @@ machine. The supported features are: * ``azr://///``, for Microsoft Azure; * ``azr://[snapshots|disk]//``, for Microsoft Azure; * ``/``, for FedCloud OCCI connector. - * ``appdb:///?``, for FedCloud OCCI or OpenStack connector using AppDB info (from vers. 1.6.0 and 1.8.6). + * ``appdb:///?``, for FedCloud OCCI, OpenStack or EGI connectors using AppDB info (from vers. 1.6.0 and 1.8.6). * ``docker://``, for Docker images. * ``fbw:///``, for FogBow images. * ``lin://linode/``, for Linode images. From f4679e5feb4b311609ff5bfbcf8b9a51192aa70f Mon Sep 17 00:00:00 2001 From: micafer Date: Thu, 22 Apr 2021 08:57:18 +0200 Subject: [PATCH 4/5] Improve docs --- doc/source/radl.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/source/radl.rst b/doc/source/radl.rst index 7f17a53f1..373a21432 100644 --- a/doc/source/radl.rst +++ b/doc/source/radl.rst @@ -311,7 +311,8 @@ machine. The supported features are: * ``azr://///``, for Microsoft Azure; * ``azr://[snapshots|disk]//``, for Microsoft Azure; * ``/``, for FedCloud OCCI connector. - * ``appdb:///?``, for FedCloud OCCI, OpenStack or EGI connectors using AppDB info (from vers. 1.6.0 and 1.8.6). + * ``appdb:///?``, for FedCloud OCCI, OpenStack or EGI connectors using AppDB info (from vers. 1.6.0, 1.8.6 and 1.10.2 respectively). + In case of EGI connector the ``vo_name`` is not required as it will be get from auth data. * ``docker://``, for Docker images. * ``fbw:///``, for FogBow images. * ``lin://linode/``, for Linode images. From f60843d64753a97b281c6cea0fd02c5faec0325e Mon Sep 17 00:00:00 2001 From: micafer Date: Thu, 22 Apr 2021 09:02:41 +0200 Subject: [PATCH 5/5] Remove unused code --- test/unit/connectors/EGI.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/unit/connectors/EGI.py b/test/unit/connectors/EGI.py index 8e6457aac..d7228e99d 100644 --- a/test/unit/connectors/EGI.py +++ b/test/unit/connectors/EGI.py @@ -25,10 +25,9 @@ from IM.CloudInfo import CloudInfo from IM.auth import Authentication from radl import radl_parse -from IM.VirtualMachine import VirtualMachine from IM.InfrastructureInfo import InfrastructureInfo from IM.connectors.EGI import EGICloudConnector -from mock import patch, MagicMock, call +from mock import patch, MagicMock class TestEGIConnector(TestCloudConnectorBase):