adding TestScripts class
[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
7 from Table import Table
8 from logger import Logfile
9
10
11 class Node(dict, Remote):
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         'nodenetworks': [],                           # node networks
22         'homedir': '/var/VirtualMachines/',
23         'rootkey': '/etc/planetlab/root_ssh_key.rsa', # path to root ssh key
24         'host_rootkey': None
25         }
26
27     def __init__(self, config, fields = {}):
28
29         # XX Filter out fields not specified in fields
30         dict.__init__(self, self.fields)
31         
32         # Merge defined fields with defaults
33         self.update(fields)
34         self.config = config
35         self.__init_logfile__()
36         
37     get_host_command = Remote.get_remote_command
38     get_host_scp_command = Remote.get_scp_command
39
40     def __init_logfile__(self, filename = None):
41         if not filename:
42             filename = '/var/log/%s.log' % self['hostname']
43         self.logfile = Logfile(filename)
44
45     def rotate_logfile(self):
46         if os.path.isfile(self.logfile.filename):
47             (status, output) = utils.commands("ls %s*" % self.logfile.filename)
48             files = output.split("\n")
49             files.sort()
50             lastfile = files[-1:][0]
51             index = lastfile.split(self.logfile.filename)[1].replace(".", "")                                   
52             if not index:
53                 index = "1"
54             else:
55                 index = str(int(index) + 1)
56             utils.commands("mv %s %s.%s" % (self.logfile.filename, self.logfile.filename, index))
57                 
58     def get_host_ip(self):
59         self.__init_logfile__()
60
61         # Used to get ip of this nodes host
62         ip_command = "/sbin/ifconfig eth0 | grep -v inet6 | grep inet | awk '{print$2;}'" 
63         (status, output) = self.host_commands(ip_command)            
64         ip = re.findall(r'[0-9\.]+', output)[0] 
65         return ip
66
67     def get_remote_command(self, command, user = 'root', key = None):
68         if key is None and 'rootkey' in self:
69             key = self['rootkey']
70         options = ""
71         options += " -o StrictHostKeyChecking=no "
72         if key:
73             options += " -i %(key)s" % locals()
74         host = self['hostname']
75         if 'type' in self and self['type'] in ['vm']:
76             if 'redir_ssh_port' in self and self['redir_ssh_port']:
77                 options += " -p %s " % self['redir_ssh_port']
78             host = self.get_host_ip() 
79         command = "ssh %(options)s %(user)s@%(host)s \'%(command)s\'" % locals()
80         return self.get_host_command(command)
81  
82     def get_scp_command(self, localfile, remotefile, direction, recursive = False, user = 'root', key = None):
83         # scp options
84         options = ""
85         options += " -o StrictHostKeyChecking=no "
86         if recursive:
87             options += " -r "   
88         if key:
89             options += " -i %(key)s "% locals()
90         elif self['rootkey']:
91             options += " -i %s " % self['rootkey']
92         
93         # Are we copying to a real node or a virtual node hosted
94         # at another machine 
95         host = self['hostname']
96         if 'type' in self and self['type'] in ['vm']:
97             if 'redir_ssh_port' in self and self['redir_ssh_port']:
98                 options += " -p %s " % self['redir_ssh_port']
99             host = self.get_host_ip()
100
101         if direction in ['to']:
102             command = "scp %(options)s %(localfile)s %(user)s@%(host)s:/%(remotefile)s" % locals()
103         elif direction in ['from']:
104             command = "scp %(options)s %(user)s$%(host)s:/%(remotefile)s %(localfile)s" % locals() 
105         else:
106             raise Error, "Invalid direction, must be 'to' or 'from'."
107         return command      
108
109     # Host remote commands
110     def host_popen(self, command, fatal = True):
111         command = self.get_host_command(command)
112         return utils.popen(command, fatal, self.config.verbose)
113
114     def host_popen3(self, command):
115         command = self.get_host_command(command)
116         return utils.popen3(command, self.config.verbose)
117
118     def host_commands(self, command, fatal = True):
119         command = self.get_host_command(command)
120         return utils.commands(command, fatal, self.config.verbose)    
121
122     # Slice remote commands
123     def slice_popen(self, command, user = 'root', key = None, fatal = True):
124         command = self.get_remote_command(command, user, key)
125         return utils.popen(command, fatal)
126
127     def slice_popen3(self, command, user = 'root', key = None, fatal = True):
128         command = self.get_remote_command(command, user, key)
129         return utils.popen3(command, fatal)
130
131     def slice_commands(self, command, user = 'root', key = None, fatal = True):
132         command = self.get_remote_command(command, user, key)
133         return utils.commands(command, fatal)
134
135     # Host scp 
136     def scp_to_host(self, localfile, remotefile, recursive = False):
137         command = self.get_host_scp_command(localfile, remotefile, 'to', recursive)
138         return utils.commands(command)
139
140     def scp_from_host(self, localfile, remotefile, recursive = False):
141         command = self.get_host_scp_command(localfile, remotefile, 'from', recursive)
142         return utils.commands(command)
143
144     # Node scp
145     def scp_to(self, localfile, remotefile, recursive = False, user = 'root', key = None):
146         # if node is vm, we must scp file(s) to host machine first
147         # then run scp from there
148         if 'type' in self and self['type'] in ['vm']:
149             fileparts = localfile.split(os.sep)
150             filename = fileparts[-1:][0]
151             tempfile = '/tmp/%(filename)s' % locals()
152             self.scp_to_host(localfile, tempfile, recursive)
153             command = self.get_scp_command(tempfile, remotefile, 'to', recursive, user, key) 
154             return self.host_commands(command)
155         else:
156                 
157             command = self.get_scp_command(localfile, remotefile, 'to', recursive, user, key) 
158             return utils.commands(command)      
159
160     def scp_from(self, localfile, remotefile, recursive = False, user = 'root', key = None):
161         # if node is vm, we must scp file(s) onto host machine first
162         # then run scp from there
163         if 'type' in self and self['type'] in ['vm']:
164             fileparts = remotefile.split(os.sep)
165             filename = fileparts[-1:]
166             tempfile = '/tmp/%(filename)s' % locals()
167             self.scp_from_host(remotefile, tempfile, recursive)
168             command = self.get_scp_command(localfile, tempfile, 'from', recursive, user, key)  
169             return self.host_commands(command)
170         else:
171
172             command = self.get_scp_command(localfile, remotefile, 'from', recursive, user, key) 
173             return utils.commands(command)      
174
175     def is_ready(self, timeout=10):
176         # Node is considered ready when Node Manager has started avuseradd processes have stopped 
177         class test:
178             def __init__(self, name, description, system, cmd, check, inverse = False):
179                 self.system = system
180                 self.cmd = cmd
181                 self.check = check
182                 self.name = name
183                 self.description = description
184                 self.inverse = inverse
185  
186             def run(self, verbose = True):
187                 if verbose:
188                     utils.header(self.description)      
189                 (status, output) = self.system(self.cmd)
190                 if self.inverse and output.find(self.check) == -1:
191                     if verbose: utils.header("%s Passed Test" % self.name)
192                     return True
193                 elif not self.inverse and output and output.find(self.check)  -1:               
194                     if verbose: utils.header("%s Passed Test" % self.name)
195                     return True
196                 
197                 if verbose: utils.header("%s Failed Test" % self.name)
198                 return False
199
200         ready = False
201         start_time = time.time()
202         end_time = start_time + 60 * timeout
203         vcheck_cmd = "ps -elfy | grep vuseradd | grep -v grep"  
204         grep_cmd = "grep 'Starting Node Manager' %s" % self.logfile.filename
205         tests = {
206         '1':  test("NodeManager", "Checking if NodeManager has started", utils.commands, grep_cmd, "OK"),
207         '2':  test("vuseradd", "Checking if vuseradd is done", self.commands, vcheck_cmd, "vuseradd", True)      
208         }
209         
210         while time.time() < end_time and ready == False:
211             # Run tests in order
212             steps = tests.keys()
213             steps.sort()
214             results = {}
215             for step in steps:
216                 test = tests[step]
217                 results[step] = result = test.run(self.config.verbose)
218                 if not result: break
219                                                 
220             # Check results. We are ready if all passed                 
221             if not set(results.values()).intersection([False, None]):
222                 ready = True
223             else:
224                 if self.config.verbose:
225                     utils.header("%s not ready. Waiting 30 seconds. %s seconds left" % \
226                                  (self['hostname'], int(end_time - time.time())) )
227                 time.sleep(30)                          
228
229         return ready  
230          
231 class Nodes(list, Table):
232
233     def __init__(self, config, nodes):
234         nodelist = [Node(config, node) for node in nodes]
235         list.__init__(self, nodelist)
236         self.config = config
237