Restructure server
[ta/remote-installer.git] / src / remoteinstaller / client / remote-installer
1 #! /usr/bin/python
2
3 # Copyright 2019 Nokia
4
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 #     http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 import sys
18 import argparse
19 import requests
20 import json
21
22
23 class Client(object):
24     DEFAULT_INSTALL_URL = 'http://{}:{}/v1/installations/'
25     DEFAULT_INSTALL_STATE_URL = 'http://{}:{}/v1/installations/{}/state'
26     DEFAULT_PATH = '/opt/remoteinstaller'
27     DEFAULT_PORT = '15101'
28     DEFAULT_HOST = 'localhost'
29
30     def __init__(self):
31         self._verbose = None
32         self._host = Client.DEFAULT_HOST
33         self._port = Client.DEFAULT_PORT
34         self._client_cert_path = None
35         self._client_key_path = None
36         self._user_config = None
37         self._image = None
38         self._request_url = None
39         self._uuid = None
40         self._parser = None
41         self._args = self._parse_args(sys.argv[1:])
42         self._debug(self._args)
43
44     def _parse_args(self, args):
45         parser = argparse.ArgumentParser(description='Remote Installer Client',add_help=False)
46         self._parser = parser
47         subparsers = parser.add_subparsers(dest="subparsers")
48
49         install_parser = subparsers.add_parser('install', description='Remote Installer Client: intall')
50         install_parser.add_argument('--image',
51                             dest='image', required=True,
52                             help='Full path to installation iso image')
53         install_parser.add_argument('--user-config', required=True,
54                             dest='userconfig',
55                             help='Full path to user config')
56         install_parser.set_defaults(func=self._install)
57
58         query_parser = subparsers.add_parser('get-progress', description='Remote Installer Client: get-progress')
59         query_parser.add_argument('--uuid', required=True,
60                             dest='uuid',
61                             help='Installation uuid')
62         query_parser.set_defaults(func=self._query_progress)
63
64         for name, subp in subparsers.choices.items():
65             subp.add_argument('--debug', action='store_true',
66                                 required=False, dest='debug', help = "Debug mode")
67
68             subp.add_argument('--host',
69                                 dest='host', required=False,
70                                 help='Remote installer server address. %s used if not specified.' % Client.DEFAULT_HOST)
71
72             subp.add_argument('--port', required=False,
73                                 dest='port',
74                                 help='Remote installer server port. %s used if not specified.' % Client.DEFAULT_PORT)
75
76             subp.add_argument('--client-key', required=True,
77                                 dest='client_key_path',
78                                 help='Full path to client key')
79
80             subp.add_argument('--client-certificate', required=True,
81                                 dest='client_cert_path',
82                                 help='Full path to client certificate')
83
84             # To be removed before publishing
85             subp.add_argument('--insecure', required=False,
86                                 dest='insecure', action='store_true',
87                                 help='Allow http insecure connection')
88
89         _args = parser.parse_args(args)
90         return _args
91
92     def _debug(self, message):
93         if self._args.debug:
94             print "DEBUG: {}".format(str(message))
95
96     def _process_args(self, args):
97         if args:
98             if args.client_cert_path:
99                 self._client_cert_path = args.client_cert_path
100             if args.client_key_path:
101                 self._client_key_path = args.client_key_path
102             if args.port:
103                 self._port = args.port
104             if args.host:
105                 self._host = args.host
106
107     def run(self):
108         self._process_args(self._args)
109         self._args.func(self._args)
110
111     def _query_progress(self, args):
112         self._debug("get-progress")
113         self._uuid = self._args.uuid
114         self._build_request_url('get-progress')
115         request_data = {'uuid': self._uuid}
116         _response = self._post_request(request_data)
117         self._process_response(_response, request_type='get-progress')
118
119     def _install(self, args):
120         self._debug('install')
121         self._user_config = self._args.userconfig
122         self._image = self._args.image
123         self._build_request_url('install')
124         request_data = {'user-config': self._user_config, 'iso': self._image}
125         _response = self._post_request(request_data)
126         self._process_response(_response, request_type='install')
127
128     def _cert_tuple(self):
129         cert_tuple = None
130         cert_tuple = (self._client_cert_path, self._client_key_path)
131         return None if None in cert_tuple else cert_tuple
132
133     def _build_request_url(self, request_type):
134         if request_type == 'install':
135             self._request_url = Client.DEFAULT_INSTALL_URL.format(self._host, self._port)
136         elif request_type == 'get-progress':
137             self._request_url = Client.DEFAULT_INSTALL_STATE_URL.format(self._host, self._port, self._uuid)
138
139     def _post_request(self, request_data):
140         if self._request_url:
141             response = None
142             cert_tuple = self._cert_tuple() if not self._args.insecure else None
143             try:
144                 response = requests.post(self._request_url, json=request_data, cert=cert_tuple)
145                 self._debug("post request %s %s %s" % (self._request_url, request_data, cert_tuple))
146             except Exception as ex:
147                 self._debug('Failed to send request: {}'.format(str(ex)))
148
149             if response.status_code != requests.codes.ok:
150                 self._debug('Failed to send requst: %s (%s)', str(response.reason), str(response.status_code))
151             else:
152                 self._debug('response: %s' % response.json())
153                 return response.json()
154
155     def _process_response(self, response_content, request_type):
156         _json = response_content
157         if request_type == 'install':
158             _uuid = _json.get('uuid')
159             print "{}".format(_uuid)
160         elif request_type == 'get-progress':
161             for key in ['status', 'description', 'percentage']:
162                 print "{}".format(str(_json.get(key)))
163
164 def main():
165     try:
166         client = Client()
167         client.run()
168     except Exception as exp:
169         print 'Failed with error: %s', str(exp)
170         return 1
171
172 if __name__ == '__main__':
173     sys.exit(main())