-added methods to help scp files to / from Remotes
[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 get_host_ip(self):
46         self.__init_logfile__()
47
48         # Used to get ip of this nodes host
49         ip_command = "/sbin/ifconfig eth0 | grep -v inet6 | grep inet | awk '{print$2;}'" 
50         (status, output) = self.host_commands(ip_command)            
51         ip = re.findall(r'[0-9\.]+', output)[0] 
52         return ip
53
54     def get_remote_command(self, command, user = 'root', key = None):
55         if key is None and 'rootkey' in self:
56             key = self['rootkey']
57         options = " -q "
58         options += " -o StrictHostKeyChecking=no "
59         if key:
60             options += " -i %(key)s" % locals()
61         host = self['hostname']
62         if 'type' in self and self['type'] in ['vm']:
63             if 'redir_ssh_port' in self and self['redir_ssh_port']:
64                 options += " -p %s " % self['redir_ssh_port']
65             host = self.get_host_ip() 
66         command = "ssh %(options)s %(user)s@%(host)s \'%(command)s\'" % locals()
67         return self.get_host_command(command)
68  
69     def get_scp_command(self, localfile, remotefile, direction, recursive = False, user = 'root', key = None):
70         # scp options
71         options = " -q "
72         options += " -o StrictHostKeyChecking=no "
73         if recursive:
74             options += " -r "   
75         if key:
76             options += " -i %(key)s "% locals()
77         elif self['rootkey']:
78             options += " -i %s " % self['rootkey']
79         
80         # Are we copying to a real node or a virtual node hosted
81         # at another machine 
82         host = self['hostname']
83         if 'type' in self and self['type'] in ['vm']:
84             if 'redir_ssh_port' in self and self['redir_ssh_port']:
85                 options += " -p %s " % self['redir_ssh_port']
86             host = self.get_host_ip()
87
88         if direction in ['to']:
89             command = "scp %(options)s %(localfile)s %(user)s@%(host)s:/%(remotefile)s" % locals()
90         elif direction in ['from']:
91             command = "scp %(options)s %(user)s$%(host)s:/%(remotefile)s %(localfile)s" % locals() 
92         else:
93             raise Error, "Invalid direction, must be 'to' or 'from'."
94         return command      
95
96     # Host remote commands
97     def host_popen(self, command, fatal = True):
98         command = self.get_host_command(command)
99         return utils.popen(command, fatal, self.config.verbose)
100
101     def host_popen3(self, command):
102         command = self.get_host_command(command)
103         return utils.popen3(command, self.config.verbose)
104
105     def host_commands(self, command, fatal = True):
106         command = self.get_host_command(command)
107         return utils.commands(command, fatal, self.config.verbose)    
108
109     # Slice remote commands
110     def slice_popen(self, command, user = 'root', key = None, fatal = True):
111         command = self.get_remote_command(command, user, key)
112         return utils.popen(command, fatal)
113
114     def slice_popen3(self, command, user = 'root', key = None, fatal = True):
115         command = self.get_remote_command(command, user, key)
116         return utils.popen3(command, fatal)
117
118     def slice_commands(self, command, user = 'root', key = None, fatal = True):
119         command = self.get_remote_command(command, user, key)
120         return utils.commands(command, fatal)
121
122     # Host scp 
123     def scp_to_host(self, localfile, remotefile, recursive = False):
124         command = self.get_host_scp_command(localfile, remotefile, 'to', recursive)
125         return utils.commands(command)
126
127     def scp_from_host(self, localfile, remotefile, recursive = False):
128         command = self.get_host_scp_command(localfile, remotefile, 'from', recursive)
129         return utils.commands(command)
130
131     # Node scp
132     def scp_to(self, localfile, remotefile, recursive = False, user = 'root', key = None):
133         # if node is vm, we must scp file(s) to host machine first
134         # then run scp from there
135         if 'type' in self and self['type'] in ['vm']:
136             fileparts = localfile.split(os.sep)
137             filename = fileparts[-1:][0]
138             tempfile = '/tmp/%(filename)s' % locals()
139             self.scp_to_host(localfile, tempfile, recursive)
140             command = self.get_scp_command(tempfile, remotefile, 'to', recursive, user, key) 
141             return self.host_commands(command)
142         else:
143                 
144             command = self.get_scp_command(localfile, remotefile, 'to', recursive, user, key) 
145             return utils.commands(command)      
146
147     def scp_from(self, localfile, remotefile, recursive = False, user = 'root', key = None):
148         # if node is vm, we must scp file(s) onto host machine first
149         # then run scp from there
150         if 'type' in self and self['type'] in ['vm']:
151             fileparts = remotefile.split(os.sep)
152             filename = fileparts[-1:]
153             tempfile = '/tmp/%(filename)s' % locals()
154             self.scp_from_host(remotefile, tempfile, recursive)
155             command = self.get_scp_command(localfile, tempfile, 'from', recursive, user, key)  
156             return self.host_commands(command)
157         else:
158
159             command = self.get_scp_command(localfile, remotefile, 'from', recursive, user, key) 
160             return utils.commands(command)      
161
162     def is_ready(self, timeout=8):
163         # Node is considered ready when vuseradd processes have stopped 
164         ready = False
165         start_time = time.time()
166         end_time = start_time + 60 * timeout
167         while time.time() < end_time and ready == False:
168             command = "ps -elfy | grep vuseradd | grep -v grep" 
169             (output, errors) = self.popen(command, False) 
170             if output and output.find('vuseradd') or errors:
171                 if self.config.verbose:
172                     utils.header('%s is not ready. waiting 30 seconds' %  self['hostname'])
173                 sleep(20)
174             else:
175                 ready = True
176                 if self.config.verbose:
177                     utils.header('%s is ready' % self['hostname'])
178
179         return ready  
180          
181 class Nodes(list, Table):
182
183     def __init__(self, config, nodes):
184         nodelist = [Node(config, node) for node in nodes]
185         list.__init__(self, nodelist)
186         self.config = config
187