Andrew Bogott has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/325830 )

Change subject: Add clientlib.pp and mwopenstackclients.py
......................................................................


Add clientlib.pp and mwopenstackclients.py

This is a stand-alone class that should install everything needed
to do basic openstack queries -- in particular, to enumerate
projects and instances.

Bug: T150092
Change-Id: I621a434d5cadb4c1f50043685a735108560463b8
---
A modules/openstack/files/mwopenstackclients.py
A modules/openstack/manifests/clientlib.pp
M modules/openstack/manifests/envscripts.pp
M modules/role/manifests/horizon.pp
M modules/role/manifests/labs/openstack/nova/controller.pp
5 files changed, 169 insertions(+), 9 deletions(-)

Approvals:
  Andrew Bogott: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/modules/openstack/files/mwopenstackclients.py 
b/modules/openstack/files/mwopenstackclients.py
new file mode 100644
index 0000000..5890320
--- /dev/null
+++ b/modules/openstack/files/mwopenstackclients.py
@@ -0,0 +1,133 @@
+import os
+
+import glanceclient
+from keystoneclient.auth.identity import generic
+from keystoneclient import session as keystone_session
+from keystoneclient.v3 import client as keystone_client
+from novaclient import client as nova_client
+
+
+class clients(object):
+    # envfile should be a puppetized environment file like observerenv.sh.
+    #
+    #  If envfile is not specified, specific creds can be passed in as
+    #  username, password, url, project args.  Failing that we fall
+    #  back on the environment.
+    def __init__(self,
+                 envfile="",
+                 username="",
+                 password="",
+                 url="",
+                 project=""):
+        self.sessions = {}
+        self.keystoneclients = {}
+        self.novaclients = {}
+        self.glanceclients = {}
+
+        if envfile:
+            if username or password or url or project:
+                raise Exception("envfile is incompatible with specific args")
+
+            with open(envfile) as f:
+                for line in iter(f):
+                    pieces = line.strip().split("=")
+                    if pieces[0].endswith('OS_USERNAME'):
+                        self.username = pieces[1].strip('"')
+                    if pieces[0].endswith('OS_PASSWORD'):
+                        self.password = pieces[1].strip('"')
+                    if pieces[0].endswith('OS_AUTH_URL'):
+                        self.url = pieces[1].strip('"')
+                    if pieces[0].endswith('OS_TENANT_NAME'):
+                        self.project = pieces[1].strip('"')
+        else:
+            if username:
+                self.username = username
+            else:
+                self.username = os.environ.get('OS_USERNAME', None)
+
+            if password:
+                self.username = password
+            else:
+                self.password = os.environ.get('OS_PASSWORD', None)
+
+            if url:
+                self.url = url
+            else:
+                self.url = os.environ.get('OS_AUTH_URL', None)
+
+            if project:
+                self.project = project
+            else:
+                self.project = os.environ.get('OS_TENANT_NAME', None)
+
+        if not self.username:
+            raise Exception("No username (env OS_USERNAME) specified")
+        if not self.password:
+            raise Exception("No password (env OS_PASSWORD) specified")
+        if not self.url:
+            raise Exception("No url (env OS_AUTH_URL) specified")
+        if not self.project:
+            raise Exception("No project (env OS_TENANT_NAME) specified")
+
+    def session(self, project=None):
+        if not project:
+            project = self.project
+
+        if project not in self.sessions:
+
+            auth = generic.Password(
+                auth_url=self.url,
+                username=self.username,
+                password=self.password,
+                user_domain_name='Default',
+                project_domain_name='Default',
+                project_name=project)
+
+            self.sessions[project] = keystone_session.Session(auth=auth)
+        return self.sessions[project]
+
+    def keystoneclient(self, project=None):
+        if not project:
+            project = self.project
+
+        if project not in self.keystoneclients:
+            session = self.session(project)
+            self.keystoneclients[project] = keystone_client.Client(
+                session=session)
+        return self.keystoneclients[project]
+
+    def novaclient(self, project=None):
+        if not project:
+            project = self.project
+
+        if project not in self.novaclients:
+            session = self.session(project)
+            self.novaclients[project] = nova_client.Client('2',
+                                                           session=session)
+        return self.novaclients[project]
+
+    def glanceclient(self, project=None):
+        if not project:
+            project = self.project
+
+        if project not in self.glanceclients:
+            session = self.session(project)
+            self.glanceclients[project] = glanceclient.Client('1',
+                                                              session=session)
+        return self.glanceclients[project]
+
+    def allprojects(self):
+        client = self.keystoneclient()
+        return client.projects.list()
+
+    def allinstances(self):
+        instances = []
+        for project in self.allprojects():
+            if project.id == 'admin':
+                continue
+            instances.extend(self.novaclient(project.id).servers.list())
+        return instances
+
+    def globalimages(self):
+        client = self.glanceclient()
+        return [i for i in client.images.list()]
diff --git a/modules/openstack/manifests/clientlib.pp 
b/modules/openstack/manifests/clientlib.pp
new file mode 100644
index 0000000..5b24080
--- /dev/null
+++ b/modules/openstack/manifests/clientlib.pp
@@ -0,0 +1,33 @@
+# Utilities for querying openstack
+class openstack::clientlib {
+
+    # We don't need all the extras that role::labs::openstack::nova::common
+    #  includes... the simple config straight from hiera should do the trick.
+    $novaconfig = hiera_hash('novaconfig', {})
+    $nova_region = $::site
+
+    $packages = [
+        'python-novaclient',
+        'python-glanceclient',
+        'python-keystoneclient',
+        'python-openstackclient',
+    ]
+    require_package($packages)
+
+    # Handy script to set up environment for read-only credentials
+    file { '/root/observerenv.sh':
+        content => template('openstack/observerenv.sh.erb'),
+        mode    => '0755',
+        owner   => 'root',
+        group   => 'root',
+    }
+
+    # Wrapper python class to easily query openstack clients
+    file { '/usr/lib/python2.7/dist-packages/mwopenstackclients.py':
+        ensure => present,
+        source => 'puppet:///modules/openstack/mwopenstackclients.py',
+        mode   => '0755',
+        owner  => 'root',
+        group  => 'root',
+    }
+}
diff --git a/modules/openstack/manifests/envscripts.pp 
b/modules/openstack/manifests/envscripts.pp
index bb87839..a668a42 100644
--- a/modules/openstack/manifests/envscripts.pp
+++ b/modules/openstack/manifests/envscripts.pp
@@ -13,15 +13,7 @@
         group   => 'root',
     }
 
-    # Handy script to set up environment for read-only credentials
-    file { '/root/observerenv.sh':
-        content => template('openstack/observerenv.sh.erb'),
-        mode    => '0755',
-        owner   => 'root',
-        group   => 'root',
-    }
-
-    # Handy script to set up environment for commandline nova magic
+    # Handy script to set up environment for commandline glance magic
     file { '/root/wmflabsorg-domainadminenv.sh':
         content => template('openstack/wmflabsorg-domainadminenv.sh.erb'),
         mode    => '0755',
diff --git a/modules/role/manifests/horizon.pp 
b/modules/role/manifests/horizon.pp
index f116d74..882f55e 100644
--- a/modules/role/manifests/horizon.pp
+++ b/modules/role/manifests/horizon.pp
@@ -15,6 +15,7 @@
         srange => '$PRODUCTION_NETWORKS',
     }
 
+    include ::openstack::clientlib
     class { '::openstack::envscripts':
         novaconfig      => $novaconfig,
         designateconfig => $designateconfig
diff --git a/modules/role/manifests/labs/openstack/nova/controller.pp 
b/modules/role/manifests/labs/openstack/nova/controller.pp
index 7bb0e41..264cdd7 100644
--- a/modules/role/manifests/labs/openstack/nova/controller.pp
+++ b/modules/role/manifests/labs/openstack/nova/controller.pp
@@ -8,6 +8,7 @@
     include ::openstack::nova::conductor
     include ::openstack::nova::spiceproxy
     include ::openstack::nova::scheduler
+    include ::openstack::clientlib
     include role::labs::openstack::nova::common
     $novaconfig = $role::labs::openstack::nova::common::novaconfig
     $designateconfig = hiera_hash('designateconfig', {})

-- 
To view, visit https://gerrit.wikimedia.org/r/325830
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I621a434d5cadb4c1f50043685a735108560463b8
Gerrit-PatchSet: 7
Gerrit-Project: operations/puppet
Gerrit-Branch: production
Gerrit-Owner: Andrew Bogott <[email protected]>
Gerrit-Reviewer: Alex Monk <[email protected]>
Gerrit-Reviewer: Andrew Bogott <[email protected]>
Gerrit-Reviewer: Volans <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to