def rc(args=None): platform = __n__['platform'] share_dir = __n__['share_dir'] init_script = None command = {} chmod = 'chmod 755 /etc/init.d/nlan' if platform == 'debian': init_script = os.path.join(share_dir, 'nlan_debian') init_script_docker = os.path.join(share_dir, 'nlan_debian_docker') command['enable'] = [ 'cp {} /etc/init.d/nlan'.format(init_script), chmod, 'update-rc.d nlan defaults' ] command['update'] = ['cp {} /etc/init.d/nlan'.format(init_script)] command['enable_docker'] = [ 'cp {} /etc/init.d/nlan'.format(init_script_docker), chmod, 'update-rc.d nlan defaults' ] command['update_docker'] = [ 'cp {} /etc/init.d/nlan'.format(init_script_docker) ] command['disable'] = ['rm /etc/init.d/nlan', 'update-rc.d nlan remove'] command['status'] = ['ls /etc/rc2.d/'] elif platform == 'openwrt': init_script = os.path.join(share_dir, 'nlan_openwrt') command['enable'] = [ 'cp {} /etc/init.d/nlan'.format(init_script), chmod, '/etc/init.d/nlan enable' ] command['update'] = ['cp {} /etc/init.d/nlan'.format(init_script)] command['disable'] = [ '/etc/init.d/nlan disable', 'rm /etc/init.d/nlan' ] command['status'] = ['ls /etc/rc.d/'] if args in command: # Caution: this is just a workaround to cope with # the situation that OpenWrt's 'enable' always returns # exit code = 1, even if it is successful. if platform == 'openwrt' and args == 'enable': for l in command[args]: # Does not raise an exception even if exit code = 1 cmd(l) # Tests if S85nlan exists exitcode = check_cmd('test -f /etc/rc.d/S85nlan') if exitcode == 0: pass else: raise Exception('system.rc: nlan enable failure') else: for l in command[args]: print output_cmd(l) else: return "Usage:\nsystem.rc (enable|update|disable|status|enable_docker|update_docker)"
def service(*args): scripts = {'networking':{'openwrt': '/etc/init.d/network','raspbian': 'service networking'}} script = args[0] command = args[1] platform = __n__['platform'] return output_cmd(scripts[script][platform], command)
def rc(args=None): platform = __n__['platform'] share_dir = __n__['share_dir'] init_script = None command = {} chmod = 'chmod 755 /etc/init.d/nlan' if platform == 'debian': init_script = os.path.join(share_dir, 'nlan_debian') init_script_docker = os.path.join(share_dir, 'nlan_debian_docker') command['enable'] = ['cp {} /etc/init.d/nlan'.format(init_script), chmod, 'update-rc.d nlan defaults'] command['update'] = ['cp {} /etc/init.d/nlan'.format(init_script)] command['enable_docker'] = ['cp {} /etc/init.d/nlan'.format(init_script_docker), chmod, 'update-rc.d nlan defaults'] command['update_docker'] = ['cp {} /etc/init.d/nlan'.format(init_script_docker)] command['disable'] = ['rm /etc/init.d/nlan', 'update-rc.d nlan remove'] command['status'] = ['ls /etc/rc2.d/'] elif platform == 'openwrt': init_script = os.path.join(share_dir, 'nlan_openwrt') command['enable'] = ['cp {} /etc/init.d/nlan'.format(init_script), chmod, '/etc/init.d/nlan enable'] command['update'] = ['cp {} /etc/init.d/nlan'.format(init_script)] command['disable'] = ['/etc/init.d/nlan disable', 'rm /etc/init.d/nlan'] command['status'] = ['ls /etc/rc.d/'] if args in command: # Caution: this is just a workaround to cope with # the situation that OpenWrt's 'enable' always returns # exit code = 1, even if it is successful. if platform == 'openwrt' and args == 'enable': for l in command[args]: # Does not raise an exception even if exit code = 1 cmd(l) # Tests if S85nlan exists exitcode = check_cmd('test -f /etc/rc.d/S85nlan') if exitcode == 0: pass else: raise Exception('system.rc: nlan enable failure') else: for l in command[args]: print output_cmd(l) else: return "Usage:\nsystem.rc (enable|update|disable|status|enable_docker|update_docker)"
def service(*args): scripts = { 'networking': { 'openwrt': '/etc/init.d/network', 'raspbian': 'service networking' } } script = args[0] command = args[1] platform = __n__['platform'] return output_cmd(scripts[script][platform], command)
def main(router='_ALL',operation=None, doc=None, cmd_list=None, loglevel=None, git=False, verbose=False, mime=False, output_stdout=False, rest_output=False): rp = "Ping test to all the target routers" if verbose: print bar[:5], rp, bar[5+len(rp):] (exit, results) = _wait(router, PING_CHECK_WAIT, verbose) if exit > 0: print "" print "Ping test failure! Transaction cancelled." raise NlanException("Ping test failure", result=results) start_datetime = str(datetime.datetime.now()) start_utc = time.time() if doc and not operation or doc and operation == '--raw': doc = ' '.join(doc) if not loglevel: loglevel = '' def _ssh_exec_command(ssh, cmd, cmd_args, out): i,o,e = ssh.exec_command(cmd) o.channel.set_combine_stderr(True) # Combine STDERR if cmd_args: i.write(cmd_args) i.flush() i.channel.shutdown_write() result = o.read() if result != '': print >>out, result return o.channel.recv_exit_status() # ssh session per child process def _ssh_session(lock, queue, router, host, user, passwd, platform, operation, cmd, cmd_args, verbose, mime=False, output_stdout=False): out = StringIO() #err = StringIO() ssh = None stdout = None finish_utc = None response = OrderedDict() response['exit'] = 0 try: ssh = para.SSHClient() ssh.set_missing_host_key_policy(para.AutoAddPolicy()) ssh.connect(host,username=user,password=passwd,timeout=SSH_TIMEOUT) if operation != '--scp' and operation != '--scpmod': exitcode = _ssh_exec_command(ssh, cmd, cmd_args, out) else: filelist = [] if operation == '--scp': s = scp.SCPClient(ssh.get_transport()) if verbose: print >>out, "target_dir: " + NLAN_AGENT_DIR for f in cmd: s.put(f, NLAN_AGENT_DIR) filelist.append(f) elif operation == '--scpmod': s = scp.SCPClient(ssh.get_transport()) if verbose: print >>out, "target_dir: " + NLAN_AGENT_DIR # scp NLAN modules for moddir in NLAN_MOD_DIRS: ldir = os.path.join(NLAN_SCP_DIR, moddir) rdir = os.path.join(NLAN_AGENT_DIR, moddir) exitcode = _ssh_exec_command(ssh, 'mkdir -p ' + rdir, None, out) for f in os.listdir(ldir): ff = os.path.join(ldir, f) s.put(ff, rdir) filelist.append(f) # scp NLAN-Agent scripts for f in os.listdir(os.path.join(NLAN_SCP_DIR)): lf = os.path.join(NLAN_SCP_DIR, f) if os.path.isdir(lf): pass else: s.put(lf, NLAN_AGENT_DIR) filelist.append(f) # scp NLAN libs for f in NLAN_LIBS: lf = os.path.join(NLAN_DIR, f) s.put(lf, NLAN_AGENT_DIR) filelist.append(f) # scp NLAN Agent etc files ldir = os.path.join(NLAN_DIR, 'agent/share') rdir = os.path.join(NLAN_AGENT_DIR, 'share') exitcode = _ssh_exec_command(ssh, 'mkdir -p ' + rdir, None, out) for f in os.listdir(ldir): ff = os.path.join(ldir, f) s.put(ff, rdir) filelist.append(f) # nlan_env.conf generation rdir_nlanconf = os.path.join(NLAN_AGENT_DIR, nlanconf) env = {} env['router'] = router env['platform'] = platform env['agent_dir'] = NLAN_AGENT_DIR env['schema'] = SCHEMA env['state_order'] = STATE_ORDER env['tables'] = TABLES env['indexes'] = INDEXES env['types'] = TYPES env['share_dir'] = rdir lf = os.path.join('/tmp', '{}.{}'.format(nlanconf,router)) with open(lf, 'w') as f: f.seek(0) f.truncate() f.write(str(env)) s.put(lf, rdir_nlanconf) filelist.append(nlanconf) if verbose: print >>out, "files: " + str(filelist) with lock: outv = out.getvalue() outvl = len(outv) if verbose and (operation == '--scpmod' or operation == '--scp'): rp = "Files copied to router:{0},platform:{1}".format(router, platform) print bar[:5], rp, bar[5+len(rp):] if outvl > 0: print "*** Response from router:{0},platform:{1}".format(router, platform) stdout = email.message_from_string(outv) if mime: print stdout else: for part in stdout.walk(): content_type = part.get_content_type() payload = part.get_payload() content_description = part.get('Content-Description') x_nlan_type = part.get('X-NLAN-Type') if payload: if x_nlan_type == 'logger': print content_description if content_type == 'application/x-nlan': try: d = eval(payload) if isinstance(d, OrderedDict): if x_nlan_type == 'nlan_response': response = d if x_nlan_type == 'nlan_response' and d['exit'] > 0: for k, v in d.iteritems(): print '{}: {}'.format(k,v) elif verbose or x_nlan_type != 'nlan_response': print _toyaml(d) else: pass # NLAN Response with exit == 0 and not verbose else: if x_nlan_type == 'nlan_response': raise Exception('Illegal NLAN Response received, {}'.format(str(payload))) else: print payload except: print payload elif content_type == 'application/json': d = json.loads(payload, object_hook=util.decode_dict) print _toyaml(d) elif content_type == 'text/plain': print payload except Exception as e: response['exception'] = type(e).__name__ response['message'] = 'See the traceback message' response['exit'] = 1 response['traceeback'] = traceback.format_exc() with lock: rp = "NLAN Request Failure router:{0},platform:{1}".format(router, platform) print bar[:5], rp, bar[5+len(rp):] print ('__ Exception __') for key in response.keys(): print '{}: {}'.format(key, response[key]) finally: finish_utc = time.time() result = {} if output_stdout: result['stdout'] = None if stdout: for part in stdout.walk(): x_nlan_type = part.get('X-NLAN-Type') if x_nlan_type in ('crud_response', 'rpc_response'): payload = part.get_payload() content_type = part.get_content_type() if payload: if content_type == 'application/x-nlan': try: payload = eval(payload) except: pass result['stdout'] = payload break result['router'] = router result['response'] = response result['finish_utc'] = finish_utc queue.put(result) out.close() ssh.close() routers = [] ssh_sessions = [] lock = Lock() queue = Queue() if router == '_ALL': routers = ROSTER.keys() else: routers.append(router) if operation == '--batch': for l in cmd_list: router = l[0] operation = l[1] doc = l[2] host = ROSTER[router]['host'] user = ROSTER[router]['user'] passwd = ROSTER[router]['passwd'] platform = ROSTER[router]['platform'] cmd = NLAN_AGENT + ' ' + operation + ' --envfile ' + os.path.join(NLAN_AGENT_DIR, nlanconf) + ' ' + loglevel cmd_args = doc cmd_args = '"' + cmd_args + '"' if verbose: _printmsg_request(lock, router, platform) print 'operation: ' + operation print 'dict_args: ' + cmd_args ssh_sessions.append(Process(target=_ssh_session, args=(lock, queue, router, host, user, passwd, platform, operation, cmd, cmd_args, verbose, mime, output_stdout))) else: for router in routers: host = ROSTER[router]['host'] user = ROSTER[router]['user'] passwd = ROSTER[router]['passwd'] platform = ROSTER[router]['platform'] cmd = '' cmd_args = '' if operation == '--raw': assert(isinstance(doc,str)) cmd = doc if verbose: _printmsg_request(lock, router, platform) print 'operation: ' + operation print 'command: ' + cmd elif operation == '--scpmod': if verbose: _printmsg_request(lock, router, platform) print 'operation: ' + operation elif operation == '--scp': assert(isinstance(doc,list)) cmd = doc for f in doc: fp = os.path.join(NLAN_DIR, f) if os.path.isdir(fp): cmd.remove(f) if verbose: _printmsg_request(lock, router, platform) print 'operation: ' + operation print 'files: ' + str(cmd) elif operation == None: cmd = NLAN_AGENT + ' ' + doc + ' --envfile ' + os.path.join(NLAN_AGENT_DIR, nlanconf) + ' ' + loglevel if verbose: _printmsg_request(lock, router, platform) print 'command: ' + doc else: cmd = NLAN_AGENT + ' ' + operation + ' --envfile ' + os.path.join(NLAN_AGENT_DIR, nlanconf) + ' ' + loglevel cmd_args = doc cmd_args = '"' + cmd_args + '"' if verbose: _printmsg_request(lock, router, platform) print 'operation: ' + operation print 'dict_args: ' + cmd_args ssh_sessions.append(Process(target=_ssh_session, args=(lock, queue, router, host, user, passwd, platform, operation, cmd, cmd_args, verbose, mime, output_stdout))) # Start child processes try: for l in ssh_sessions: l.start() while True: if len(ssh_sessions) == 0: break sleep(0.05) temp = list(ssh_sessions) for l in temp: if not l.is_alive(): l.terminate() ssh_sessions.remove(l) except KeyboardInterrupt: print "\nOK. I will terminate the child processes..." for l in ssh_sessions: pid = str(l[0].pid) sub = cmdutil.output_cmd('ps -p', pid, 'h') l.terminate() l.join() print "child process:", sub raise Exception("Operation stopped by Keyboard Interruption") finally: exit = 0 results = [] if not queue.empty(): if verbose: title = "Transaction Summary" print bar[:5], title, bar[5+len(title):] print "" print "Start Time: {}".format(start_datetime) print "" print "Router Result Elapsed Time" print "---------------------------------------" for l in ssh_sessions: l.terminate() while not queue.empty(): smiley = ':-)' result = queue.get() router = result['router'] response = result['response'] if response['exit'] > 0: smiley = 'XXX' exit = 1 if verbose: print "{:17s} {:3s} {:10.2f}(sec)".format(router, smiley, result['finish_utc'] - start_utc) results.append(result) if exit > 0: raise NlanException("NLAN transaction failure", result=results) else: return results # A bunch of results from child processes
def _wait(router, timeout, verbose): import subprocess, time # child process def _ping(router, host, timeout, devnull, queue): start = time.time() okcheck = True if timeout < 0: timeout = abs(timeout) okcheck = False while True: command = 'ping -c 1 -W 1 ' + host command = command.split() exitcode = subprocess.call(command, stdout=devnull) if okcheck and exitcode == 0 or not okcheck and exitcode > 0: queue.put((router, host, True)) break if time.time() - start > timeout: queue.put((router, host, False)) break hosts = {} exit = 0 if router == '_ALL': for router in ROSTER.keys(): hosts[router] = ROSTER[router]['host'] else: hosts[router] = ROSTER[router]['host'] if verbose: print "Router Host Ping" print "------------------------------------" children = [] results = [] try: with open(os.devnull, 'w') as devnull: queue = Queue() for router, host in hosts.iteritems(): child = Process(target=_ping, args=(router, host, timeout, devnull, queue)) child.start() children.append(child) while True: if len(children) == 0: break sleep(0.5) temp = list(children) for l in temp: if not l.is_alive(): l.terminate() children.remove(l) while not queue.empty(): q = queue.get() router = q[0] host = q[1] result = q[2] if timeout > 0 and result or timeout < 0 and not result: if verbose: print '{:17s}{:15s}OK'.format(router, host) elif timeout > 0 and not result or timeout < 0 and result: if verbose: print '{:17s}{:15s}NG'.format(router, host) if result: results.append({'message': 'Ping test OK', 'router':router, 'host':host, 'exit': 0}) else: results.append({'message': 'Ping test failure', 'router':router, 'host':host, 'exit': 1}) if not result and exit == 0: exit = 1 except KeyboardInterrupt: print "\nOK. I will terminate the subprocesses..." for l in children: pid = str(l.pid) sub = cmdutil.output_cmd('ps -p', pid, 'h') l.terminate() l.join() print "child process:", sub finally: return (exit, results)
def reboot(): return output_cmd('reboot')
def halt(): return output_cmd('halt')
def _flow_entries(ope): # serarch Open_vSwitch table if not search('Controller', ['target']): # no OpenFlow Controller params = {} if ope == 'add': params['svni'] = str(_vni_) params['svid'] = str(_vid_) if _ip_dvr: params['defaultgw'] = _ip_dvr['addr'].split('/')[0] else: # 'delete' params['svni'] = str(vni_) params['svid'] = str(vid_) if _ip_dvr: params['defaultgw'] = ip_dvr_['addr'].split('/')[0] int_dvr = "int_dvr" + params['svni'] int_br = "int_br" + params['svni'] cmd = cmdutil.check_cmd if _vid: if ope: cmd('ovs-ofctl add-flow br-tun table=2,priority=1,tun_id={svni},actions=mod_vlan_vid:{svid},resubmit(,10)'.format(**params)) else: cmd('ovs-ofctl del-flows br-tun table=2,tun_id={svni}'.format(**params)) if _ip_dvr and 'mode' not in _ip_dvr: raise ModelError('requires "mode"') if _ip_dvr and _ip_dvr['mode'] == 'dvr': if ope: cmd('ovs-ofctl add-flow br-tun', 'table=19,priority=1,dl_type=0x0806,dl_vlan={svid},nw_dst={defaultgw},actions=drop'.format(**params)) else: cmd('ovs-ofctl del-flows br-tun', 'table=19,dl_type=0x0806,dl_vlan={svid},nw_dst={defaultgw}'.format(**params)) # Redirects a packet to int_dvr port if nw_dst is a private ip address elif _ip_dvr and _ip_dvr['mode'] == 'spoke_dvr': mask = _ip_dvr['addr'].split('/')[1] #address = params['defaultgw'].split('.') nw_dst = network_address(params['defaultgw'], mask)+'/'+mask output = cmdutil.output_cmd('ip link show dev', int_dvr).split('\n')[1] dl_dst = output.split()[1] r = OvsdbRow('Interface', ('name', int_dvr)) outport = str(r['ofport']) r = OvsdbRow('Interface', ('name', int_br)) inport = str(r['ofport']) params['inport'] = inport params['outport'] = outport params['dl_type'] = '0x0800' params['dl_dst'] = dl_dst params['nw_dst'] = nw_dst params['nw_dst10'] = nw_dst10 params['nw_dst172'] = nw_dst172 params['nw_dst192'] = nw_dst192 params['cmdadd'] = 'ovs-ofctl add-flow br-int' params['cmddel'] = 'ovs-ofctl del-flows br-int' if ope: cmd('{cmdadd} table=0,priority=2,in_port={inport},dl_type={dl_type},nw_dst={nw_dst},actions=normal'.format(**params)) cmd('{cmdadd} table=0,priority=1,in_port={inport},dl_type={dl_type},nw_dst={nw_dst10},actions=resubmit(,1)'.format(**params)) cmd('{cmdadd} table=0,priority=1,in_port={inport},dl_type={dl_type},nw_dst={nw_dst172},actions=resubmit(,1)'.format(**params)) cmd('{cmdadd} table=0,priority=1,in_port={inport},dl_type={dl_type},nw_dst={nw_dst192},actions=resubmit(,1)'.format(**params)) # ARP, opcode = 2, TPA = defaultgw cmd('{cmdadd} table=0,priority=1,in_port={outport},dl_type=0x0806,nw_src={defaultgw},nw_proto=2,actions=drop'.format(**params)) cmd('{cmdadd} table=1,priority=0,in_port={inport},actions=set_field:{dl_dst}->dl_dst,output:{outport}'.format(**params)) else: cmd('{cmddel} table=0,in_port={inport},dl_type={dl_type},nw_dst={nw_dst}'.format(**params)) cmd('{cmddel} table=0,in_port={inport},dl_type={dl_type},nw_dst={nw_dst10}'.format(**params)) cmd('{cmddel} table=0,in_port={inport},dl_type={dl_type},nw_dst={nw_dst172}'.format(**params)) cmd('{cmddel} table=0,in_port={inport},dl_type={dl_type},nw_dst={nw_dst192}'.format(**params)) # ARP, opcode = 2, TPA = defaultgw cmd('{cmddel} table=0,in_port={outport},dl_type=0x0806,nw_src={defaultgw},nw_proto=2'.format(**params)) cmd('{cmddel} table=1,in_port={inport}'.format(**params)) elif _ip_dvr and _ip_dvr['mode'] == 'hub' or 'spoke': pass else: pass if _peers: # Broadcast tree for each vni output_ports = '' vxlan_ports = get_vxlan_ports(_peers) for vxlan_port in vxlan_ports: output_ports = output_ports+',output:'+vxlan_port if ope: cmd('ovs-ofctl add-flow br-tun table=21,priority=1,dl_vlan={svid},actions=strip_vlan,set_tunnel:{svni}'.format(**params)+output_ports) else: cmd('ovs-ofctl del-flow br-tun table=21,dl_vlan={svid}'.format(**params))
def ping(host): return cmdutil.output_cmd('ping -c4', host)
# NLAN default roster file #NLAN_ROSTER = 'roster.yaml' #NLAN_ROSTER = 'docker.yaml' NLAN_ROSTER = 'docker2.yaml' # NLAN default state file NLAN_STATE = 'state.yaml' # Directory of NLAN agent scripts including NLAN modules (local) NLAN_SCP_DIR = os.path.join(NLAN_DIR, 'agent') # roster file (local) ROSTER_YAML = os.path.join(NLAN_ETC, 'roster', NLAN_ROSTER) DOCKER_IP = os.path.join(ROOT, 'bin', 'docker_ip') docker_ip = lambda container: cmdutil.output_cmd(DOCKER_IP, container) _roster = {} with open(ROSTER_YAML, 'r') as f: _roster = yaml.load(f.read()) for router, attr in _roster.iteritems(): if attr['host'] == '<docker_ip>': attr['host'] = docker_ip(router) ROSTER = _roster # Git repo (local) GIT_DIR = '/root/neutron-lan/etc/.git' WORK_TREE = os.path.join(NLAN_ETC, 'state') GIT_OPTIONS = '--git-dir {} --work-tree {}'.format(GIT_DIR, WORK_TREE) ### NLAN-Agent-related env #######################################
def _yaml_load(filename, gitshow): od = None template_module = None if gitshow: default = "vacant: true" try: data = output_cmd('git', GIT_OPTIONS, 'show HEAD:' + filename) if data == '': data = default else: template_module = get_template_module(StringIO(data).readline()) except CmdError: data = default od = yaml.load(data, lya.OrderedDictYAMLLoader) else: with open(os.path.join(WORK_TREE, filename), 'r') as f: od = yaml.load(f, lya.OrderedDictYAMLLoader) f.seek(0) template_module = get_template_module(f.readline()) types = None module = None if template_module: __import__(template_module) module = sys.modules[template_module] types = module.placeholder_types() base = lya.AttrDict(od) flatten = lya.AttrDict.flatten(base) values = [] state_order = [] for l in flatten: try: path = l[0][1] if path not in state_order: state_order.append(path) except: pass path = '' length = len(l[0]) for i in range(length): m = l[0][i] if path == '': path = m else: if i != length-1: path += '.'+m elif len(l[0]) == 2 and type(l[1]) is list: count = 0 for elm in l[1]: if type(elm) is OrderedDict: dic = dict(elm) index = None try: key = INDEXES[m] except: pass if key != None: value = dic[key] index = key + ':' + dumps(value, types) else: index = str(count) for key in dic: pl = path+'.'+m+'['+index+'].'+key+'='+dumps(dic[key], types) values.append(pl) else: pl = path+'.'+m+'['+str(count)+']='+dumps(elm, types) values.append(pl) count += 1 else: path += '.'+m+'='+dumps(l[1], types) values.append(path) if template_module: values = module.fillout(values) return (sorted(values), STATE_ORDER)