Merge "Add domain name when creating projects and users"
[snaps.git] / snaps / openstack / utils / keystone_utils.py
index 3fff469..10ad68a 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2016 Cable Television Laboratories, Inc. ("CableLabs")
+# Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs")
 #                    and others.  All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,7 +19,7 @@ from keystoneauth1.identity import v3, v2
 from keystoneauth1 import session
 import requests
 
-from snaps.domain.project import Project
+from snaps.domain.project import Project, Domain
 from snaps.domain.role import Role
 from snaps.domain.user import User
 
@@ -104,18 +104,17 @@ def get_endpoint(os_creds, service_type, interface='public'):
         auth=auth, service_type=service_type, interface=interface)
 
 
-def get_project(keystone=None, os_creds=None, project_name=None):
+def get_project(keystone=None, os_creds=None, project_settings=None,
+                project_name=None):
     """
     Returns the first project object or None if not found
     :param keystone: the Keystone client
     :param os_creds: the OpenStack credentials used to obtain the Keystone
                      client if the keystone parameter is None
+    :param project_settings: a ProjectSettings object
     :param project_name: the name to query
     :return: the SNAPS-OO Project domain object or None
     """
-    if not project_name:
-        return None
-
     if not keystone:
         if os_creds:
             keystone = keystone_client(os_creds)
@@ -123,21 +122,30 @@ def get_project(keystone=None, os_creds=None, project_name=None):
             raise KeystoneException(
                 'Cannot lookup project without the proper credentials')
 
+    proj_filter = dict()
+
+    if project_name:
+        proj_filter['name'] = project_name
+    elif project_settings:
+        proj_filter['name'] = project_settings.name
+        proj_filter['description'] = project_settings.description
+        proj_filter['domain_name'] = project_settings.domain_name
+        proj_filter['enabled'] = project_settings.enabled
+
     if keystone.version == V2_VERSION_STR:
         projects = keystone.tenants.list()
     else:
-        projects = keystone.projects.list(**{'name': project_name})
+        projects = keystone.projects.list(**proj_filter)
 
     for project in projects:
-        domain_id = None
-        if keystone.version != V2_VERSION_STR:
-            domain_id = project.domain_id
-        if project.name == project_name:
+        if project.name == proj_filter['name']:
+            domain_id = None
+            if keystone.version != V2_VERSION_STR:
+                domain_id = project.domain_id
+
             return Project(name=project.name, project_id=project.id,
                            domain_id=domain_id)
 
-    return None
-
 
 def create_project(keystone, project_settings):
     """
@@ -153,8 +161,12 @@ def create_project(keystone, project_settings):
             project_settings.name, project_settings.description,
             project_settings.enabled)
     else:
+        os_domain = __get_os_domain_by_name(
+            keystone, project_settings.domain_name)
+        if not os_domain:
+            os_domain = project_settings.domain_name
         os_project = keystone.projects.create(
-            project_settings.name, project_settings.domain,
+            project_settings.name, os_domain,
             description=project_settings.description,
             enabled=project_settings.enabled)
         domain_id = os_project.domain_id
@@ -193,7 +205,9 @@ def get_user(keystone, username, project_name=None):
     :param project_name: the associated project (optional)
     :return: a SNAPS-OO User domain object or None
     """
-    project = get_project(keystone=keystone, project_name=project_name)
+    project = None
+    if project_name:
+        project = get_project(keystone=keystone, project_name=project_name)
 
     if project:
         users = keystone.users.list(tenant_id=project.id)
@@ -228,18 +242,21 @@ def create_user(keystone, user_settings):
             email=user_settings.email, tenant_id=project_id,
             enabled=user_settings.enabled)
     else:
+        os_domain = __get_os_domain_by_name(
+            keystone, user_settings.domain_name)
+        if not os_domain:
+            os_domain = user_settings.domain_name
         os_user = keystone.users.create(
             name=user_settings.name, password=user_settings.password,
             email=user_settings.email, project=project,
-            domain=user_settings.domain_name, enabled=user_settings.enabled)
+            domain=os_domain, enabled=user_settings.enabled)
 
     for role_name, role_project in user_settings.roles.items():
         os_role = get_role_by_name(keystone, role_name)
         os_project = get_project(keystone=keystone, project_name=role_project)
 
         if os_role and os_project:
-            existing_roles = get_roles_by_user(keystone, os_user,
-                                               os_project)
+            existing_roles = get_roles_by_user(keystone, os_user, os_project)
             found = False
             for role in existing_roles:
                 if role.id == os_role.id:
@@ -345,6 +362,31 @@ def grant_user_role_to_project(keystone, role, user, project):
         keystone.roles.grant(os_role, user=user, project=project)
 
 
+def get_domain_by_id(keystone, domain_id):
+    """
+    Returns the first OpenStack domain with the given name else None
+    :param keystone: the Keystone client
+    :param domain_id: the domain ID to retrieve
+    :return: the SNAPS-OO Domain domain object
+    """
+    domain = keystone.domains.get(domain_id)
+    if domain:
+        return Domain(name=domain.name, domain_id=domain.id)
+
+
+def __get_os_domain_by_name(keystone, domain_name):
+    """
+    Returns the first OpenStack domain with the given name else None
+    :param keystone: the Keystone client
+    :param domain_name: the domain name to lookup
+    :return: the OpenStack domain object
+    """
+    domains = keystone.domains.list(name=domain_name)
+    for domain in domains:
+        if domain.name == domain_name:
+            return domain
+
+
 class KeystoneException(Exception):
     """
     Exception when calls to the Keystone client cannot be served properly