#!/usr/bin/python # 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 def attach_media(noderange, media): global exitcode session = client.Command() resource = '/noderange/{0}/media/attach'.format(noderange) for rsp in session.update(resource, {'url': media}): printerror(res) list_media(noderange, media) def list_media(noderange, media): session = client.Command() resource = '/noderange/{0}/media/current'.format(noderange) for res in session.read(resource): printerror(res) for node in res.get('databynode', []): url = res['databynode'][node]['url'] name = res['databynode'][node]['name'] print('{0}: {1}'.format(node, url + '/' + name if url else name)) def detach_media(noderange, media): global exitcode session = client.Command() resource = '/noderange/{0}/media/detach'.format(noderange) for res in session.update(resource, {'detachall': 1}): printerror(res) def upload_media(noderange, media): global exitcode session = client.Command() output = sq.ScreenPrinter(noderange, session) filename = os.path.abspath(media) resource = '/noderange/{0}/media/uploads/'.format(noderange) upargs = {'filename': filename} noderrs = {} nodeurls = {} 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 receiving media ({0})!\n'.format(allerrnodes)) for node in noderrs: sys.stderr.write('{0}: {1}\n'.format(node, noderrs[node])) list_media(noderange, media) funmap = { 'upload': upload_media, 'attach': attach_media, 'detach': detach_media, 'list': list_media, } def main(): argparser = optparse.OptionParser( usage="Usage: %prog [list|upload|attach|detach] " "|all|", epilog='upload will take the specified file and upload it to the BMC, ' 'attach will instruct the BMC to connect a remote media to the ' 'specified url, and detach will remove all uploaded and' 'attached urls from the BMC, list shows currently mounted ' 'media.') (options, args) = argparser.parse_args() media = None try: noderange = args[0] operation = args[1] if operation in ('attach', 'upload'): media = args[2] 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) if __name__ == '__main__': main()