source: ogClient-Git/src/ogClient.py @ 0593119

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

#999 Fix ogClient session command

Disconnect gracefully from ogServer after booting OS, the script to start the
OS calls kexec, so everything is gone after it. For Windows, this results in a
reboot.

This commit also improves the disconnect function to make sure the
disconnection is synchronous.

  • Property mode set to 100644
File size: 3.4 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 errno
10import select
11import socket
12import time
13import email
14import platform
15from io import StringIO
16
17from src.restRequest import *
18from src.ogRest import *
19from enum import Enum
20
21class State(Enum):
22        CONNECTING = 0
23        RECEIVING = 1
24        FORCE_DISCONNECTED = 2
25
26class ogClient:
27        OG_PATH = '/opt/opengnsys/'
28
29        def __init__(self, config):
30                self.CONFIG = config
31
32                self.mode = self.CONFIG['opengnsys']['mode']
33                if self.mode not in {'virtual', 'live'}:
34                        raise ValueError('Mode not supported.')
35
36                if self.CONFIG['samba']['activate']:
37                        assert('user' in self.CONFIG['samba'])
38                        assert('pass' in self.CONFIG['samba'])
39
40                self.ip = self.CONFIG['opengnsys']['ip']
41                self.port = self.CONFIG['opengnsys']['port']
42                self.ogrest = ogRest(self.CONFIG)
43
44        def get_socket(self):
45                return self.sock
46
47        def get_state(self):
48                return self.state
49
50        def connect(self):
51                print('connecting...')
52                self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
53                self.sock.setblocking(0)
54                self.state = State.CONNECTING
55                self.data = ""
56                self.trailer = False
57                self.content_len = 0
58
59                try:
60                        self.sock.connect((self.ip, self.port))
61                except socket.error as err:
62                        if err.errno == errno.EINPROGRESS:
63                                return
64                        elif err.errno == errno.ECONNREFUSED:
65                                return
66
67        def send(self, msg):
68                self.sock.send(bytes(msg, 'utf-8'))
69                return len(msg)
70
71        def connect2(self):
72                try:
73                        self.sock.connect((self.ip, self.port))
74                except socket.error as err:
75                        if err.errno == errno.EISCONN:
76                                print('connected')
77                                self.state = State.RECEIVING
78                        else:
79                                time.sleep(1)
80                                print('connection refused, retrying...')
81                                self.state = State.CONNECTING
82                                self.sock.close()
83                                self.connect()
84
85        def receive(self):
86                try:
87                        data = self.sock.recv(1024).decode('utf-8')
88                except socket.error as err:
89                        data = ''
90                        print('failed to received ' + str(err))
91
92                if len(data) == 0:
93                        self.state = State.CONNECTING
94                        self.sock.close()
95                        self.connect()
96
97                self.data = self.data + data
98                request = restRequest()
99
100                if not self.trailer:
101                        if self.data.find("\r\n") > 0:
102                                # https://stackoverflow.com/questions/4685217/parse-raw-http-headers
103                                request_line, headers_alone = self.data.split('\n', 1)
104                                headers = email.message_from_file(StringIO(headers_alone))
105
106                                if 'content-length' in headers.keys():
107                                        self.content_len = int(headers['content-length'])
108
109                                self.trailer = True
110
111                if self.trailer and len(self.data) >= self.content_len:
112                        request.parser(self.data)
113                        self.ogrest.process_request(request, self)
114
115                        # Cleanup state information from request
116                        self.data = ""
117                        self.content_len = 0
118                        self.trailer = False
119
120        def disconnect(self):
121                self.state = State.FORCE_DISCONNECTED
122                self.sock.shutdown(socket.SHUT_RDWR)
123                self.sock.close()
124
125        def run(self):
126                while 1:
127                        sock = self.get_socket()
128                        state = self.get_state()
129
130                        if state == State.CONNECTING:
131                                readset = [ sock ]
132                                writeset = [ sock ]
133                        elif state == State.FORCE_DISCONNECTED:
134                                return 0
135                        else:
136                                readset = [ sock ]
137                                writeset = [ ]
138
139                        readable, writable, exception = select.select(readset, writeset, [ ])
140                        if state == State.CONNECTING and sock in writable:
141                                self.connect2()
142                        elif state == State.RECEIVING and sock in readable:
143                                self.receive()
144                        else:
145                                print('wrong state, not ever happen!' + str(state))
Note: See TracBrowser for help on using the repository browser.