class ConsoleRunner(object): def __init__(self, cmd): self.__cmd = cmd self.__pmgr = PlaybookMgr(cmd['cluster_name']) def run(self): cmdstr = '' if self.__cmd['command'] == 'gettablelocks': cmdstr = cmdstr + '{{ infinidb_installdir }}/bin/viewtablelock' else: cmdstr = cmdstr + '{{ infinidb_installdir }}/bin/calpontConsole %s' % self.__cmd[ 'command'] try: reslt = self.__pmgr.run_module('infinidb', 'pm1', 'command', cmdstr, sudo=False) except errormsg.ErrorMsg, exc: replydict = { "cluster_name": self.__cmd['cluster_name'], "command": self.__cmd['command'], "console_host": '', "rc": exc['rc'], "stdout": exc['stdout'], "stderr": exc['stderr'], "msg": exc['msg'], "ansible_cmd": exc['cmd'] } return commandreply.CommandReply_from_dict(replydict) host = reslt['contacted'].keys()[0] replydict = { "cluster_name": self.__cmd['cluster_name'], "command": self.__cmd['command'], "console_host": host, "rc": reslt['contacted'][host]['rc'], "stdout": reslt['contacted'][host]['stdout'], "stderr": reslt['contacted'][host]['stderr'] } try: fn = getattr(console, self.__cmd['command']) replydict['results'] = fn(reslt['contacted'][host]['stdout']) except: pass return commandreply.CommandReply_from_dict(replydict)
def testRun(self): p = PlaybookMgr( 'testbook' ) p.write_inventory( 'testinv', { 'all' : ['localhost'] } ) f = open( props['emtools.test.sshkeyfile'] ) keytext = ''.join(f.readlines()) p.config_ssh( props['emtools.test.user'], keytext ) rc = p.run_module('testinv', 'all', 'setup', sudo=False) self.assertTrue( rc['contacted'].has_key( 'localhost' )) rc, results, out, err = p.run_playbook('smokecheck.yml', 'testinv') self.assertEquals(rc, 0) shutil.rmtree( p.get_rootdir() )
class ConsoleRunner(object): def __init__(self, cmd): self.__cmd = cmd self.__pmgr = PlaybookMgr( cmd['cluster_name'] ) def run(self): cmdstr = '' if self.__cmd['command'] == 'gettablelocks': cmdstr = cmdstr + '{{ infinidb_installdir }}/bin/viewtablelock' else: cmdstr = cmdstr + '{{ infinidb_installdir }}/bin/calpontConsole %s' % self.__cmd['command'] try: reslt = self.__pmgr.run_module( 'infinidb', 'pm1', 'command', cmdstr, sudo=False) except errormsg.ErrorMsg, exc: replydict = { "cluster_name" : self.__cmd['cluster_name'], "command" : self.__cmd['command'], "console_host" : '', "rc" : exc['rc'], "stdout" : exc['stdout'], "stderr" : exc['stderr'], "msg" : exc['msg'], "ansible_cmd" : exc['cmd'] } return commandreply.CommandReply_from_dict( replydict ) host = reslt['contacted'].keys()[0] replydict = { "cluster_name" : self.__cmd['cluster_name'], "command" : self.__cmd['command'], "console_host" : host, "rc" : reslt['contacted'][host]['rc'], "stdout" : reslt['contacted'][host]['stdout'], "stderr" : reslt['contacted'][host]['stderr'] } try: fn = getattr(console,self.__cmd['command']) replydict['results'] = fn(reslt['contacted'][host]['stdout']) except: pass return commandreply.CommandReply_from_dict( replydict )
# todo - handle case where use only specifies one machine of infinidb cluster # run site_facts first, then check to make sure any infinidb machine is in the # inventory. Then rerun setup & site_facts, etc. p.write_inventory('default', {'all': hosts}) cluster_valid = True cluster_dist = '' cluster_reason = '' valid_instances = 0 cluster_gluster = '' cluster_hadoop = '' cluster_infinidb = '' infinidb_host = '' instance_info = {} reslt = p.run_module('default', 'all', 'setup') role_info = {} for h in reslt['dark']: instance_info[h] = dict(valid=False) for h in reslt['contacted']: host_facts = reslt['contacted'][h]['ansible_facts'] if not cluster_dist: cluster_dist = host_facts['ansible_distribution'] elif cluster_dist != host_facts['ansible_distribution']: cluster_valid = False cluster_reason = 'Multiple distributions: %s and %s' % ( cluster_dist, host_facts['ansible_distribution']) instance_info[h] = dict( valid=True, ip_address=host_facts['ansible_default_ipv4']['address'])
class FactGetter(object): def __init__(self, req): self.__req = req self.__pmgr = PlaybookMgr( req['cluster_name'] ) # TODO - add support for ssh_pass ssh_port = None if req.has_key('ssh_port'): ssh_port = req['ssh_port'] if req.has_key('ssh_key'): self.__pmgr.config_ssh( req['ssh_user'], req['ssh_key'], ssh_port=ssh_port ) else: self.__pmgr.config_ssh( req['ssh_user'], ssh_pass=req['ssh_pass'], ssh_port=ssh_port ) self.__pmgr.write_inventory( 'default', { 'all' : req['hostnames'] }) self.__role_info = {} self.__instance_info = {} self.__parsed_idbxml = False self.__user = req['ssh_user'] def write_envsetup(self): fname = '%s/env-setup' % self.__pmgr.get_rootdir() f = open( fname, 'w' ) f.write('#!/bin/bash\n') envvars = ['PYTHONPATH','ANSIBLE_LIBRARY','INFINIDB_EM_TOOLS_HOME'] for var in envvars: if os.environ.has_key(var): f.write('export %s=%s\n' % (var, os.environ[var])) def run_host(self, hostname): # debug only #print 'Running host %s' % hostname reslt = self.__pmgr.run_module( 'default', hostname, 'setup', no_raise=True, sudo=False ) fqdn = '' for h in reslt['dark']: fqdn = h self.__instance_info[fqdn] = dict( valid=False, reason=reslt['dark'][h]['msg'] ) for h in reslt['contacted']: if reslt['contacted'][h].has_key('failed'): # module execution failed, we need to report the error self.__instance_info[h] = dict( valid=False, reason=reslt['contacted'][h]['msg'] ) elif reslt['contacted'][h].has_key('ansible_facts'): host_facts = reslt['contacted'][h]['ansible_facts'] fqdn = host_facts['ansible_fqdn'] # do a test here to make sure that the server running emtools # can resolve the FQDN that ansible found. This guards against # a local, unrouteable hostname. Note that we already know the # original IP was ok because ansible was able to contact the host try: # try a lookup host = socket.gethostbyname(fqdn) except: # this is bad - it means the hostname is non-routable from the server self.__instance_info[fqdn] = dict( valid=False, reason='non-routeable FQDN: %s' % h) continue # we made contact so let's run our site_facts module try: site_reslt = self.__pmgr.run_module( 'default', hostname, 'site_facts', sudo=False ) except errormsg.ErrorMsg, exc: self.__instance_info[h] = dict( valid=False, reason=exc['msg'] ) continue site_facts = site_reslt['contacted'][h]['ansible_facts'] self.__instance_info[fqdn] = dict() # this first group of checks will determine whether the node is valid from # an EM perspective self.__instance_info[fqdn]['homedir'] = site_facts['homedir'] self.__instance_info[fqdn]['python_version'] = host_facts['ansible_python_version'] self.__instance_info[fqdn]['sudo'] = site_facts['sudo'] valid = True if ( self.__instance_info[fqdn]['sudo'] and ( self.__instance_info[fqdn]['python_version'][0:3] == '2.6' or self.__instance_info[fqdn]['python_version'][0:3] == '2.7') ) else False self.__instance_info[fqdn]['valid'] = valid if not valid: reason = 'no posswardless sudo' if not self.__instance_info[fqdn]['sudo'] else 'unsupported python version' else: reason = '' self.__instance_info[fqdn]['reason'] = reason self.__instance_info[fqdn]['ip_address'] = host_facts['ansible_all_ipv4_addresses'][0] self.__instance_info[fqdn]['hostname'] = host_facts['ansible_hostname'] self.__instance_info[fqdn]['os_family'] = host_facts['ansible_distribution'] self.__instance_info[fqdn]['gluster_version'] = site_facts['gluster_version'] self.__instance_info[fqdn]['hadoop_version'] = site_facts['hadoop_version'] self.__instance_info[fqdn]['pdsh_version'] = site_facts['pdsh_version'] self.__instance_info[fqdn]['infinidb_version'] = site_facts['infinidb_version'] self.__instance_info[fqdn]['infinidb_installdir'] = site_facts['infinidb_installdir'] self.__instance_info[fqdn]['infinidb_user'] = site_facts['infinidb_user'] # ansible does not report ansible_processor_vcpus on Mac OS if host_facts.has_key('ansible_processor_vcpus'): self.__instance_info[fqdn]['processor_count'] = host_facts['ansible_processor_vcpus'] else: self.__instance_info[fqdn]['processor_count'] = host_facts['ansible_processor_cores'] self.__instance_info[fqdn]['memory_available'] = host_facts['ansible_memtotal_mb'] # ansible does not report ansible_swaptotal_mb on Mac OS if host_facts.has_key('ansible_swaptotal_mb'): self.__instance_info[fqdn]['swap_configured'] = host_facts['ansible_swaptotal_mb'] self.__instance_info[fqdn]['em_components'] = {} self.__instance_info[fqdn]['em_components']['collectd'] = site_facts['collectd_version'] self.__instance_info[fqdn]['em_components']['python-stack'] = site_facts['python-stack_version'] self.__instance_info[fqdn]['em_components']['graphite'] = site_facts['graphite_version'] self.__instance_info[fqdn]['em_components']['tools'] = site_facts['tools_version'] self.__instance_info[fqdn]['em_components']['oam-server'] = '' self.__instance_info[fqdn]['deployment_type'] = '' self.__instance_info[fqdn]['storage_type'] = '' self.__instance_info[fqdn]['system_name'] = '' self.__instance_info[fqdn]['port3306available'] = site_facts['port3306available'] else: # no clue what happened - didn't see Failed but no ansible facts, return the whole result in the reason field self.__instance_info[h] = dict( valid=False, reason='%s' % reslt['contacted'][h] ) if not self.__parsed_idbxml and self.__instance_info[fqdn]['valid'] and self.__instance_info[fqdn]['infinidb_version'] and self.__instance_info[fqdn]['sudo']: self.__parsed_idbxml = True # we found infinidb software. Run our getinfo playbook to retrieve Calpont.xml rc, results, out, err = self.__pmgr.run_playbook('getinfo.yml', 'default', host_subset=hostname) if rc == 0: xml = idbxml.IdbXml( '%s/cluster_files/Calpont.xml' % (self.__pmgr.get_rootdir()) ) for r in xml.get_all_roles(): # eoch role here has role= and ip_address= but we need to put # map role to hostname for our reply. role = r['role'] ip = r['ip_address'] for i in self.__instance_info.iterkeys(): self.__instance_info[i]['deployment_type'] = xml.get_parm('Installation', 'ServerTypeInstall') self.__instance_info[i]['storage_type'] = xml.get_parm('Installation', 'DBRootStorageType') self.__instance_info[i]['system_name'] = xml.get_parm('SystemConfig', 'SystemName') host = '' try: # try a lookup host = socket.gethostbyaddr(ip)[0] if host == 'localhost': host = fqdn except: # this is bad - it means that the Calpont.xml we found uses IP addresses that don't # resolve to hostnames on the server. self.__instance_info[fqdn]['valid'] = False self.__instance_info[fqdn]['reason'] = 'Calpont.xml contained IP address %s that does not resolve to a hostname' % ip break self.__role_info[role] = host # check to see if this host needs to be added to the request if not self.__instance_info.has_key(host): self.__req['hostnames'].append(host) self.__pmgr.write_inventory( 'default', { 'all' : self.__req['hostnames'] }) self.run_host(host) if self.__instance_info[fqdn]['valid']: # only do these updates if the node is still considered valid - may get set to False # above if unknown IPs in Calpont.xml invdict = { 'all' : self.__req['hostnames'], 'pm:children' : [ 'pm1' ], 'pm1' : [ self.__role_info['pm1'] ] } if self.__role_info.has_key('pm2'): invdict['pm2'] = [ self.__role_info['pm2'] ] self.__pmgr.write_inventory( 'infinidb', invdict ) varlist = [ ('em_server',socket.gethostbyname(socket.gethostname())), ('infinidb_installdir',self.__instance_info[fqdn]['infinidb_installdir']), ('infinidb_user',self.__instance_info[fqdn]['infinidb_user']) ] self.__pmgr.write_vars('pm', varlist) else: # some kind of problem running getinfo.yml...Will reset the entire host info self.__instance_info[h] = { 'valid' : False, 'reason': 'Failed to run playbook getinfo.yml: rc=%s, stdout=%s, stderr=%s' % \ ( rc, out, err ) }
# todo - handle case where use only specifies one machine of infinidb cluster # run site_facts first, then check to make sure any infinidb machine is in the # inventory. Then rerun setup & site_facts, etc. p.write_inventory( 'default', { 'all' : hosts }) cluster_valid = True cluster_dist = '' cluster_reason = '' valid_instances = 0 cluster_gluster = '' cluster_hadoop = '' cluster_infinidb = '' infinidb_host = '' instance_info = {} reslt = p.run_module( 'default', 'all', 'setup' ) role_info = {} for h in reslt['dark']: instance_info[h] = dict( valid=False ) for h in reslt['contacted']: host_facts = reslt['contacted'][h]['ansible_facts'] if not cluster_dist: cluster_dist = host_facts['ansible_distribution'] elif cluster_dist != host_facts['ansible_distribution']: cluster_valid = False cluster_reason = 'Multiple distributions: %s and %s' % (cluster_dist, host_facts['ansible_distribution']) instance_info[h] = dict( valid=True, ip_address=host_facts['ansible_default_ipv4']['address'] ) site_reslt = p.run_module( 'default', h, 'site_facts' ) print site_reslt