server.py 7.5 KB
Newer Older
Ismail Moumni's avatar
Ismail Moumni committed
1
#!/usr/bin/env python3
Ismail Moumni's avatar
Ismail Moumni committed
2
# authors: Julien DAVID & Ismail MOUMNI
Ismail-Moumni's avatar
Ismail-Moumni committed
3
import socket
Ismail Moumni's avatar
Ismail Moumni committed
4
import json
5
import datetime
Ismail Moumni's avatar
Ismail Moumni committed
6
import os
Ismail Moumni's avatar
Ismail Moumni committed
7
import sys
Ismail Moumni's avatar
Ismail Moumni committed
8
sys.path.append(os.path.realpath('../softwares/'))
Ismail Moumni's avatar
Ismail Moumni committed
9
import database as db  # noqa E402
Ismail Moumni's avatar
Ismail Moumni committed
10

11
__RDOS_Dict__ = {"parameters": "request"}
Ismail Moumni's avatar
Ismail Moumni committed
12
13

# tools List
Ismail Moumni's avatar
Ismail Moumni committed
14
# __RDOS_Tool__ = db.list_gen()
Ismail Moumni's avatar
Ismail Moumni committed
15

Ismail Moumni's avatar
Ismail Moumni committed
16

Ismail Moumni's avatar
Ismail Moumni committed
17
18
19
20
21
class RdosServer:

    # Function server_conn creates a socket and listens on port 9393
    # Function input address : SERVER IP ADRESS & Port server Port
    # Function output query send from client to server
Ismail Moumni's avatar
Ismail Moumni committed
22
23
24
25
26
    def server_conn(address, PORT):
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as serv:
            serv.bind((address, PORT))
            # Listening to 5 CLients
            serv.listen(5)
Ismail Moumni's avatar
Ismail Moumni committed
27
            while True:
28
29
30
31
32
33
34
35
                # accepting the connection from client and getting client IP
                conn, addr = serv.accept()
                if conn:
                    print('Connexion acceptee depuis l IP : ', addr)
                    # Receiving Data from Client
                    data = conn.recv(4096)
                    query = (json.loads(data.decode('utf-8')))
                    print("Requete reçu : ", query)
36
                    if (query is not None):
37
                        print(query)
Ismail Moumni's avatar
Ismail Moumni committed
38
39
40
41
42
43
44
45
46
47
48
49
50
                        query_process(conn, query)
                        conn.close()


# Function query_process checks query to get generators or to insert query
# Function takes 2 parameters socket and query (get generator query or to insert in database a new job)
# Function returns generators list to client or returns insert result to client
def query_process(sock: socket, query: dict):
    # Sending GENERATORS
    if (match_query_dict(query, __RDOS_Dict__)):
        response = db.get_generators()
        sock.send(bytes(json.dumps(response), "utf-8"))
        print("database generators ", response)
Ismail Moumni's avatar
Ismail Moumni committed
51

Ismail Moumni's avatar
Ismail Moumni committed
52
    # Sending default generator values
Ismail Moumni's avatar
Ismail Moumni committed
53
54
    elif ((list(query.keys()))[0] == "default"):
        gen = query["default"]
Ismail Moumni's avatar
Ismail Moumni committed
55
        print("generator :", gen)
Ismail Moumni's avatar
Ismail Moumni committed
56
57
58
        resp = client_generator({gen})
        sock.send(bytes(json.dumps(resp), "utf-8"))

Ismail Moumni's avatar
Ismail Moumni committed
59
60
61
62
63
64
65
66
    # Inserting client query in DATABASE
    else:
        print("check", check_and_complete_parameters(query))
        res = db_send_job(sock, query_fields(sock, check_and_complete_parameters(query)))
        print(res)


# Function query_fields generates default fields to insert query send from client to database
Ismail Moumni's avatar
Ismail Moumni committed
67
68
# Function takes 2 parameters addr : IP address of client and data : Generators values
# Function return a valid insert query
Ismail Moumni's avatar
Ismail Moumni committed
69
def query_fields(addr, data):
70
    __RDOS_Tool__ = db.get_generator_list()
71
72
    sa = __RDOS_Tool__.get(list(data.keys())[0])
    lm = list((data.values()))
Ismail Moumni's avatar
Ismail Moumni committed
73
74
    s = {"id": "", "idGenerator": "", "IP": "", "timeSubmitted": "", "timeExecuted": "",
         "timeFinished": "", "status": "", "parametersJSON": "", "directory": "", "url": "", "message": "", "email": ""}
75
76
    s["id"] = str(os.getuid())
    s["idGenerator"] = str(sa)
Ismail Moumni's avatar
Ismail Moumni committed
77
    s["IP"] = addr.getpeername()[0]
78
79
80
    s["timeSubmitted"] = (str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
    s["parametersJSON"] = json.dumps(lm[0])
    return s
Ismail Moumni's avatar
Ismail Moumni committed
81
82


Ismail Moumni's avatar
Ismail Moumni committed
83
84
85
86
87
88
89
# Function Client Generator gets from database a generator paramaters and default parameters
# Function takes a dict generator to send to database
# Function outputs the result from database
def client_generator(generator: dict):
    if generator is not None:
        res = db.getParameters(generator)
        return res
Ismail Moumni's avatar
Ismail Moumni committed
90
    else:
Ismail Moumni's avatar
Ismail Moumni committed
91
92
93
        return Exception("Generator Vide !!")


94
95
96
# Function db_send_job send a query to insert in database by socket
# Function takes a socket and dictionary for input
# Function returns a string if query send
Ismail Moumni's avatar
Ismail Moumni committed
97
98
def db_send_job(s: socket, req: dict):
    if(req is not None):
99
        ins = db.add_job(req)
Ismail Moumni's avatar
Ismail Moumni committed
100
101
102
103
104
105
        s.send(bytes(json.dumps(ins), "utf-8"))
        print("Query send")
    else:
        raise Exception("Empty Query")


106
# Function query_valid matches the query send from client side with the the parameter dict
Ismail Moumni's avatar
Ismail Moumni committed
107
# Function input dictionary from client
Ismail Moumni's avatar
Ismail Moumni committed
108
109
# Function output boolean true if match else False
def query_valid(data: dict):
Ismail Moumni's avatar
Ismail Moumni committed
110
111
    if 'parameters' in data:
        if (data['parameters'] != '') & (len(data) <= 2):
112
113
114
            return True
        else:
            return False
Ismail Moumni's avatar
Ismail Moumni committed
115
116


117
118
119
120
# Function json_to_dict changes a json file into a Dict
# Function json_to_dict returns a dictionary
def json_to_dict(data):
    if data is not None:
Ismail Moumni's avatar
editing    
Ismail Moumni committed
121
        result = json.loads(data)
122
        return result
Ismail Moumni's avatar
Ismail Moumni committed
123
124
    else:
        raise Exception("Dictionnaire Vide!!")
Ismail Moumni's avatar
Ismail Moumni committed
125
126


Ismail Moumni's avatar
Ismail Moumni committed
127
# Function db_req sends a request to get parameters of tools from database
Ismail Moumni's avatar
Ismail Moumni committed
128
# Function takes a dictionary for input
Ismail Moumni's avatar
Ismail Moumni committed
129
130
# Function return a Dict containing tool parameters and default parameters
def db_req(tool: dict):
Ismail Moumni's avatar
Ismail Moumni committed
131
132
133
134
135
    if dict is not None:
        tool_dict = db.getParameters(tool)
        return tool_dict
    else:
        raise Exception("Dictionnaire Vide!!")
Ismail Moumni's avatar
Ismail Moumni committed
136
137


138
# Function missing_keys returns non existing fields in a dict
Ismail Moumni's avatar
Ismail Moumni committed
139
140
141
142
143
144
145
146
147
148
149
150
151
# Function input biblio and dict
# Function returns a list containing missing values
def missing_keys(biblio: dict, gen: dict):
    missing = []
    if(biblio is not None and gen is not None):
        for key in biblio:
            if key not in gen:
                missing.append(key)
        return missing
    else:
        raise Exception("Dictionnaire Vide!!")


Ismail Moumni's avatar
Ismail Moumni committed
152
153
# Function match_query_dict matches two dictionaries
# Function input takes 2 dictionaries to match
154
# Function output return trur if dictionaries matches
Ismail Moumni's avatar
Ismail Moumni committed
155
156
157
158
def match_query_dict(biblio: dict, data: dict):
    if biblio is not None and data is not None:
        return biblio.keys() == data.keys()
    else:
Ismail Moumni's avatar
Ismail Moumni committed
159
        raise ValueError("Dictionnaire Vide ")
Ismail Moumni's avatar
Ismail Moumni committed
160
161


Ismail Moumni's avatar
Ismail Moumni committed
162
# Function check_and_complete_parameters verifies json send from client to server by matching it with database query
Ismail Moumni's avatar
Ismail Moumni committed
163
# Function input takes a dictionary
Ismail Moumni's avatar
editing    
Ismail Moumni committed
164
# Function output returns query if it matches with database query keys
Ismail Moumni's avatar
Ismail Moumni committed
165
def check_and_complete_parameters(data: dict):
Ismail Moumni's avatar
Ismail Moumni committed
166
    if data is not None:
167
168
        tool = list(data.keys())[0]
        s = db.getParameters({tool})
Ismail Moumni's avatar
Ismail Moumni committed
169
170
        parameter = {}
        if s is not None:
Ismail Moumni's avatar
Ismail Moumni committed
171
            # gen = s[0]
172
173
174
175
176
            parameter = s[1]
            q = data.get(tool)
            if match_query_dict(parameter.get(tool), q):
                check_and_replace(data.get(tool), parameter.get(tool))
                return data
Ismail Moumni's avatar
Ismail Moumni committed
177
178
            else:
                raise Exception("Query Doesn't match")
Ismail Moumni's avatar
Ismail Moumni committed
179
        else:
Ismail Moumni's avatar
Ismail Moumni committed
180
            raise Exception("Error Database")
Ismail Moumni's avatar
Ismail Moumni committed
181
    else:
Ismail Moumni's avatar
Ismail Moumni committed
182
        return Exception("Dictionnaire Vide!!", tool)
Ismail Moumni's avatar
Ismail Moumni committed
183
184


Ismail Moumni's avatar
Ismail Moumni committed
185
# check_and_replace checks query with default_parameters of generator and replaces empty values with default_parameters
186
187
# Function input takes 2 dictionaries
# Function output returns matched query
Ismail Moumni's avatar
Ismail Moumni committed
188
189
def check_and_replace(query: dict, default_parameters: dict):
    if query is not None and default_parameters is not None:
190
191
        for a, b in query.items():
            if b == '':
Ismail Moumni's avatar
Ismail Moumni committed
192
193
194
195
                query[a] = default_parameters.get(a)
        return query
    else:
        raise Exception("Dictionnaire Vide!!")
196
197


198
# Function db_generators returns all database generators
Ismail Moumni's avatar
Ismail Moumni committed
199
200
201
# Function takes a dictionary request from client side
# Function returns all database generators or raises an error if request doesn't match
def db_generators(req: dict):
Ismail Moumni's avatar
Ismail Moumni committed
202
203
204
205
206
207
    if req is not None:
        match = {"request": "generators"}
        if(req == match):
            s = db.get_generators()
            return s
        else:
Ismail Moumni's avatar
Ismail Moumni committed
208
            raise Exception("Dictionnaire non Valid")
Ismail Moumni's avatar
Ismail Moumni committed
209
    else:
210
        return Exception("Dictionnaire Vide!!", req)
Ismail Moumni's avatar
Ismail Moumni committed
211
212


Ismail Moumni's avatar
Ismail Moumni committed
213
214
215
if __name__ == '__main__':
    # TEST FOR Docker
    RdosServer.server_conn('127.0.0.1', '9393')