source: ogClient-Git/src/live/ogOperations.py @ bd98dd1

Last change on this file since bd98dd1 was bd98dd1, checked in by OpenGnSys Support Team <soporte-og@…>, 4 years ago

#995 Add link speed in probe responses

Separates probe method into separate ogclient modes (virtual, vdi) so
future supported OS can easily have a tailored probe responses.

Link speed is retrieved using a minimal ethtool command sent using fcntl
module from python.

  • Property mode set to 100644
File size: 10.7 KB
Line 
1#
2# Copyright (C) 2020 Soleta Networks <info@soleta.eu>
3#
4# This program is free software: you can redistribute it and/or modify it under
5# the terms of the GNU Affero General Public License as published by the
6# Free Software Foundation, version 3.
7#
8
9import os
10import json
11import subprocess
12import fcntl, socket, array, struct
13from src.ogClient import ogClient
14from src.ogRest import ThreadState
15
16OG_SHELL = '/bin/bash'
17
18class OgLiveOperations:
19    def __init__(self, config):
20        self._url = config['opengnsys']['url']
21        self._url_log = config['opengnsys']['url_log']
22
23    def _restartBrowser(self, url):
24        try:
25            proc = subprocess.call(["pkill", "-9", "browser"])
26            proc = subprocess.Popen(["browser", "-qws", url])
27        except:
28            raise ValueError('Error: cannot restart browser')
29
30    def parseGetConf(self, out):
31        parsed = {'serial_number': '',
32              'disk_setup': list(),
33              'partition_setup': list()}
34        configs = out.split('\n')
35        for line in configs[:-1]:
36            if 'ser=' in line:
37                parsed['serial_number'] = line.partition('ser=')[2]
38            else:
39                part_setup = {}
40                params = dict(param.split('=') for param in line.split('\t'))
41                # Parse partition configuration.
42                part_setup['disk'] = params['disk']
43                part_setup['partition'] = params['par']
44                part_setup['code'] = params['cpt']
45                part_setup['filesystem'] = params['fsi']
46                part_setup['os'] = params['soi']
47                part_setup['size'] = params['tam']
48                part_setup['used_size'] = params['uso']
49                if part_setup['partition'] == '0':
50                    parsed['disk_setup'].append(part_setup)
51                else:
52                    parsed['partition_setup'].append(part_setup)
53        return parsed
54
55    def poweroff(self):
56        if os.path.exists('/scripts/oginit'):
57            cmd = f'source {ogClient.OG_PATH}etc/preinit/loadenviron.sh; ' \
58                  f'{ogClient.OG_PATH}scripts/poweroff'
59            subprocess.call([cmd], shell=True, executable=OG_SHELL)
60        else:
61            subprocess.call(['/sbin/poweroff'])
62
63    def reboot(self):
64        if os.path.exists('/scripts/oginit'):
65            cmd = f'source {ogClient.OG_PATH}etc/preinit/loadenviron.sh; ' \
66                  f'{ogClient.OG_PATH}scripts/reboot'
67            subprocess.call([cmd], shell=True, executable=OG_SHELL)
68        else:
69            subprocess.call(['/sbin/reboot'])
70
71    def shellrun(self, request, ogRest):
72        cmd = request.getrun()
73        cmds = cmd.split(";|\n\r")
74
75        self._restartBrowser(self._url_log)
76
77        try:
78            ogRest.proc = subprocess.Popen(cmds,
79                               stdout=subprocess.PIPE,
80                               shell=True,
81                               executable=OG_SHELL)
82            (output, error) = ogRest.proc.communicate()
83        except:
84            raise ValueError('Error: Incorrect command value')
85
86        cmd_get_conf = f'{ogClient.OG_PATH}interfaceAdm/getConfiguration'
87        result = subprocess.check_output([cmd_get_conf], shell=True)
88        self._restartBrowser(self._url)
89
90        return output.decode('utf-8')
91
92    def session(self, request, ogRest):
93        disk = request.getDisk()
94        partition = request.getPartition()
95        cmd = f'{ogClient.OG_PATH}interfaceAdm/IniciarSesion {disk} {partition}'
96
97        try:
98            ogRest.proc = subprocess.Popen([cmd],
99                               stdout=subprocess.PIPE,
100                               shell=True,
101                               executable=OG_SHELL)
102            (output, error) = ogRest.proc.communicate()
103        except:
104            raise ValueError('Error: Incorrect command value')
105
106        return output.decode('utf-8')
107
108    def software(self, request, path, ogRest):
109        disk = request.getDisk()
110        partition = request.getPartition()
111
112        self._restartBrowser(self._url_log)
113
114        try:
115            cmd = f'{ogClient.OG_PATH}interfaceAdm/InventarioSoftware {disk} ' \
116                  f'{partition} {path}'
117
118            ogRest.proc = subprocess.Popen([cmd],
119                               stdout=subprocess.PIPE,
120                               shell=True,
121                               executable=OG_SHELL)
122            (output, error) = ogRest.proc.communicate()
123        except:
124            raise ValueError('Error: Incorrect command value')
125
126        self._restartBrowser(self._url)
127
128        software = ''
129        with open(path, 'r') as f:
130            software = f.read()
131        return software
132
133    def hardware(self, path, ogRest):
134        self._restartBrowser(self._url_log)
135
136        try:
137            cmd = f'{ogClient.OG_PATH}interfaceAdm/InventarioHardware {path}'
138            ogRest.proc = subprocess.Popen([cmd],
139                               stdout=subprocess.PIPE,
140                               shell=True,
141                               executable=OG_SHELL)
142            (output, error) = ogRest.proc.communicate()
143        except:
144            raise ValueError('Error: Incorrect command value')
145
146        self._restartBrowser(self._url)
147
148        return output.decode('utf-8')
149
150    def setup(self, request, ogRest):
151        table_type = request.getType()
152        disk = request.getDisk()
153        cache = request.getCache()
154        cache_size = request.getCacheSize()
155        partlist = request.getPartitionSetup()
156        cfg = f'dis={disk}*che={cache}*tch={cache_size}!'
157
158        for part in partlist:
159            cfg += f'par={part["partition"]}*cpt={part["code"]}*' \
160                   f'sfi={part["filesystem"]}*tam={part["size"]}*' \
161                   f'ope={part["format"]}%'
162
163            if ogRest.terminated:
164                break
165
166        cmd = f'{ogClient.OG_PATH}interfaceAdm/Configurar {table_type} {cfg}'
167        try:
168            ogRest.proc = subprocess.Popen([cmd],
169                               stdout=subprocess.PIPE,
170                               shell=True,
171                               executable=OG_SHELL)
172            (output, error) = ogRest.proc.communicate()
173        except:
174            raise ValueError('Error: Incorrect command value')
175
176        cmd_get_conf = f'{ogClient.OG_PATH}interfaceAdm/getConfiguration'
177        result = subprocess.check_output([cmd_get_conf], shell=True)
178        self._restartBrowser(self._url)
179
180        return self.parseGetConf(result.decode('utf-8'))
181
182    def image_restore(self, request, ogRest):
183        disk = request.getDisk()
184        partition = request.getPartition()
185        name = request.getName()
186        repo = request.getRepo()
187        ctype = request.getType()
188        profile = request.getProfile()
189        cid = request.getId()
190        cmd = f'{ogClient.OG_PATH}interfaceAdm/RestaurarImagen {disk} {partition} ' \
191              f'{name} {repo} {ctype}'
192
193        self._restartBrowser(self._url_log)
194
195        try:
196            ogRest.proc = subprocess.Popen([cmd],
197                               stdout=subprocess.PIPE,
198                               shell=True,
199                               executable=OG_SHELL)
200            (output, error) = ogRest.proc.communicate()
201            if (ogRest.proc.returncode):
202                raise Exception
203        except:
204            raise ValueError('Error: Incorrect command value')
205
206        cmd_get_conf = f'{ogClient.OG_PATH}interfaceAdm/getConfiguration'
207        result = subprocess.check_output([cmd_get_conf], shell=True)
208        self._restartBrowser(self._url)
209
210        return output.decode('utf-8')
211
212    def image_create(self, path, request, ogRest):
213        disk = request.getDisk()
214        partition = request.getPartition()
215        name = request.getName()
216        repo = request.getRepo()
217        cmd_software = f'{ogClient.OG_PATH}interfaceAdm/InventarioSoftware {disk} ' \
218                   f'{partition} {path}'
219        cmd_create_image = f'{ogClient.OG_PATH}interfaceAdm/CrearImagen {disk} ' \
220                   f'{partition} {name} {repo}'
221
222        self._restartBrowser(self._url_log)
223
224        try:
225            ogRest.proc = subprocess.Popen([cmd_software],
226                               stdout=subprocess.PIPE,
227                               shell=True,
228                               executable=OG_SHELL)
229            (output, error) = ogRest.proc.communicate()
230        except:
231            raise ValueError('Error: Incorrect command value')
232
233        if ogRest.terminated:
234            return
235
236        try:
237            ogRest.proc = subprocess.Popen([cmd_create_image],
238                               stdout=subprocess.PIPE,
239                               shell=True,
240                               executable=OG_SHELL)
241            ogRest.proc.communicate()
242        except:
243            raise ValueError('Error: Incorrect command value')
244
245        if ogRest.proc.returncode != 0:
246            raise ValueError('Error: Image creation failed')
247
248        with open('/tmp/image.info') as file_info:
249            line = file_info.readline().rstrip()
250
251        image_info = {}
252
253        (image_info['clonator'],
254         image_info['compressor'],
255         image_info['filesystem'],
256         image_info['datasize'],
257         image_info['clientname']) = line.split(':', 5)
258
259        os.remove('/tmp/image.info')
260
261        self._restartBrowser(self._url)
262
263        return image_info
264
265    def refresh(self, ogRest):
266        self._restartBrowser(self._url_log)
267
268        try:
269            cmd = f'{ogClient.OG_PATH}interfaceAdm/getConfiguration'
270            ogRest.proc = subprocess.Popen([cmd],
271                               stdout=subprocess.PIPE,
272                               shell=True,
273                               executable=OG_SHELL)
274            (output, error) = ogRest.proc.communicate()
275        except:
276            raise ValueError('Error: Incorrect command value')
277
278        self._restartBrowser(self._url)
279
280        return self.parseGetConf(output.decode('utf-8'))
281
282    def probe(self, ogRest):
283        def ethtool(interface):
284            try:
285                ETHTOOL_GSET = 0x00000001
286                SIOCETHTOOL = 0x8946
287                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
288                sockfd = sock.fileno()
289                ecmd = array.array(
290                        "B", struct.pack("I39s", ETHTOOL_GSET, b"\x00" * 39)
291                       )
292                interface = interface.encode("utf-8")
293                ifreq = struct.pack("16sP", interface, ecmd.buffer_info()[0])
294                fcntl.ioctl(sockfd, SIOCETHTOOL, ifreq)
295                res = ecmd.tobytes()
296                speed = struct.unpack("12xH29x", res)[0]
297            except IOError:
298                speed = 0
299            finally:
300                sock.close()
301            return speed
302
303        interface = os.environ['DEVICE']
304        speed = ethtool(interface)
305
306        return {'status': 'OPG' if ogRest.state != ThreadState.BUSY else 'BSY',
307                'speed': speed}
Note: See TracBrowser for help on using the repository browser.