#!/usr/bin/python2 # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright 2018 Lenovo # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import optparse import os import signal import sys import time try: signal.signal(signal.SIGPIPE, signal.SIG_DFL) except AttributeError: pass path = os.path.dirname(os.path.realpath(__file__)) path = os.path.realpath(os.path.join(path, '..', 'lib', 'python')) if path.startswith('/opt'): sys.path.append(path) import confluent.client as client import confluent.screensqueeze as sq exitcode = 0 def get_update_progress(session, url): for res in session.read(url): status = res['phase'] percent = res['progress'] detail = res['detail'] if status == 'error': text = 'error!' else: text = '{0}: {1:3.0f}%'.format(status, percent) return text, status, detail def printerror(res, node=None): global exitcode if 'errorcode' in res: exitcode = res['errorcode'] if 'error' in res: if node: sys.stderr.write('{0}: {1}\n'.format(node, res['error'])) else: sys.stderr.write('{0}\n'.format(res['error'])) if 'errorcode' not in res: exitcode = 1 for node in res.get('databynode', ()): printerror(res['databynode'][node], node) def download_servicedata(noderange, media, options): global exitcode session = client.Command() output = sq.ScreenPrinter(noderange, session) filename = os.path.abspath(media) resource = '/noderange/{0}/support/servicedata/'.format(noderange) upargs = {'filename': filename} noderrs = {} nodeurls = {} session.stop_if_noderange_over(noderange, options.maxnodes) for res in session.create(resource, upargs): if 'created' not in res: for nodename in res.get('databynode', ()): output.set_output(nodename, 'error!') noderrs[nodename] = res['databynode'][nodename].get( 'error', 'Unknown Error') continue watchurl = res['created'] currnode = watchurl.split('/')[1] nodeurls[currnode] = '/' + watchurl while nodeurls: for node in list(nodeurls): progress, status, err = get_update_progress( session, nodeurls[node]) if status == 'error': exitcode = 1 noderrs[node] = err if status in ('error', 'complete', 'pending'): list(session.delete(nodeurls[node])) del nodeurls[node] output.set_output(node, progress) time.sleep(2) allerrnodes = ','.join(noderrs) if noderrs: sys.stderr.write( 'Nodes had errors retrieving service data ({0})!\n'.format(allerrnodes)) for node in noderrs: sys.stderr.write('{0}: {1}\n'.format(node, noderrs[node])) funmap = { 'servicedata': download_servicedata, } class OptParser(optparse.OptionParser): def format_epilog(self, formatter): return self.expand_prog_name(self.epilog) def main(): argparser = OptParser( usage="Usage: %prog servicedata " "", epilog='\nservicedata will save service data to the given ' 'directory. It is saved to the location on the relevant ' 'management server (the confluent server if running remote, ' 'and the collective.manager if in collective)\n' '\n\nSee `man %prog` for more info.\n') argparser.add_option('-m', '--maxnodes', type='int', help='Specify a maximum number of ' 'nodes to download diagnostic data from, ' 'prompting if over the threshold') (options, args) = argparser.parse_args() media = None try: noderange = args[0] operation = args[1] arglength = 2 if operation == 'servicedata': media = args[2] arglength = 3 if len(args) > arglength: argparser.print_help() sys.exit(1) except IndexError: argparser.print_help() sys.exit(1) client.check_globbing(noderange) try: handler = funmap[operation] except KeyError: argparser.print_help() sys.exit(1) handler(noderange, media, options) if __name__ == '__main__': main()