import utils
import os
+import re
+import time
+from time import sleep
from Remote import Remote
from Table import Table
+from logger import Logfile
class Node(dict, Remote):
fields = {
'plcs': ['TestPLC'],
- 'hostname': None, # Node Hostname
- 'host': 'localhost', # host where node lives
- 'redir_port': None, # Port on host where ssh is redirected to virtual node
- 'vserver': None, # vserver where this node lives
- 'type': 'vm', # type of node
+ 'hostname': None, # Node Hostname
+ 'host': 'localhost', # host where node lives
+ 'redir_ssh_port': '51022', # Port on host where ssh is redirected to virtual node
+ 'vserver': None, # vserver where this node lives
+ 'type': 'vm', # type of node
'model': '/minhw',
- 'nodenetworks': [], # node networks
+ 'nodenetworks': [], # node networks
'homedir': '/var/VirtualMachines/',
- 'rootkey': None # path to root ssh key
+ 'rootkey': '/etc/planetlab/root_ssh_key.rsa', # path to root ssh key
+ 'host_rootkey': None
}
def __init__(self, config, fields = {}):
# Merge defined fields with defaults
self.update(fields)
self.config = config
+ self.__init_logfile__()
+
+ get_host_command = Remote.get_remote_command
+ get_host_scp_command = Remote.get_scp_command
+
+ def __init_logfile__(self, filename = None):
+ if not filename:
+ filename = '/var/log/%s.log' % self['hostname']
+ self.logfile = Logfile(filename)
+
+ def rotate_logfile(self):
+ if os.path.isfile(self.logfile.filename):
+ (status, output) = utils.commands("ls %s*" % self.logfile.filename)
+ files = output.split("\n")
+ files.sort()
+ lastfile = files[-1:][0]
+ index = lastfile.split(self.logfile.filename)[1].replace(".", "")
+ if not index:
+ index = "1"
+ else:
+ index = str(int(index) + 1)
+ utils.commands("mv %s %s.%s" % (self.logfile.filename, self.logfile.filename, index))
+
+ def get_host_ip(self):
+ self.__init_logfile__()
+
+ # Used to get ip of this nodes host
+ ip_command = "/sbin/ifconfig eth0 | grep -v inet6 | grep inet | awk '{print$2;}'"
+ (status, output) = self.host_commands(ip_command)
+ ip = re.findall(r'[0-9\.]+', output)[0]
+ return ip
+
+ def get_remote_command(self, command, user = 'root', key = None):
+ if key is None and 'rootkey' in self:
+ key = self['rootkey']
+ options = ""
+ options += " -o StrictHostKeyChecking=no "
+ if key:
+ options += " -i %(key)s" % locals()
+ host = self['hostname']
+ if 'type' in self and self['type'] in ['vm']:
+ if 'redir_ssh_port' in self and self['redir_ssh_port']:
+ options += " -p %s " % self['redir_ssh_port']
+ host = self.get_host_ip()
+ command = "ssh %(options)s %(user)s@%(host)s \'%(command)s\'" % locals()
+ return self.get_host_command(command)
+
+ def get_scp_command(self, localfile, remotefile, direction, recursive = False, user = 'root', key = None):
+ # scp options
+ options = ""
+ options += " -o StrictHostKeyChecking=no "
+ if recursive:
+ options += " -r "
+ if key:
+ options += " -i %(key)s "% locals()
+ elif self['rootkey']:
+ options += " -i %s " % self['rootkey']
+
+ # Are we copying to a real node or a virtual node hosted
+ # at another machine
+ host = self['hostname']
+ if 'type' in self and self['type'] in ['vm']:
+ if 'redir_ssh_port' in self and self['redir_ssh_port']:
+ options += " -p %s " % self['redir_ssh_port']
+ host = self.get_host_ip()
+
+ if direction in ['to']:
+ command = "scp %(options)s %(localfile)s %(user)s@%(host)s:/%(remotefile)s" % locals()
+ elif direction in ['from']:
+ command = "scp %(options)s %(user)s$%(host)s:/%(remotefile)s %(localfile)s" % locals()
+ else:
+ raise Error, "Invalid direction, must be 'to' or 'from'."
+ return command
+ # Host remote commands
def host_popen(self, command, fatal = True):
command = self.get_host_command(command)
return utils.popen(command, fatal, self.config.verbose)
def host_commands(self, command, fatal = True):
command = self.get_host_command(command)
return utils.commands(command, fatal, self.config.verbose)
+
+ # Slice remote commands
+ def slice_popen(self, command, user = 'root', key = None, fatal = True):
+ command = self.get_remote_command(command, user, key)
+ return utils.popen(command, fatal)
+
+ def slice_popen3(self, command, user = 'root', key = None, fatal = True):
+ command = self.get_remote_command(command, user, key)
+ return utils.popen3(command, fatal)
+
+ def slice_commands(self, command, user = 'root', key = None, fatal = True):
+ command = self.get_remote_command(command, user, key)
+ return utils.commands(command, fatal)
+
+ # Host scp
+ def scp_to_host(self, localfile, remotefile, recursive = False):
+ command = self.get_host_scp_command(localfile, remotefile, 'to', recursive)
+ return utils.commands(command)
+
+ def scp_from_host(self, localfile, remotefile, recursive = False):
+ command = self.get_host_scp_command(localfile, remotefile, 'from', recursive)
+ return utils.commands(command)
+
+ # Node scp
+ def scp_to(self, localfile, remotefile, recursive = False, user = 'root', key = None):
+ # if node is vm, we must scp file(s) to host machine first
+ # then run scp from there
+ if 'type' in self and self['type'] in ['vm']:
+ fileparts = localfile.split(os.sep)
+ filename = fileparts[-1:][0]
+ tempfile = '/tmp/%(filename)s' % locals()
+ self.scp_to_host(localfile, tempfile, recursive)
+ command = self.get_scp_command(tempfile, remotefile, 'to', recursive, user, key)
+ return self.host_commands(command)
+ else:
+
+ command = self.get_scp_command(localfile, remotefile, 'to', recursive, user, key)
+ return utils.commands(command)
+
+ def scp_from(self, localfile, remotefile, recursive = False, user = 'root', key = None):
+ # if node is vm, we must scp file(s) onto host machine first
+ # then run scp from there
+ if 'type' in self and self['type'] in ['vm']:
+ fileparts = remotefile.split(os.sep)
+ filename = fileparts[-1:]
+ tempfile = '/tmp/%(filename)s' % locals()
+ self.scp_from_host(remotefile, tempfile, recursive)
+ command = self.get_scp_command(localfile, tempfile, 'from', recursive, user, key)
+ return self.host_commands(command)
+ else:
+
+ command = self.get_scp_command(localfile, remotefile, 'from', recursive, user, key)
+ return utils.commands(command)
+
+ def is_ready(self, timeout=10):
+ # Node is considered ready when Node Manager has started avuseradd processes have stopped
+ class test:
+ def __init__(self, name, description, system, cmd, check, inverse = False):
+ self.system = system
+ self.cmd = cmd
+ self.check = check
+ self.name = name
+ self.description = description
+ self.inverse = inverse
+
+ def run(self, verbose = True):
+ if verbose:
+ utils.header(self.description)
+ (status, output) = self.system(self.cmd)
+ if self.inverse and output.find(self.check) == -1:
+ if verbose: utils.header("%s Passed Test" % self.name)
+ return True
+ elif not self.inverse and output and output.find(self.check) -1:
+ if verbose: utils.header("%s Passed Test" % self.name)
+ return True
+
+ if verbose: utils.header("%s Failed Test" % self.name)
+ return False
+
+ ready = False
+ start_time = time.time()
+ end_time = start_time + 60 * timeout
+ vcheck_cmd = "ps -elfy | grep vuseradd | grep -v grep"
+ grep_cmd = "grep 'Starting Node Manager' %s" % self.logfile.filename
+ tests = {
+ '1': test("NodeManager", "Checking if NodeManager has started", utils.commands, grep_cmd, "OK"),
+ '2': test("vuseradd", "Checking if vuseradd is done", self.commands, vcheck_cmd, "vuseradd", True)
+ }
+
+ while time.time() < end_time and ready == False:
+ # Run tests in order
+ steps = tests.keys()
+ steps.sort()
+ results = {}
+ for step in steps:
+ test = tests[step]
+ results[step] = result = test.run(self.config.verbose)
+ if not result: break
+
+ # Check results. We are ready if all passed
+ if not set(results.values()).intersection([False, None]):
+ ready = True
+ else:
+ if self.config.verbose:
+ utils.header("%s not ready. Waiting 30 seconds. %s seconds left" % \
+ (self['hostname'], int(end_time - time.time())) )
+ time.sleep(30)
+
+ return ready
class Nodes(list, Table):