From 1181a3bb396ca783b841e5e58bbd60e0548ede17 Mon Sep 17 00:00:00 2001 From: Hashir Mohammed Date: Mon, 12 Dec 2016 04:00:52 -0500 Subject: [PATCH] Bug 129 RIFT-15122 * Added support for domain in Opnestack for KeyStone API v3 * Added two new YANG model object user-domain and project-domain * user-domain and project domain default to the value 'default' * Changed the Nova service name from computev21 to compute * Added test cases to verify the new feature and backward compatability Reviewers: TBD Rajesh, Ravu, Aniruddha Signed-off-by: Hashir Mohammed --- .../rift/rwcal/openstack/openstack_drv.py | 62 +++++++--- .../vala/rwcal_openstack/rwcal_openstack.py | 15 +-- rwcal/plugins/yang/rwcal.yang | 11 ++ rwcal/test/test_rwcal_openstack.py | 114 ++++++++++++++++-- 4 files changed, 168 insertions(+), 34 deletions(-) diff --git a/rwcal/plugins/vala/rwcal_openstack/rift/rwcal/openstack/openstack_drv.py b/rwcal/plugins/vala/rwcal_openstack/rift/rwcal/openstack/openstack_drv.py index 943cdd54..90cefa1a 100644 --- a/rwcal/plugins/vala/rwcal_openstack/rift/rwcal/openstack/openstack_drv.py +++ b/rwcal/plugins/vala/rwcal_openstack/rift/rwcal/openstack/openstack_drv.py @@ -70,6 +70,18 @@ class KeystoneDriver(object): """ return self._tenant_name + def get_user_domain_name(self): + """ + Returns None as this field does not exist for v2. + """ + return None; + + def get_project_domain_name(self): + """ + Returns None as this field does not exist for v2. + """ + return None; + def _get_keystone_connection(self): """ Returns object of class python-keystoneclient class @@ -263,7 +275,7 @@ class KeystoneDriverV3(KeystoneDriver): """ Driver class for keystoneclient V3 APIs """ - def __init__(self, username, password, auth_url,tenant_name, insecure): + def __init__(self, username, password, auth_url,tenant_name, insecure, user_domain_name = None, project_domain_name = None): """ Constructor for KeystoneDriverV3 class Arguments: @@ -274,26 +286,41 @@ class KeystoneDriverV3(KeystoneDriver): Returns: None """ - self._username = username - self._password = password - self._auth_url = auth_url - self._tenant_name = tenant_name - self._insecure = insecure + self._username = username + self._password = password + self._auth_url = auth_url + self._tenant_name = tenant_name + self._insecure = insecure + self._user_domain_name = user_domain_name + self._project_domain_name = project_domain_name super(KeystoneDriverV3, self).__init__(ksclientv3.Client) def _get_keystone_credentials(self): """ Returns the dictionary of kwargs required to instantiate python-keystoneclient class """ - creds = {} - #creds['user_domain'] = self._domain_name - creds['username'] = self._username - creds['password'] = self._password - creds['auth_url'] = self._auth_url - creds['project_name'] = self._tenant_name - creds['insecure'] = self._insecure + creds = {} + creds['username'] = self._username + creds['password'] = self._password + creds['auth_url'] = self._auth_url + creds['project_name'] = self._tenant_name + creds['insecure'] = self._insecure + creds['user_domain_name'] = self._user_domain_name + creds['project_domain_name'] = self._project_domain_name return creds + def get_user_domain_name(self): + """ + Returns the domain_name of the associated OpenStack user account + """ + return self._user_domain_name; + + def get_project_domain_name(self): + """ + Returns the domain_name of the associated OpenStack project + """ + return self._project_domain_name; + def get_auth_token(self): """ Returns a valid auth_token @@ -340,6 +367,9 @@ class NovaDriver(object): creds['project_id'] = self.ks_drv.get_tenant_name() creds['auth_token'] = self.ks_drv.get_auth_token() creds['insecure'] = self.ks_drv.get_security_mode() + creds['user_domain_name'] = self.ks_drv.get_user_domain_name() + creds['project_domain_name'] = self.ks_drv.get_project_domain_name() + return creds def _get_nova_connection(self): @@ -899,7 +929,7 @@ class NovaDriverV21(NovaDriver): Constructor for NovaDriver Arguments: KeystoneDriver class object """ - super(NovaDriverV21, self).__init__(ks_drv, 'computev21', '2.1') + super(NovaDriverV21, self).__init__(ks_drv, 'compute', '2.1') class GlanceDriver(object): """ @@ -1639,7 +1669,7 @@ class OpenstackDriver(object): """ Driver for openstack nova, neutron, glance, keystone, swift, cinder services """ - def __init__(self, username, password, auth_url, tenant_name, mgmt_network = None, cert_validate = False): + def __init__(self, username, password, auth_url, tenant_name, mgmt_network = None, cert_validate = False, user_domain_name = None, project_domain_name = None): """ OpenstackDriver Driver constructor Arguments: @@ -1654,7 +1684,7 @@ class OpenstackDriver(object): """ insecure = not cert_validate if auth_url.find('/v3') != -1: - self.ks_drv = KeystoneDriverV3(username, password, auth_url, tenant_name, insecure) + self.ks_drv = KeystoneDriverV3(username, password, auth_url, tenant_name, insecure, user_domain_name, project_domain_name) self.glance_drv = GlanceDriverV2(self.ks_drv) self.nova_drv = NovaDriverV21(self.ks_drv) self.neutron_drv = NeutronDriverV2(self.ks_drv) diff --git a/rwcal/plugins/vala/rwcal_openstack/rwcal_openstack.py b/rwcal/plugins/vala/rwcal_openstack/rwcal_openstack.py index 05dc4989..d3c0b972 100644 --- a/rwcal/plugins/vala/rwcal_openstack/rwcal_openstack.py +++ b/rwcal/plugins/vala/rwcal_openstack/rwcal_openstack.py @@ -75,7 +75,6 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): self._rwlog_handler = None RwcalOpenstackPlugin.instance_num += 1 - @contextlib.contextmanager def _use_driver(self, account): if self._rwlog_handler is None: @@ -83,12 +82,14 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): with rwlogger.rwlog_root_handler(self._rwlog_handler): try: - drv = self._driver_class(username = account.openstack.key, - password = account.openstack.secret, - auth_url = account.openstack.auth_url, - tenant_name = account.openstack.tenant, - mgmt_network = account.openstack.mgmt_network, - cert_validate = account.openstack.cert_validate ) + drv = self._driver_class(username = account.openstack.key, + password = account.openstack.secret, + auth_url = account.openstack.auth_url, + tenant_name = account.openstack.tenant, + mgmt_network = account.openstack.mgmt_network, + cert_validate = account.openstack.cert_validate, + user_domain_name = account.openstack.user_domain, + project_domain_name = account.openstack.project_domain) except (KeystoneExceptions.Unauthorized, KeystoneExceptions.AuthorizationFailure, NeutronException.NotFound) as e: raise diff --git a/rwcal/plugins/yang/rwcal.yang b/rwcal/plugins/yang/rwcal.yang index 76bd38b3..e038c471 100644 --- a/rwcal/plugins/yang/rwcal.yang +++ b/rwcal/plugins/yang/rwcal.yang @@ -231,6 +231,17 @@ module rwcal mandatory true; } + leaf user-domain { + type string; + default "Default"; + description "Domain of the OpenStack user"; + } + leaf project-domain { + type string; + default "Default"; + description "Domain of the OpenStack project"; + } + leaf tenant { type string; mandatory true; diff --git a/rwcal/test/test_rwcal_openstack.py b/rwcal/test/test_rwcal_openstack.py index 960beb9f..d0d7d62c 100644 --- a/rwcal/test/test_rwcal_openstack.py +++ b/rwcal/test/test_rwcal_openstack.py @@ -20,7 +20,6 @@ import logging import time import unittest import hashlib - import novaclient.exceptions as nova_exception import paramiko import rw_peas @@ -29,7 +28,7 @@ from keystoneclient import v3 as ksclient from gi.repository import RwcalYang from gi.repository.RwTypes import RwStatus -from rift.rwcal.openstack.openstack_drv import KeystoneDriver, NovaDriver +from rift.rwcal.openstack.openstack_drv import KeystoneDriver, NovaDriver, KeystoneDriverV3, KeystoneDriverV2 logger = logging.getLogger('rwcal-openstack') @@ -46,7 +45,22 @@ openstack_info = { 'reserved_image' : 'Fedora-x86_64-20-20131211.1-sda-ping.qcow2', 'physical_network' : None, 'network_type' : None, - 'segmentation_id' : None + 'segmentation_id' : None, + 'user_domain_name' : 'default', + 'project_domain_name': 'default' + } + +openstack_V3_info = { + 'username' : 'riftdev_admin', + 'password' : 'mypasswd', + 'auth_url' : 'http://10.68.0.11:5000/v3/', + 'project_name' : 'demov3', + 'mgmt_network' : 'center', + 'physical_network' : None, + 'network_type' : None, + 'segmentation_id' : None, + 'user_domain_name' : 'riftdev', + 'project_domain_name': 'riftdev' } @@ -54,14 +68,16 @@ def get_cal_account(): """ Creates an object for class RwcalYang.CloudAccount() """ - account = RwcalYang.CloudAccount() - account.name = "Gruntxx" - account.account_type = "openstack" - account.openstack.key = openstack_info['username'] - account.openstack.secret = openstack_info['password'] - account.openstack.auth_url = openstack_info['auth_url'] - account.openstack.tenant = openstack_info['project_name'] - account.openstack.mgmt_network = openstack_info['mgmt_network'] + account = RwcalYang.CloudAccount() + account.name = "Gruntxx" + account.account_type = "openstack" + account.openstack.key = openstack_info['username'] + account.openstack.secret = openstack_info['password'] + account.openstack.auth_url = openstack_info['auth_url'] + account.openstack.tenant = openstack_info['project_name'] + account.openstack.mgmt_network = openstack_info['mgmt_network'] + account.openstack.user_domain = openstack_info['user_domain_name'] + account.openstack.project_domain = openstack_info['project_domain_name'] return account def get_cal_plugin(): @@ -531,6 +547,7 @@ class OpenStackTest(unittest.TestCase): openstack_info['username'], openstack_info['password'], openstack_info['auth_url'], + None, openstack_info['project_name']) # Get hold of the client instance need for Token Manager client = drv._get_keystone_connection() @@ -566,6 +583,81 @@ class OpenStackTest(unittest.TestCase): flavors = nova.flavor_list() self.assertTrue(len(flavors) > 1) + def test_v3_Keystone(self): + # Keystone v3 authentication + auth_exp = False + try: + drv = KeystoneDriverV3(openstack_V3_info['username'], + openstack_V3_info['password'], + openstack_V3_info['auth_url'], + openstack_V3_info['project_name'], + None, + openstack_V3_info['user_domain_name'], + openstack_V3_info['project_domain_name']) + client = drv._get_keystone_connection() + except Exception: + auth_exp = True + self.assertFalse(auth_exp) + + # Incorrect domain being to passed to v3 Keystone API + auth_exp = False + try: + drv = KeystoneDriverV3(openstack_V3_info['username'], + openstack_V3_info['password'], + openstack_V3_info['auth_url'], + openstack_V3_info['project_name'], + None, + "DummyDom", + openstack_V3_info['project_domain_name']) + client = drv._get_keystone_connection() + except Exception: + auth_exp = True + self.assertTrue(auth_exp) + + # Keystone v3 authentication-Backward compatabilty test + auth_exp = False + try: + drv = KeystoneDriverV3(openstack_info['username'], + openstack_info['password'], + openstack_info['auth_url'], + openstack_info['project_name'], + None, + openstack_info['user_domain_name'], + openstack_info['project_domain_name']) + client = drv._get_keystone_connection() + except Exception: + auth_exp = True + self.assertFalse(auth_exp) + + # Keystone v3 authentication-Backward compatabilty + auth_exp = False + try: + drv = KeystoneDriverV3(openstack_info['username'], + openstack_info['password'], + openstack_info['auth_url'], + openstack_info['project_name'], + None, + None, + None) + client = drv._get_keystone_connection() + except Exception: + auth_exp = True + self.assertFalse(auth_exp) + + # Keystone v2 authentication + auth_exp = False + try: + drv2 = KeystoneDriverV2( + openstack_info['username'], + openstack_info['password'], + 'http://10.66.4.17:5000/v2.0', + openstack_info['project_name'], + None) + client = drv2._get_keystone_connection() + except Exception: + auth_exp = True + self.assertFalse(auth_exp) + @unittest.skip("Skipping test_vm_operations") def test_vm_operations(self): """ -- 2.25.1