oops
[tests.git] / qaapi / qa / Nodes.py
1 import utils
2 import os
3 import re
4 import time
5 from time import sleep
6 from Remote import Remote, VRemote
7 from Table import Table
8 from logger import Logfile
9
10
11 class Node(dict, VRemote):
12
13     fields = {
14         'plcs': ['TestPLC'],
15         'hostname': None,                             # Node Hostname
16         'host': 'localhost',                          # host where node lives
17         'redir_ssh_port': '51022',                    # Port on host where ssh is redirected to virtual node
18         'vserver': None,                              # vserver where this node lives
19         'type': 'vm',                                 # type of node
20         'model': '/minhw',
21         'nodegroups': [],
22         'nodenetworks': [],                           # node networks
23         'homedir': '/var/VirtualMachines/',
24         'rootkey': '/etc/planetlab/root_ssh_key.rsa', # path to root ssh key
25         'host_rootkey': None,                         # path to host root ssh key
26         'tests_dir': '/usr/share/tests/',
27         'tests': []                                   # which test to run. None or empty list means run all             
28         }
29         
30     
31     def __init__(self, config, fields = {}):
32
33         # XX Filter out fields not specified in fields
34         dict.__init__(self, self.fields)
35         
36         # Merge defined fields with defaults
37         self.update(fields)
38         self.config = config
39         self.__init_logfile__()
40         
41     get_host_command = Remote.get_remote_command
42     get_host_scp_command = Remote.get_scp_command
43
44     def __init_logfile__(self, filename = None):
45         if not filename:
46             filename = '%s/%s.log' % (self.config.logdir, self['hostname'])
47         self.logfile = Logfile(filename)
48
49     def rotate_logfile(self):
50         if os.path.isfile(self.logfile.filename):
51             (status, output) = utils.commands("ls %s*" % self.logfile.filename)
52             files = output.split("\n")
53             files.sort()
54             lastfile = files[-1:][0]
55             index = lastfile.split(self.logfile.filename)[1].replace(".", "")                                   
56             if not index:
57                 index = "1"
58             else:
59                 index = str(int(index) + 1)
60             utils.commands("mv %s %s.%s" % (self.logfile.filename, self.logfile.filename, index))
61                 
62     def get_host_ip(self):
63         self.__init_logfile__()
64
65         # Used to get ip of this nodes host
66         ip_command = "/sbin/ifconfig eth0 | grep -v inet6 | grep inet | awk '{print$2;}'" 
67         (status, output) = self.host_commands(ip_command)            
68         ip = re.findall(r'[0-9\.]+', output)[0] 
69         return ip
70
71     def is_ready(self, timeout=30):
72         # Node is considered ready when Node Manager has started avuseradd processes have stopped
73         log = self.config.logfile 
74         class test:
75             def __init__(self, name, description, system, cmd, check, inverse = False, logfile = log):
76                 self.system = system
77                 self.cmd = cmd
78                 self.check = check
79                 self.name = name
80                 self.description = description
81                 self.inverse = inverse
82                 self.logfile = logfile
83  
84             def run(self, logfile, verbose = True):
85                 if verbose:
86                     utils.header(self.description, logfile =  self.logfile)     
87                 (status, output) = self.system(self.cmd)
88                 if self.inverse and output.find(self.check) == -1:
89                     if verbose: utils.header("%s Passed Test" % self.name, logfile = self.logfile)
90                     return True
91                 elif not self.inverse and output and output.find(self.check)  -1:               
92                     if verbose: utils.header("%s Passed Test" % self.name, logfile = self.logfile)
93                     return True
94                 
95                 if verbose: utils.header("%s Failed Test" % self.name, logfile = self.logfile)
96                 return False
97
98         ready = False
99         start_time = time.time()
100         end_time = start_time + 60 * timeout
101         vcheck_cmd = "ps -elfy | grep vuseradd | grep -v grep"  
102         grep_cmd = "grep 'Starting Node Manager' %s" % self.logfile.filename
103         tests = {
104         '1':  test("NodeManager", "Checking if NodeManager has started", utils.commands, grep_cmd, "OK", logfile = self.config.logfile),
105         '2':  test("vuseradd", "Checking if vuseradd is done", self.commands, vcheck_cmd, "vuseradd", True, logfile = self.config.logfile)      
106         }
107         
108         while time.time() < end_time and ready == False:
109             # Run tests in order
110             steps = tests.keys()
111             steps.sort()
112             results = {}
113             for step in steps:
114                 test = tests[step]
115                 results[step] = result = test.run(self.config.verbose)
116                 if not result: break
117                                                 
118             # Check results. We are ready if all passed                 
119             if not set(results.values()).intersection([False, None]):
120                 utils.header("%s is ready" % (self['hostname'])) 
121                 ready = True
122             else:
123                 if self.config.verbose:
124                     utils.header("%s not ready. Waiting 30 seconds. %s seconds left" % \
125                                  (self['hostname'], int(end_time - time.time())) )
126                 time.sleep(30)                          
127
128         return ready  
129
130     def download_testscripts(self):
131         node_tests_dir = self['tests_dir']
132         self.commands("mkdir %(node_tests_dir)s" % locals(), fatal = False) 
133         (archive_filename, archive_path) = self.config.archive_node_tests()
134         self.scp_to(archive_path, node_tests_dir)   
135         
136         # Extract tests archive
137         tarx_cmd = "cd %(node_tests_dir)s && tar -xzm -f %(archive_filename)s" % locals()
138         print >> self.logfile, tarx_cmd
139         self.popen(tarx_cmd)    
140
141         # Make tests executable
142         # XX Should find a better way to do this
143         chmod_cmd = "cd %s/node && chmod -R 755 * " % (node_tests_dir)
144         print >> self.logfile, chmod_cmd
145         self.popen(chmod_cmd)
146
147     def slice_commands(self, command, slice, key = None):
148         if key is None: 
149             print self.config.slices
150             # get a valid key
151             persons = self.config.slices[slice]['persons']
152             if not persons: raise Exception 
153             name, domain = persons[0].split('@')
154             key = "/%s/%s" % (self.config.KEYS_PATH,  name)
155         
156         return VRemote.slice_commands(command, slice, key, False)               
157            
158     def get_logs(self, files = None):
159         
160         hostname = self['hostname']
161         logs_dir = '/var/log/'
162         dest = "%s/%s-var.log/" % (self.logfile.dir, hostname)  
163         try: os.mkdir(dest)
164         except: pass
165         #utils.commands('rm -Rf %(dest)s/*' % locals()) 
166         self.scp_from(logs_dir, dest, recursive = True)
167
168  
169 class Nodes(Table):
170
171     def __init__(self, config, nodes):
172         nodelist = [Node(config, node) for node in nodes]
173         Table.__init__(self, nodelist)
174         self.config = config
175