server.py 6.87 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__ = {}
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
51
52
53
54
55
56
57
58
                        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)
    # 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
59
60
# 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
61
def query_fields(addr, data):
62
    __RDOS_Tool__ = db.get_generator_list()
63
64
    sa = __RDOS_Tool__.get(list(data.keys())[0])
    lm = list((data.values()))
Ismail Moumni's avatar
Ismail Moumni committed
65
66
    s = {"id": "", "idGenerator": "", "IP": "", "timeSubmitted": "", "timeExecuted": "",
         "timeFinished": "", "status": "", "parametersJSON": "", "directory": "", "url": "", "message": "", "email": ""}
67
68
    s["id"] = str(os.getuid())
    s["idGenerator"] = str(sa)
Ismail Moumni's avatar
Ismail Moumni committed
69
    s["IP"] = addr.getpeername()[0]
70
71
72
    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
73
74


75
76
77
# 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
78
79
def db_send_job(s: socket, req: dict):
    if(req is not None):
80
        ins = db.add_job(req)
Ismail Moumni's avatar
Ismail Moumni committed
81
82
83
84
85
86
        s.send(bytes(json.dumps(ins), "utf-8"))
        print("Query send")
    else:
        raise Exception("Empty Query")


87
# Function query_valid matches the query send from client side with the the parameter dict
Ismail Moumni's avatar
Ismail Moumni committed
88
# Function input dictionary from client
Ismail Moumni's avatar
Ismail Moumni committed
89
90
# Function output boolean true if match else False
def query_valid(data: dict):
Ismail Moumni's avatar
Ismail Moumni committed
91
92
    if 'parameters' in data:
        if (data['parameters'] != '') & (len(data) <= 2):
93
94
95
            return True
        else:
            return False
Ismail Moumni's avatar
Ismail Moumni committed
96
97


98
99
100
101
# 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
102
        result = json.loads(data)
103
        return result
Ismail Moumni's avatar
Ismail Moumni committed
104
105
    else:
        raise Exception("Dictionnaire Vide!!")
Ismail Moumni's avatar
Ismail Moumni committed
106
107


Ismail Moumni's avatar
Ismail Moumni committed
108
# Function db_req sends a request to get parameters of tools from database
Ismail Moumni's avatar
Ismail Moumni committed
109
# Function takes a dictionary for input
Ismail Moumni's avatar
Ismail Moumni committed
110
111
# Function return a Dict containing tool parameters and default parameters
def db_req(tool: dict):
Ismail Moumni's avatar
Ismail Moumni committed
112
113
114
115
116
    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
117
118


119
# Function missing_keys returns non existing fields in a dict
Ismail Moumni's avatar
Ismail Moumni committed
120
121
122
123
124
125
126
127
128
129
130
131
132
# 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
133
134
# Function match_query_dict matches two dictionaries
# Function input takes 2 dictionaries to match
135
# Function output return trur if dictionaries matches
Ismail Moumni's avatar
Ismail Moumni committed
136
137
138
139
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
140
        raise ValueError("Dictionnaire Vide ")
Ismail Moumni's avatar
Ismail Moumni committed
141
142


Ismail Moumni's avatar
Ismail Moumni committed
143
# 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
144
# Function input takes a dictionary
Ismail Moumni's avatar
editing    
Ismail Moumni committed
145
# Function output returns query if it matches with database query keys
Ismail Moumni's avatar
Ismail Moumni committed
146
def check_and_complete_parameters(data: dict):
Ismail Moumni's avatar
Ismail Moumni committed
147
    if data is not None:
148
149
        tool = list(data.keys())[0]
        s = db.getParameters({tool})
Ismail Moumni's avatar
Ismail Moumni committed
150
151
        parameter = {}
        if s is not None:
Ismail Moumni's avatar
Ismail Moumni committed
152
            # gen = s[0]
153
154
155
156
157
            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
158
159
            else:
                raise Exception("Query Doesn't match")
Ismail Moumni's avatar
Ismail Moumni committed
160
        else:
Ismail Moumni's avatar
Ismail Moumni committed
161
            raise Exception("Error Database")
Ismail Moumni's avatar
Ismail Moumni committed
162
    else:
Ismail Moumni's avatar
Ismail Moumni committed
163
        return Exception("Dictionnaire Vide!!", tool)
Ismail Moumni's avatar
Ismail Moumni committed
164
165


Ismail Moumni's avatar
Ismail Moumni committed
166
# check_and_replace checks query with default_parameters of generator and replaces empty values with default_parameters
167
168
# Function input takes 2 dictionaries
# Function output returns matched query
Ismail Moumni's avatar
Ismail Moumni committed
169
170
def check_and_replace(query: dict, default_parameters: dict):
    if query is not None and default_parameters is not None:
171
172
        for a, b in query.items():
            if b == '':
Ismail Moumni's avatar
Ismail Moumni committed
173
174
175
176
                query[a] = default_parameters.get(a)
        return query
    else:
        raise Exception("Dictionnaire Vide!!")
177
178


179
# Function db_generators returns all database generators
Ismail Moumni's avatar
Ismail Moumni committed
180
181
182
# 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
183
184
185
186
187
188
    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
189
            raise Exception("Dictionnaire non Valid")
Ismail Moumni's avatar
Ismail Moumni committed
190
    else:
191
        return Exception("Dictionnaire Vide!!", req)
Ismail Moumni's avatar
Ismail Moumni committed
192
193


Ismail Moumni's avatar
Ismail Moumni committed
194
195
196
if __name__ == '__main__':
    # TEST FOR Docker
    RdosServer.server_conn('127.0.0.1', '9393')