updated to support remote plcs and nodes
authorTony Mack <tmack@cs.princeton.edu>
Tue, 18 Mar 2008 21:14:14 +0000 (21:14 +0000)
committerTony Mack <tmack@cs.princeton.edu>
Tue, 18 Mar 2008 21:14:14 +0000 (21:14 +0000)
qaapi/qa/tests/add_test_data.py
qaapi/qa/tests/delete_test_data.py
qaapi/qa/tests/plc_configure.py
qaapi/qa/tests/plc_install.py
qaapi/qa/tests/plc_start.py
qaapi/qa/tests/plc_stop.py
qaapi/qa/tests/plc_uninstall.py

index 9dc84ed..b411816 100644 (file)
 import os,sys
 from Test import Test
 from qa import utils
-
+from qa.PLCs import PLC, PLCs
+  
 class add_test_data(Test):
     """
     Adds the test data found in config to the plc db
     """   
-    def call(self):
-       api = self.config.api
-       auth = self.config.auth
-       # Make sure some required fields are in config
-       required_fields = ['TEST_SITE_NAME', 'TEST_SITE_LOGIN_BASE', 'TEST_SLICE_NAME', 'TEST_PERSON_EMAIL']
-       required_node_fields = ['TEST_NODE_TYPE', 'TEST_NODE_METHOD', 'TEST_NODE_HOSTNAME', 'TEST_NODE_IP',
-                               'TEST_NODE_GATEWAY', 'TEST_NODE_DNS', 'TEST_NODE_NETWORK', 'TEST_NODE_BROADCAST',
-                               'TEST_NODE_NETMASK']
-
-       for field in required_fields:
-           if not hasattr(self.config, field) or \
-                  len(getattr(self.config, field).strip()) < 1:
-               raise Exception, "%(field)s must be set and cannot be blank" % locals()
-
-       # Look for node configurations
-       node_params = {}
-        for attr in dir(self.config):
-            if attr.find("NODE") > 0:
-                parts = attr.split('_')
-                node_prefix = parts[1] +"_"+ parts[3]
-                name = "_".join(parts[:3])
-                value = getattr(self.config, attr)
-                # start a new node dictionary
-                if node_prefix not in node_params:
-                    node_params[node_prefix] = {'prefix': node_prefix}
-                node_params[node_prefix][name] = value
-
-       node_configs = node_params.values()
-       node_list = []
-
-       # Make sure required node fields are preset for each node config
-        for node_config in node_configs:
-           for field in required_node_fields:
-               if field not in node_config or len(node_config[field].strip()) < 1:
-                   raise Exception, "%s must be set for %s and cannot be blank" % (field, node_config['prefix'])
-           node = {'type': node_config['TEST_NODE_TYPE'],
-                   'method': node_config['TEST_NODE_METHOD'],
-                   'hostname': node_config['TEST_NODE_HOSTNAME'],
-                   'ip':  node_config['TEST_NODE_IP'],
-                   'gateway': node_config['TEST_NODE_GATEWAY'],
-                   'dns1': node_config['TEST_NODE_DNS'],
-                   'broadcast': node_config['TEST_NODE_BROADCAST'], 
-                   'network': node_config['TEST_NODE_NETWORK'],
-                   'netmask': node_config['TEST_NODE_NETMASK'],
-                   'slice_ids': [],
-                   'nodenetwork_ids': []}
-           node_list.append(node)
-           
-           
-       # Define test objects 
-       site_fields = {'name': self.config.TEST_SITE_NAME, 'login_base': self.config.TEST_SITE_LOGIN_BASE, 
-                      'url': 'http://google.com', 'enabled': True, 'max_slices': 1000, 
-                      'max_slivers': 1000, 'is_public': True, 'abbreviated_name': 'Test', 
-                      'person_ids': []}
+    def call(self,  plc_name = None):
 
-       slice_fields = {'name': self.config.TEST_SLICE_NAME, 'instantiation': 'plc-instantiated', 
-                       'max_nodes': 1000, 'description': 'blank', 'person_ids': [], 'node_ids': []}
+       # Determine which plc to talk to 
+        plc = PLC(self.config)
+        plcs = getattr(self.config, 'plcs', [])
+        for p in plcs:
+            if p['name'] in [plc_name]:
+                plc.update(p)
+        plc.config.update_api(plc)
 
-       person_fields = {'first_name': 'fname', 'last_name': 'lname', 'password': 'password',
-                        'email': self.config.TEST_PERSON_EMAIL, 'site_ids': [], 'slice_ids': []}
+        api = plc.config.api
+        auth = plc.config.auth
 
 
+       # Search config for objects that belong to this plc
+       # Any object with 'plc' defined as this plc's name or with 
+       # no 'plc' defined will be added
+       this_plc = lambda object: 'plc' not in object or \
+                                 'plc' in object and object['plc'] == plc['name'] or \
+                                 object['plc'] == None   
+     
+       sitelist = filter(this_plc, self.config.sites)          
+       nodelist = filter(this_plc, self.config.nodes)
+       slicelist = filter(this_plc, self.config.slices)
+       personlist = filter(this_plc, self.config.persons) 
+       
        # Add Test site
-       sites = api.GetSites(auth, {'login_base': site_fields['login_base']})
-       if not sites:
-           site_id = api.AddSite(auth, site_fields)
-           site_fields['site_id'] = site_id
-           site = site_fields
-           if self.config.verbose:
-               utils.header("Added test site")
-       else:
-           site = sites[0]
-           if self.config.verbose:
-               utils.header("Test site found")
+       for site in sitelist:
+           sites = api.GetSites(auth, [site['login_base']])
+           if not sites:
+               site_id = api.AddSite(auth, dict(site))
+               site['site_id'] = site_id
+               if self.config.verbose:
+                   utils.header("Added site: %s" % site['name'])
+           else:
+               site.update(sites[0])
+               if self.config.verbose:
+                   utils.header("Site %s found" % site['name'])
 
        # Add Test nodes
-       for node_fields in node_list:
-           nodes = api.GetNodes(auth, [node_fields['hostname']])
+       for node in nodelist:
+           nodes = api.GetNodes(auth, [node['hostname']])
            if not nodes:
-               node_id = api.AddNode(auth, site_fields['login_base'], node_fields)
-               node_fields['node_id'] = node_id
-               node = node_fields
-               nodes.append(node_fields)
+               node_id = api.AddNode(auth, node['site'], dict(node))
+               node['node_id'] = node_id
                if self.config.verbose:
-                   utils.header("Added test node")
+                   utils.header("Added node: %s" % node['hostname'])
            else:
-               node = nodes[0]
+               node.update(nodes[0])
                if self.config.verbose:
-                   utils.header("Test node found")
+                   utils.header("Node %s found" % node['hostname'])
 
            # Add node network
-           if not node['nodenetwork_ids']:
-               nodenetwork_id = api.AddNodeNetwork(auth, node_fields['hostname'], node_fields)
-               if self.config.verbose:
-                   utils.header("Added test nodenetwork")
+           if 'nodenetwork_ids' not in node or not node['nodenetwork_ids']:
+               for nodenetwork in node['nodenetworks']:
+                   nodenetwork_id = api.AddNodeNetwork(auth, node['hostname'], dict(nodenetwork))
+                   if self.config.verbose:
+                       utils.header("Added nodenetwork to %s" % node['hostname'])
+               else:
+                   if self.config.verbose:
+                       utils.header("Nodenetwork found on node %s" % node['hostname']) 
+       
+       # Add Test slice
+       for slice in slicelist:
+           slices = api.GetSlices(auth, [slice['name']])
+           if not slices:
+               slice_id = api.AddSlice(auth, dict(slice))
+               slice['slice_id'] = slice_id
+               if self.config.verbose:
+                   utils.header("Added slice: %s" % slice['name'])
            else:
+               slice.update(slices[0])
+               if self.config.verbose:
+                   utils.header("Slice %s found" % slice['name'])
+           
+           # Add slice to nodes
+           for node in slice['nodes']:
+               api.AddSliceToNodes(auth, slice['name'], [node])                
                if self.config.verbose:
-                   utils.header("Nodenetwork found")   
+                   utils.header("Added slice to %s" % node)
        
-       # Add Test slice
-       slices = api.GetSlices(auth, [slice_fields['name']])
-       if not slices:
-           slice_id = api.AddSlice(auth, slice_fields)
-           slice_fields['slice_id'] = slice_id
-           slice = slice_fields
-           if self.config.verbose:
-               utils.header("Added test slice")
-       else:
-           slice = slices[0]
-           if self.config.verbose:
-               utils.header("Test slice found")
-
-       # Add slice to nodes
-       node_ids = [n['node_id'] for n in nodes]
-       node_ids = filter(lambda node_id: node_id not in slice['node_ids'], node_ids)
-       if node_ids:
-           api.AddSliceToNodes(auth, slice['name'], node_ids)
-           if self.config.verbose:
-               utils.header("Added test slice to test nodes")
-       else:
-           if self.config.verbose:
-               utils.header("Test slice found on test nodes")
-
        # Add test person
-       persons = api.GetPersons(auth, [person_fields['email']])
-       if not persons:
-           person_id = api.AddPerson(auth, person_fields)
-           person_fields['person_id'] = person_id
-           person = person_fields
-           if self.config.verbose:
-               utils.header("Added test person")
-       else:
-           person = persons[0]
-           if self.config.verbose:
-               utils.header("Test person found")
+       for person in personlist:
+           roles = person['roles']
+           persons = api.GetPersons(auth, [person['email']])
+           if not persons:
+               person_id = api.AddPerson(auth, dict(person))
+               person['person_id'] = person_id
+               api.UpdatePerson(auth, person_id, {'enabled': True})
+               if self.config.verbose:
+                   utils.header("Added person: %s" % person['email'])
+           else:
+               person.update(persons[0])
+               if self.config.verbose:
+                   utils.header("Person %s found" % person['email'])
        
-       # Add roles to person
-       api.AddRoleToPerson(auth, 'user', person['email'])
-       # Add person to site
-       if site['site_id'] not in person['site_ids']:   
-           api.AddPersonToSite(auth, person['email'], site['login_base'])
-           if self.config.verbose:
-               utils.header("Added test person to test site")
-       else:
-           if self.config.verbose:
-               utils.header("Test person found on test site")
+           # Add roles to person
+           for role in roles:
+               api.AddRoleToPerson(auth, role, person['email'])
+               if self.config.verbose:
+                   utils.header("Added %s to %s" % (role, person['email']))
+           # Add person to site
+           for site in person['sites']:
+               api.AddPersonToSite(auth, person['email'], site)
+               if self.config.verbose:
+                   utils.header("Added %s to %s" % (person['email'], site))
 
-       # Add person to slice
-       if slice['slice_id'] not in person['slice_ids']:
-            api.AddPersonToSlice(auth, person_fields['email'], slice_fields['name'])
-           if self.config.verbose:
-               utils.header("Added test person to slice")
-       else:
-           if self.config.verbose:
-               utils.header("Test person found on test slice")
+           # Add person to slice
+           for slice in person['slices']:
+                api.AddPersonToSlice(auth, person['email'], slice)
+               if self.config.verbose:
+                   utils.header("Added %s to %s" % (person['email'], slice))
        return 1
 
 if __name__ == '__main__':
index b6c1f45..d831f0a 100644 (file)
@@ -3,25 +3,45 @@
 import os, sys
 from Test import Test
 from qa import utils
-
+from qa.PLCs import PLC, PLCs
 
 class delete_test_data(Test):
     """
     Removes the test data found in config from the plc db
     """
 
-    def call(self):
-       api = self.config.api
-       auth = self.config.auth 
-       site_login_base = self.config.TEST_SITE_LOGIN_BASE
-       slice_name = self.config.TEST_SLICE_NAME
+    def call(self, plc_name = None):
+
+       # Determine which plc to talk to 
+        plc = PLC(self.config)
+        plcs = getattr(self.config, 'plcs', [])
+        for p in plcs:
+            if p['name'] in [plc_name]:
+                plc.update(p)
+        plc.config.update_api(plc)
+
+        api = plc.config.api
+        auth = plc.config.auth
        
+       # Search config for objects that belong to this plc
+        # Any object with 'plc' defined as this plc's name or with 
+        # no 'plc' defined will be added
+        this_plc = lambda object: 'plc' not in object or \
+                                  'plc' in object and object['plc'] == plc['name'] or \
+                                  object['plc'] == None
+
+       sitelist = filter(this_plc, self.config.sites)
+               
        # Deleting the site should delete everything associated with it
        # including nodes, persons
-       api.DeleteSite(auth, site_login_base)
-       if self.config.verbose:
-           utils.header("Test data deleted")
-
+       for site in sitelist:
+           try:
+               api.DeleteSite(auth, site['login_base'])
+               if self.config.verbose:
+                   utils.header("Test data deleted")
+           except:
+               if self.config.verbose:
+                   utils.header("Error deleting %s" % site['login_base'])              
        return 1 
        
 if __name__ == '__main__':
index c08993f..381179a 100644 (file)
@@ -4,25 +4,34 @@ import traceback
 from Test import Test
 from qa import utils
 import tempfile
+from qa.PLCs import PLC, PLCs
 
 class plc_configure(Test):
     """
     Configure the myplc from config options in config file
     """
 
-    def call(self, plc_config_option=None, plc_config_value=None):
+    def call(self, plc_name, plc_config_option=None, plc_config_value=None):
        
+       # Get plc configuration from config
+        plc = PLC(self.config)
+        plcs = getattr(self.config, 'plcs', [])
+        for p in plcs:
+            if p['name'] in [plc_name]:
+                plc.update(p)
+
        services = ['API', 'DB', 'WWW', 'BOOT']
        plc_options = [] 
-        # Turn off plc (for good measure)
+        
+       # Turn off plc (for good measure)
        command = "/sbin/service plc stop"
        if self.config.verbose: utils.header(command)
-        (stdout, stderr) = utils.popen(command)
+        (status, output) = plc.commands(command)
 
        # mount plc (need to do this optionally, as we do not want this for myplc-native)
        command = "/sbin/service plc mount"
        if self.config.verbose: utils.header(command)
-        (stdout, stderr) = utils.popen(command)
+        (status, output) = plc.commands(command)
 
        # Get plc configuration variables
        if plc_config_option is not None and \
@@ -34,35 +43,39 @@ class plc_configure(Test):
            for service in services:
                host_option = 'PLC_%(service)s_HOST' % locals()
                ip_option = 'PLC_%(service)s_IP' % locals() 
-               plc_options.append((host_option, self.config.hostname))
-               plc_options.append((ip_option, self.config.ip)) 
+               plc_options.append((host_option, plc['host']))
+               plc_options.append((ip_option, plc['ip']))      
            # Load any other options found in config file
            for attr in dir(self.config):
                if attr.startswith('PLC'):
                    plc_options.append((attr, getattr(self.config, attr)))
                
        # Write temporary plc-config file
-        tmpfconf, tmpfname = tempfile.mkstemp(".config","plc-config-tty")
+       # XX use plc instance to copy file
+        tmpfconf, tmpfname = tempfile.mkstemp(".config","plc-config-tty", '/usr/tmp/')
+       tmpfname_parts = tempfname.split(os.sep)
        if self.config.verbose:
             utils.header("generating temporary config file %(tmpfname)s"%locals())
        for (option, value) in plc_options:
             os.write(tmpfconf, 'e %s\n%s\n' % (option, value))
         os.write(tmpfconf,'w\nq\n')
        os.close(tmpfconf)
-        
+       plc.scp(tmpfname, "%s:/usr/tmp" % (plc['host']))
+
         # configure plc
        command = "plc-config-tty < %(tmpfname)s" % locals()
        if self.config.verbose: utils.header(command)
-        (stdout, stderr) = utils.popen(command)
+        (status, output) = plc.commands(command)
 
        # clean up temporary conf file
+       # XX use plc instance to copy file
        if self.config.verbose: utils.header("removing %(tmpfname)s"%locals())
         os.unlink(tmpfname)
 
        # umount plc (need to do this optionally, as we do not want this for myplc-native)
        command = "/sbin/service plc umount"
        if self.config.verbose: utils.header(command)
-        (stdout, stderr) = utils.popen(command)
+        (status, output) = plc.commands(command)
 
        return 1
 
index 2f5642d..9283eff 100644 (file)
@@ -4,15 +4,25 @@ import os, sys
 import traceback
 from qa import utils
 from Test import Test
+from qa.PLCs import PLC, PLCs
 
 class plc_install(Test):
     """
     Installs a myplc
     """
 
-    def call(self, url=None):
+    def call(self, plc_name, url=None):
+       
+       # Get plc qa config
+       plc = PLC(self.config)
+       plcs = getattr(self.config, 'plcs', [])  
+       for p in plcs:
+           if p['name'] in [plc_name]:
+               plc.update(p) 
+      
        
        url_path = self.config.path
+
        # Determine url
        if not url:
            try:
@@ -36,26 +46,23 @@ class plc_install(Test):
        if self.config.verbose:
            utils.header('Downloading myplc from url %s' % url)
 
+       # build commands
        url_parts = url.split(os.sep)
        rpm_file = url[-1:]
        download_cmd = "wget %(url)s /tmp/%(rpm_file)s" % locals()
-
-       # build command
        rpm_install = "rpm -Uvh /tmp/%(rpm_file)s" % locals()
        yum_install = "yum -y localinstall /tmp/%(rpm_file)s" % locals()
 
        if self.config.verbose:
            utils.header("Trying: %(rpm_install)s" % locals())
         try: 
-           (stdout, stderr) = utils.popen(rpm_install)
+           (status, output) = plc.commands(rpm_install)
        except:
            if self.config.verbose:
-               utils.header("Trying %(yum_install)s" % locals()) 
-           (stdout, stderr) = utils.popen(yum_install)
+               utils.header("Trying %(yum_install)s" % locals())
+           (status, output) = plc.commands(download_cmd) 
+           (status, output) = plc.commands(yum_install)
 
-       if self.config.verbose:
-           utils.header("\n".join(stdout))
-       
        return 1
 
 if __name__ == '__main__':
index a514ed4..635a5c0 100644 (file)
@@ -4,24 +4,30 @@ import traceback
 import sys
 from Test import Test
 from qa import utils
+from qa.PLCs import PLC, PLCs
 
 class plc_start(Test):
     """
     Starts the myplc service
     """
 
-    def call(self):
-       
-       command = "/sbin/service plc start "
+    def call(self, plc_name = None):
 
+       # Get plc configuration from config
+       plc = PLC(self.config)
+       plcs = getattr(self.config, 'plcs', [])
+       for p in plcs:
+           if p['name'] in [plc_name]:
+               plc.update(p)   
+               
+       command = "/sbin/service plc start "
        if self.config.verbose:
            utils.header(command)       
+       (status, output) = plc.commands(command)
 
-       (stdout, stderr) = utils.popen(command)
-       
        if self.config.verbose:
-            utils.header("".join(stdout))
-         
+           utils.header(output)
+       
        return 1
 
 if __name__ == '__main__':
index 58f20bf..ff5bb9c 100644 (file)
@@ -4,23 +4,30 @@ import os, sys
 import traceback
 from Test import Test
 from qa import utils
+from qa.PLCs import PLC, PLCs
 
 class plc_stop(Test):
     """
     Installs a myplc
     """
 
-    def call(self):
-        
-       command = " /sbin/service plc stop "
+    def call(self, plc_name):
+       
+        # Get plc qa config
+        plc = PLC(self.config)
+        plcs = getattr(self.config, 'plcs', [])
+        for p in plcs:
+            if p['name'] in [plc_name]:
+                plc.update(p)
 
+       command = " /sbin/service plc stop "
        if self.config.verbose:
            utils.header(command)
        
-       (stdout, stderr) = utils.popen(command)
+       (status, output) = plc.commands(command)
 
        if self.config.verbose:
-           utils.header("\n".join(stdout))
+           utils.header(output)
 
        return 1
 
index 6860d9e..6d8c161 100644 (file)
@@ -10,22 +10,27 @@ class plc_uninstall(Test):
     Completely removes the installed myplc
     """
 
-    def call(self, remove_all = False):
+    def call(self, plc_name = None, remove_all = False):
+
+       # Get plc configuration from config
+        plc = PLC(self.config)
+        plcs = getattr(self.config, 'plcs', [])
+        for p in plcs:
+            if p['name'] in [plc_name]:
+                plc.update(p)
        
-       command = "/sbin/service plc safestop; rpm -e myplc " 
+       command = "/sbin/service plc safestop && rpm -e myplc " 
        if remove_all:
            command += " && rm -rf /plc/data" 
 
        if self.config.verbose:
             utils.header("Removing myplc")
-
-       (stdout, stderr) = utils.popen(command)
-       if self.config.verbose:
-           utils.header("\n".join(stdout))
+           utils.header("\n".join(command))
+       
+       (status, output) = plc.commands(command)
                
-       (stdout, stderr) = utils.popen(command)
        if self.config.verbose:
-           utiils.header("\n".join(stdout))
+           utiils.header("\n".join(output))
        
        return 1