#! /usr/bin/python # Copyright 2019 Nokia # 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 sys import argparse import requests import json class Client(object): DEFAULT_INSTALL_URL = 'http://{}:{}/v1/installations/' DEFAULT_INSTALL_STATE_URL = 'http://{}:{}/v1/installations/{}/state' DEFAULT_PATH = '/opt/remoteinstaller' DEFAULT_PORT = '15101' DEFAULT_HOST = 'localhost' def __init__(self): self._verbose = None self._host = Client.DEFAULT_HOST self._port = Client.DEFAULT_PORT self._client_cert_path = None self._client_key_path = None self._user_config = None self._image = None self._request_url = None self._uuid = None self._parser = None self._args = self._parse_args(sys.argv[1:]) self._debug(self._args) def _parse_args(self, args): parser = argparse.ArgumentParser(description='Remote Installer Client',add_help=False) self._parser = parser subparsers = parser.add_subparsers(dest="subparsers") install_parser = subparsers.add_parser('install', description='Remote Installer Client: intall') install_parser.add_argument('--image', dest='image', required=True, help='Full path to installation iso image') install_parser.add_argument('--user-config', required=True, dest='userconfig', help='Full path to user config') install_parser.set_defaults(func=self._install) query_parser = subparsers.add_parser('get-progress', description='Remote Installer Client: get-progress') query_parser.add_argument('--uuid', required=True, dest='uuid', help='Installation uuid') query_parser.set_defaults(func=self._query_progress) for name, subp in subparsers.choices.items(): subp.add_argument('--debug', action='store_true', required=False, dest='debug', help = "Debug mode") subp.add_argument('--host', dest='host', required=False, help='Remote installer server address. %s used if not specified.' % Client.DEFAULT_HOST) subp.add_argument('--port', required=False, dest='port', help='Remote installer server port. %s used if not specified.' % Client.DEFAULT_PORT) subp.add_argument('--client-key', required=True, dest='client_key_path', help='Full path to client key') subp.add_argument('--client-certificate', required=True, dest='client_cert_path', help='Full path to client certificate') # To be removed before publishing subp.add_argument('--insecure', required=False, dest='insecure', action='store_true', help='Allow http insecure connection') _args = parser.parse_args(args) return _args def _debug(self, message): if self._args.debug: print "DEBUG: {}".format(str(message)) def _process_args(self, args): if args: if args.client_cert_path: self._client_cert_path = args.client_cert_path if args.client_key_path: self._client_key_path = args.client_key_path if args.port: self._port = args.port if args.host: self._host = args.host def run(self): self._process_args(self._args) self._args.func(self._args) def _query_progress(self, args): self._debug("get-progress") self._uuid = self._args.uuid self._build_request_url('get-progress') request_data = {'uuid': self._uuid} _response = self._post_request(request_data) self._process_response(_response, request_type='get-progress') def _install(self, args): self._debug('install') self._user_config = self._args.userconfig self._image = self._args.image self._build_request_url('install') request_data = {'user-config': self._user_config, 'iso': self._image} _response = self._post_request(request_data) self._process_response(_response, request_type='install') def _cert_tuple(self): cert_tuple = None cert_tuple = (self._client_cert_path, self._client_key_path) return None if None in cert_tuple else cert_tuple def _build_request_url(self, request_type): if request_type == 'install': self._request_url = Client.DEFAULT_INSTALL_URL.format(self._host, self._port) elif request_type == 'get-progress': self._request_url = Client.DEFAULT_INSTALL_STATE_URL.format(self._host, self._port, self._uuid) def _post_request(self, request_data): if self._request_url: response = None cert_tuple = self._cert_tuple() if not self._args.insecure else None try: response = requests.post(self._request_url, json=request_data, cert=cert_tuple) self._debug("post request %s %s %s" % (self._request_url, request_data, cert_tuple)) except Exception as ex: self._debug('Failed to send request: {}'.format(str(ex))) if response.status_code != requests.codes.ok: self._debug('Failed to send requst: %s (%s)', str(response.reason), str(response.status_code)) else: self._debug('response: %s' % response.json()) return response.json() def _process_response(self, response_content, request_type): _json = response_content if request_type == 'install': _uuid = _json.get('uuid') print "{}".format(_uuid) elif request_type == 'get-progress': for key in ['status', 'description', 'percentage']: print "{}".format(str(_json.get(key))) def main(): try: client = Client() client.run() except Exception as exp: print 'Failed with error: %s', str(exp) return 1 if __name__ == '__main__': sys.exit(main())