def do_members_history(): # The information is available only if the agent is started wait_for_agent_started(visual_wait=True) try: history_entries = get_opsbro_json('/agent/members/history') except get_request_errors() as exp: logger.error('Cannot join opsbro agent to show member history: %s' % exp) sys.exit(1) print_h1('History') for history_entry in history_entries: epoch_date = history_entry['date'] # We want only group type events entries = [ entry for entry in history_entry['entries'] if entry['type'] == 'node-state-change' ] if not entries: continue print_h2( ' Date: %s ' % time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime(epoch_date))) for entry in entries: name = entry['name'] if entry.get('display_name', ''): name = '[ ' + entry.get('display_name') + ' ]' old_state = entry['old_state'] new_state = entry['state'] old_color = NODE_STATE_COLORS.get(old_state, 'cyan') old_state_prefix = NODE_STATE_PREFIXS.get( old_state, CHARACTERS.double_exclamation) new_color = NODE_STATE_COLORS.get(new_state, 'cyan') new_state_prefix = NODE_STATE_PREFIXS.get( new_state, CHARACTERS.double_exclamation) cprint('%s ' % name.ljust(20), color='magenta', end='') cprint(('%s %s' % (old_state_prefix, old_state)).ljust(9), color=old_color, end='') # 7 for the maximum state string + 2 for prefix cprint(' %s ' % CHARACTERS.arrow_left, color='grey', end='') cprint(('%s %s' % (new_state_prefix, new_state)).ljust(9), color=new_color ) # 7 for the maximum state string + 2 for prefix
def do_gossip_add_event(event_type): # The information is available only if the agent is started wait_for_agent_started(visual_wait=True) try: r = post_opsbro_json('/agent/event', {'event_type': event_type}) except get_request_errors() as exp: logger.error(exp) sys.exit(2) cprint('\n %s ' % CHARACTERS.arrow_left, color='grey', end='') cprint('%s ' % CHARACTERS.check, color='green', end='') cprint('The event ', end='') cprint('%s' % event_type, color='magenta', end='') cprint(' is ', end='') cprint('added', color='green')
def do_wait_event(event_type, timeout=30): # The information is available only if the agent is started wait_for_agent_started(visual_wait=True) import itertools spinners = itertools.cycle(CHARACTERS.spinners) for i in range(timeout): uri = '/agent/event/%s' % event_type logger.debug('ASK FOR EVENT %s' % event_type) try: evt = get_opsbro_json( uri, timeout=1) # slow timeout to allow fast looping # Timemouts: just loop except get_not_critical_request_errors() as exp: logger.debug( 'Asking for event: get timeout (%s), skiping this turn' % exp) evt = None except get_request_errors() as exp: logger.error( 'Cannot ask for event %s because there is a critical error: %s' % (event_type, exp)) sys.exit(2) if evt is not None: cprint('\n %s ' % CHARACTERS.arrow_left, color='grey', end='') cprint('%s ' % CHARACTERS.check, color='green', end='') cprint('The event ', end='') cprint('%s' % event_type, color='magenta', end='') cprint(' is ', end='') cprint('detected', color='green') sys.exit(0) # Not detected? increase loop cprint('\r %s ' % next(spinners), color='blue', end='') cprint('%s' % event_type, color='magenta', end='') cprint(' is ', end='') cprint('NOT DETECTED', color='magenta', end='') cprint(' (%d/%d)' % (i, timeout), end='') # As we did not \n, we must flush stdout to print it sys.stdout.flush() time.sleep(1) cprint("\nThe event %s was not detected after %s seconds" % (event_type, timeout)) sys.exit(2)
def do_exec(group='*', cmd='uname -a'): if cmd == '': logger.error('Missing command') return # The information is available only if the agent is started wait_for_agent_started(visual_wait=True) try: (code, r) = get_opsbro_local('/exec/%s?cmd=%s' % (group, cmd)) except get_request_errors() as exp: logger.error(exp) return print(r) cid = r print("Command group launch as cid", cid) time.sleep(5) # TODO: manage a real way to get the result.. try: (code, r) = get_opsbro_local('/exec-get/%s' % cid) except get_request_errors() as exp: logger.error(exp) return j = jsoner.loads(r) res = j['res'] for (uuid, e) in res.items(): node = e['node'] nname = node['name'] color = { 'alive': 'green', 'dead': 'red', 'suspect': 'yellow', 'leave': 'cyan' }.get(node['state'], 'cyan') cprint(nname, color=color) cprint('Return code:', end='') color = {0: 'green', 1: 'yellow', 2: 'red'}.get(e['rc'], 'cyan') cprint(e['rc'], color=color) cprint('Output:', end='') cprint(e['output'].strip(), color=color) if e['err']: cprint('Error:', end='') cprint(e['err'].strip(), color='red') cprint('')
def do_exec(group='*', cmd='uname -a'): if cmd == '': logger.error('Missing command') return # The information is available only if the agent is started wait_for_agent_started(visual_wait=True) cmd_64 = bytes_to_unicode(base64.b64encode(unicode_to_bytes(cmd))) try: r = get_opsbro_json('/exec/%s?cmd=%s' % (group, cmd_64)) except get_request_errors() as exp: cprint('ERROR: cannot launch the command: %s' % exp, color='red') sys.exit(2) cid = r print("Command group launch as cid", cid) time.sleep(5) # TODO: manage a real way to get the result.. try: r = get_opsbro_json('/exec-get/%s' % cid) except get_request_errors() as exp: cprint('ERROR: cannot get execution results: %s' % exp, color='red') sys.exit(2) res = r['res'] print('Launched at: %s' % res) for (uuid, e) in res.items(): node = e['node'] nname = node['name'] color = {'alive': 'green', 'dead': 'red', 'suspect': 'yellow', 'leave': 'cyan'}.get(node['state'], 'cyan') cprint(nname, color=color) cprint('Return code for [%s]:' % e['cmd'], end='') color = {0: 'green', 1: 'yellow', 2: 'red'}.get(e['rc'], 'cyan') cprint(e['rc'], color=color) cprint('Output:', end='') cprint(e['output'].strip(), color=color) if e['err']: cprint('Error:', end='') cprint(e['err'].strip(), color='red') cprint('')
def do_join(seed=''): if seed == '': logger.error('Missing target argument. For example 192.168.0.1:6768') return # The information is available only if the agent is started wait_for_agent_started(visual_wait=True) try: (code, r) = get_opsbro_local('/agent/join/%s' % seed) except get_request_errors() as exp: logger.error(exp) return try: b = jsoner.loads(r) except ValueError as exp: # bad json logger.error('Bad return from the server %s' % exp) return cprint('Joining %s : ' % seed, end='') if b: cprint('OK', color='green') else: cprint('FAILED', color='red')
def do_leave(nuuid=''): # The information is available only if the agent is started wait_for_agent_started(visual_wait=True) # Lookup at the localhost name first if not nuuid: try: nuuid = get_opsbro_json('/agent/uuid') except get_request_errors() as exp: logger.error('Cannot join opsbro agent to get our uuid: %s' % exp) sys.exit(2) uri = '/agent/leave/%s' % nuuid try: (code, r) = get_opsbro_local(uri) except get_request_errors() as exp: logger.error(exp) return if code != 200: logger.error('Node %s is missing (return=%s)' % (nuuid, r)) return cprint('Node %s is set to leave state' % nuuid, end='') cprint(': OK', color='green')
def do_ping(node): # The information is available only if the agent is started wait_for_agent_started(visual_wait=True) try: node_obj = get_opsbro_json('/agent/query/guess/%s' % node) except get_request_errors() as exp: logger.error('Cannot query the node: %s' % exp) sys.exit(2) if node_obj is None: cprint('FAILED: cannot find the node %s' % node, color='red') sys.exit(2) node_uuid = node_obj['uuid'] try: ping_result = get_opsbro_json('/agent/ping/%s' % node_uuid) except get_request_errors() as exp: logger.error('Cannot launch the node ping: %s' % exp) sys.exit(2) if 'error' in ping_result: cprint('FAILED: %s' % ping_result['error'], color='red') sys.exit(2) node_state = ping_result['state'] display_name = node_obj['display_name'] if not display_name: display_name = node_obj['name'] state_color = NODE_STATE_COLORS.get(node_state) state_char = NODE_STATE_PREFIXS.get(node_state) cprint(' %s ' % state_char, color=state_color, end='') cprint('%-15s ' % display_name, color='magenta', end='') cprint('is: ', end='') cprint(node_state, color=state_color) # If not alive, it's an error if node_state != NODE_STATES.ALIVE: sys.exit(2)
def do_wait_members(name='', display_name='', group='', count=1, timeout=30): # The information is available only if the agent is started wait_for_agent_started(visual_wait=True) import itertools spinners = itertools.cycle(CHARACTERS.spinners) for i in range(timeout): try: members = get_opsbro_json('/agent/members').values() except get_request_errors() as exp: logger.error(exp) sys.exit(2) if name: for m in members: if m['name'] == name: cprint('\n %s ' % CHARACTERS.arrow_left, color='grey', end='') cprint('%s ' % CHARACTERS.check, color='green', end='') cprint('The member ', end='') cprint('%s' % name, color='magenta', end='') cprint(' is ', end='') cprint('detected', color='green') sys.exit(0) elif display_name: for m in members: if m['display_name'] == display_name: cprint('\n %s ' % CHARACTERS.arrow_left, color='grey', end='') cprint('%s ' % CHARACTERS.check, color='green', end='') cprint('The member ', end='') cprint('%s' % display_name, color='magenta', end='') cprint(' is ', end='') cprint('detected', color='green') sys.exit(0) elif group: founded = [] for m in members: if group in m['groups']: founded.append(m) if len(founded) > count: cprint('\n %s ' % CHARACTERS.arrow_left, color='grey', end='') cprint('%s ' % CHARACTERS.check, color='green', end='') cprint('The group ', end='') cprint('%s' % group, color='magenta', end='') cprint(' is ', end='') cprint('detected', color='green') cprint(' with %d members' % len(founded), end='') sys.exit(0) # Not detected? increase loop cprint('\r %s ' % next(spinners), color='blue', end='') if name: cprint('%s' % name, color='magenta', end='') elif display_name: cprint('%s' % display_name, color='magenta', end='') else: cprint('%s' % group, color='magenta', end='') cprint(' is ', end='') cprint('NOT DETECTED', color='magenta', end='') cprint(' (%d/%d)' % (i, timeout), end='') # As we did not \n, we must flush stdout to print it sys.stdout.flush() time.sleep(1) cprint("\nThe name/display_name/group was not detected after %s seconds" % (timeout)) sys.exit(2)
def do_members(detail=False): # The information is available only if the agent is started wait_for_agent_started(visual_wait=True) try: members = get_opsbro_json('/agent/members').values() except get_request_errors() as exp: logger.error('Cannot join opsbro agent to list members: %s' % exp) sys.exit(1) members = my_sort(members, cmp_f=__sorted_members) pprint = libstore.get_pprint() logger.debug('Raw members: %s' % (pprint.pformat(members))) # If there is a display_name, use it max_name_size = max([ max(len(m['name']), len(m.get('display_name', '')) + 4) for m in members ]) max_addr_size = max( [len(m['addr']) + len(str(m['port'])) + 1 for m in members]) zones = set() for m in members: mzone = m.get('zone', '') if mzone == '': mzone = NO_ZONE_DEFAULT m['zone'] = mzone # be sure to fix broken zones zones.add(mzone) zones = list(zones) zones.sort() for z in zones: z_display = z if not z: z_display = NO_ZONE_DEFAULT z_display = z_display.ljust(15) title_s = '%s: %s' % (sprintf('Zone', color='yellow', end=''), sprintf(z_display, color='blue', end='')) print_h1(title_s, raw_title=True) for m in members: zone = m.get('zone', NO_ZONE_DEFAULT) if zone != z: continue name = m['name'] if m.get('display_name', ''): name = '[ ' + m.get('display_name') + ' ]' groups = m.get('groups', []) groups.sort() port = m['port'] addr = m['addr'] state = m['state'] is_proxy = m.get('is_proxy', False) if not detail: cprint(' - %s > ' % zone, color='blue', end='') cprint('%s ' % name.ljust(max_name_size), color='magenta', end='') else: cprint(' %s %s ' % (m['uuid'], name.ljust(max_name_size)), end='') c = NODE_STATE_COLORS.get(state, 'cyan') state_prefix = NODE_STATE_PREFIXS.get( state, CHARACTERS.double_exclamation) cprint(('%s %s' % (state_prefix, state)).ljust(9), color=c, end='') # 7 for the maximum state string + 2 for prefix s = ' %s:%s ' % (addr, port) s = s.ljust(max_addr_size + 2) # +2 for the spaces cprint(s, end='') if is_proxy: cprint('proxy ', end='') else: cprint(' ', end='') if detail: cprint('%5d' % m['incarnation'], end='') cprint(' %s ' % ','.join(groups))
def do_detect_nodes(auto_join, timeout=5): # The information is available only if the agent is started wait_for_agent_started(visual_wait=True) print_h1('UDP broadcast LAN detection') print( "Trying to detect other nodes on the network thanks to a UDP broadcast. Will last %ds." % timeout) cprint(' * The detection scan will be ', end='') cprint('%ds' % timeout, color='magenta', end='') cprint(' long.') threader.create_and_launch(__print_detection_spinner, (timeout, ), 'spinner', essential=False) # Send UDP broadcast packets from the daemon try: network_nodes = get_opsbro_json('/agent/detect?timeout=%d' % timeout, timeout=timeout + 10) except get_request_errors() as exp: logger.error('Cannot join opsbro agent to detect network nodes: %s' % exp) sys.exit(1) cprint(" * Detection is DONE") print_h1('Detection result') if len(network_nodes) == 0: cprint(' ERROR: ', color='red', end='') cprint("cannot detect (broadcast UDP) other nodes") sys.exit(1) cprint("Other network nodes detected on this network:") cprint( ' Name Zone Address:port Proxy Groups' ) for node in network_nodes: cprint(' %-35s %-10s %s:%d %5s %s' % (node['name'], node['zone'], node['addr'], node['port'], node['is_proxy'], ','.join(node['groups']))) if not auto_join: cprint('NOTICE: ', color='blue', end='') cprint( "Auto join (--auto-join) is not enabled, so don't try to join theses nodes" ) return # try to join theses nodes so :) # NOTE: sort by uuid so we are always joining the same nodes # and so we don't have split network if possible (common node) all_proxys = sorted([node for node in network_nodes if node['is_proxy']], key=lambda n: n['uuid']) not_proxys = sorted( [node for node in network_nodes if not node['is_proxy']], key=lambda n: n['uuid']) if all_proxys: node = all_proxys.pop() cprint("A proxy node is detected, using it: %s (%s:%d)" % (node['name'], node['addr'], node['port'])) to_connect = '%s:%d' % (node['addr'], node['port']) else: node = not_proxys.pop() cprint("No proxy node detected. Using a standard one: %s (%s:%d)" % (node['name'], node['addr'], node['port'])) to_connect = '%s:%d' % (node['addr'], node['port']) do_join(to_connect)
def do_agent_wait_full_initialized(timeout=30, show_init_header=False): import itertools from opsbro.agentstates import AGENT_STATES if show_init_header: spinners = itertools.cycle(CHARACTERS.spinners) display_state = AGENT_STATES.AGENT_STATE_INITIALIZING agent_state = display_state for i in range(timeout): _show_init_d_label() _print_move_to_init_d_state() cprint('[', end='') cprint('%s ' % next(spinners), color='cyan', end='') # note: spinners.next() do not exists in python3 cprint(display_state, color='blue', end='') cprint(']', end='') sys.stdout.flush() agent_state = wait_for_agent_started(visual_wait=False, timeout=1, wait_for_spawn=True) # If the agent is started, we can exit and show the user help if agent_state == AGENT_STATES.AGENT_STATE_OK: _show_init_d_label() _print_move_to_init_d_state() cprint('[', end='') cprint('%s OK' % CHARACTERS.check, color='green', end='') cprint('] ' ) # lot of space to clean the initializing text cprint( ' %s Note: you can have information about OpsBro with the command: opsbro agent info' % CHARACTERS.corner_bottom_left, color='grey') return # if stopped or initializing, still wait elif agent_state in [ AGENT_STATES.AGENT_STATE_STOPPED, AGENT_STATES.AGENT_STATE_INITIALIZING ]: continue else: cprint('ERROR: the agent state: %s is not managed', color='red') sys.exit(2) # Oups, timeout reached, still not initialized after this _show_init_d_label() _print_move_to_init_d_state() cprint('FAILED (initialisation was not finish after %d seconds): %s' % (timeout, agent_state), color='red') sys.exit(2) else: agent_state = wait_for_agent_started(visual_wait=True, timeout=timeout, wait_for_spawn=True) if agent_state == AGENT_STATES.AGENT_STATE_OK: cprint(AGENT_STATES.AGENT_STATE_OK, color='green') return if agent_state == AGENT_STATES.AGENT_STATE_STOPPED: cprint(AGENT_STATES.AGENT_STATE_STOPPED, color='red') sys.exit(2) if agent_state == AGENT_STATES.AGENT_STATE_INITIALIZING: cprint(AGENT_STATES.AGENT_STATE_INITIALIZING, color='yellow') sys.exit(2) cprint(agent_state, color='grey')