group instances into tenants instead of running all instances in the admin tenant...
authorTony Mack <tmack@paris.CS.Princeton.EDU>
Tue, 14 Aug 2012 16:45:04 +0000 (12:45 -0400)
committerTony Mack <tmack@paris.CS.Princeton.EDU>
Tue, 14 Aug 2012 16:45:04 +0000 (12:45 -0400)
sfa/openstack/client.py
sfa/openstack/nova_driver.py
sfa/openstack/osaggregate.py
sfa/openstack/shell.py

index f0d717e..215d333 100644 (file)
@@ -23,14 +23,26 @@ def parse_novarc(filename):
 
 
 class KeystoneClient:
-    def __init__(self, config=None):
+    def __init__(self, username=None, password=None, tenant=None, url=None, config=None):
         if not config:
             config = Config()
         opts = parse_novarc(config.SFA_NOVA_NOVARC)
+        if username:
+            opts['OS_USERNAME'] = username
+        if password:
+            opts['OS_PASSWORD'] = password
+        if tenant:
+            opts['OS_TENANT_NAME'] = tenant
+        if url:
+            opts['OS_AUTH_URL'] = url
+        self.opts = opts 
         self.client = keystone_client.Client(username=opts.get('OS_USERNAME'),
                                              password=opts.get('OS_PASSWORD'),
                                              tenant_name=opts.get('OS_TENANT_NAME'),
                                              auth_url=opts.get('OS_AUTH_URL'))
+
+    def connect(self, *args, **kwds):
+        self.__init__(*args, **kwds)
    
     def __getattr__(self, name):
         return getattr(self.client, name) 
@@ -50,10 +62,19 @@ class GlanceClient:
         return getattr(self.client, name)
 
 class NovaClient:
-    def __init__(self, config=None):
+    def __init__(self, username=None, password=None, tenant=None, url=None, config=None):
         if not config:
             config = Config()
         opts = parse_novarc(config.SFA_NOVA_NOVARC)
+        if username:
+            opts['OS_USERNAME'] = username
+        if password:
+            opts['OS_PASSWORD'] = password
+        if tenant:
+            opts['OS_TENANT_NAME'] = tenant
+        if url:
+            opts['OS_AUTH_URL'] = url
+        self.opts = opts
         self.client = nova_client.Client(username=opts.get('OS_USERNAME'),
                                          api_key=opts.get('OS_PASSWORD'),
                                          project_id=opts.get('OS_TENANT_NAME'),
@@ -63,6 +84,9 @@ class NovaClient:
                                          service_type='compute',
                                          service_name='',  
                                          )
+
+    def connect(self, *args, **kwds):
+        self.__init__(*args, **kwds)
                               
     def __getattr__(self, name):
         return getattr(self.client, name)        
index 7fb5393..27795f7 100644 (file)
@@ -43,7 +43,7 @@ class NovaDriver(Driver):
 
     def __init__ (self, config):
         Driver.__init__(self, config)
-        self.shell = Shell(config)
+        self.shell = Shell(config=config)
         self.cache=None
         if config.SFA_AGGREGATE_CACHING:
             if NovaDriver.cache is None:
@@ -90,7 +90,9 @@ class NovaDriver(Driver):
         for researcher in researchers:
             name = Xrn(researcher).get_leaf()
             user = self.shell.auth_manager.users.find(name=name)
+            self.shell.auth_manager.roles.add_user_role(user, 'Member', tenant)
             self.shell.auth_manager.roles.add_user_role(user, 'user', tenant)
+            
 
         pis = sfa_record.get('pis', [])
         for pi in pis:
@@ -432,6 +434,19 @@ class NovaDriver(Driver):
         aggregate = OSAggregate(self)
         rspec = RSpec(rspec_string)
         instance_name = hrn_to_os_slicename(slice_hrn)
+
+        # make sure a tenant exists for this slice
+        tenant = aggregate.create_tenant(slice_hrn)
+
+        # add the sfa admin user to this tenant and update our nova client connection
+        # to use these credentials for the rest of this session. This emsures that the instances
+        # we create will be assigned to the correct tenant.
+        sfa_admin_user = self.shell.auth_manager.users.find(name=self.shell.auth_manager.opts['OS_USERNAME'])
+        user_role = self.shell.auth_manager.roles.find(name='user')
+        admin_role = self.shell.auth_manager.roles.find(name='admin')
+        self.shell.auth_manager.roles.add_user_role(sfa_admin_user, admin_role, tenant)
+        self.shell.auth_manager.roles.add_user_role(sfa_admin_user, user_role, tenant)
+        self.shell.nova_manager.connect(tenant=tenant.name)
        
         # assume first user is the caller and use their context
         # for the ec2/euca api connection. Also, use the first users
index 241ec0b..519f8e8 100644 (file)
@@ -99,9 +99,9 @@ class OSAggregate:
             node_xrn = instance.metadata.get('component_id')
             node_xrn
             if not node_xrn:
-                node_xrn = OSXrn('cloud', 'node')
+                node_xrn = OSXrn('cloud', type='node')
             else:
-                node_xrn = OSXrn(xrn=node_xrn, 'node') 
+                node_xrn = OSXrn(xrn=node_xrn, type='node') 
 
             rspec_node['component_id'] = node_xrn.urn
             rspec_node['component_name'] = node_xrn.name
@@ -170,10 +170,21 @@ class OSAggregate:
         return rspec_nodes 
 
 
+    def create_tenant(self, slice_hrn):
+        tenant_name = OSXrn(xrn=slice_hrn, type='slice').get_tenant_name()
+        tenants = self.driver.shell.auth_manager.tenants.findall(name=tenant_name)
+        if not tenants:
+            self.driver.shell.auth_manager.tenants.create(tenant_name, tenant_name)
+            tenant = self.driver.shell.auth_manager.tenants.find(name=tenant_name)
+        else:
+            tenant = tenants[0]
+        return tenant
+            
+
     def create_instance_key(self, slice_hrn, user):
         slice_name = Xrn(slice_hrn).leaf
         user_name = Xrn(user['urn']).leaf
-        key_name = "%s:%s" % (slice_name, user_name)
+        key_name = "%s_%s" % (slice_name, user_name)
         pubkey = user['keys'][0]
         key_found = False
         existing_keys = self.driver.shell.nova_manager.keypairs.findall(name=key_name)
index 7fab67f..acb9cff 100644 (file)
@@ -31,9 +31,9 @@ class Shell:
             config = Config()
         if has_nova:
             # instantiate managers 
-            self.auth_manager = KeystoneClient(config)
-            self.image_manager = GlanceClient(config)
-            self.nova_manager = NovaClient(config)
+            self.auth_manager = KeystoneClient(config=config)
+            self.image_manager = GlanceClient(config=config)
+            self.nova_manager = NovaClient(config=config)
         else:
             logger.debug('nova access - REST')
             raise SfaNotImplemented('nova access - Rest')