-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmaster.py
183 lines (126 loc) · 4.45 KB
/
master.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
import socket
from time import sleep
import paramiko
SSH_HOST = "localhost"
SSH_USERNAME = "comnetsemu"
SSH_PASSWORD = "comnetsemu"
SSH_PORT = 2222
SOCKET_HOST = "127.0.0.1"
SOCKET_PORT = 2223
LAUNCHER_PATH = "<LAUNCHER PATH>"
LAUNCHER_PATH = LAUNCHER_PATH if LAUNCHER_PATH.endswith(".py") else join(LAUNCHER_PATH,"launcher.py")
def connect():
global SOCKET_HOST, SOCKET_PORT
# Connect to mininet socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((SOCKET_HOST, SOCKET_PORT))
return s
def disconnect(s: socket.socket):
# Disconnect
s.close()
def send(s: socket.socket, message: str, wait: bool = False):
# Send message
message = f"{message}"
s.sendall(message.encode())
if wait: # If True, it will wait until an ack is received
s.recv(1024)
def isConnected(s: socket.socket):
# Test connection with the mininet socket
try:
send(s,f"ping",True)
return True
except Exception as e:
return False
def _exec_command(s: socket.socket, command: str):
global SSH_HOST, SSH_USERNAME, SSH_PASSWORD, SSH_PORT
# Parse command
if command == "start":
# If connected, return
if isConnected(s):
return
disconnect(s)
# Since the mininet socket isn't running, we establish a connection with the VM via ssh
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(SSH_HOST, username=SSH_USERNAME, password=SSH_PASSWORD, port=SSH_PORT)
# Execute launcher.py (start mininet network)
ssh.exec_command(f"sudo python3 {LAUNCHER_PATH} &")
ssh.close()
# Wait for the mininet socket
while True:
s = connect()
if isConnected(s):
break
disconnect(s)
sleep(1)
# Commands sequence terminated
send(s,"#")
elif command == "stop":
# If not connected, return
if not isConnected(s):
return
# Send stop message
send(s,"stop",True)
# Wait until disconnected
while isConnected(s):
sleep(1)
elif command == "ping":
# Ping connection
result = str(isConnected(s)).lower()
if result == "true":
send(s,"#")
return result
elif command.startswith("changeScenario="):
# Change scenario
args = command.replace("changeScenario=","")
# Check if the provided scenario id is valid
if type(args) == str:
if not args.isnumeric():
return
elif type(args) != int:
return
if int(args) not in range(0,5):
return
if not isConnected(s):
return
send(s,f"scenarioId={args[0]}",True)
send(s,"#")
elif command == "mapNetworkScenarios":
# If not connected return
if not isConnected(s):
return ""
send(s,"mapNetworkScenarios")
# Since the network map can have an high size,
# the reading of a message is set to non blocking.
# In this way it's possible to receive data and stop once a message
# is followed by an exception (empty buffer, there is no data to read)
s.setblocking(0)
# Wait for response
prev = False
result = ""
while True:
try:
data = s.recv(1024)
except BlockingIOError: # No data available
# Close if i have already read something
if prev:
break
sleep(0.5)
continue
# Store all the received data
if len(data.decode()):
result = result + data.decode()
prev = True
send(s,"#")
return result
def exec_command(command: str):
try:
s = connect()
result = _exec_command(s,command)
disconnect(s) # Disconnect once finished
except ConnectionRefusedError:
result = "-" # VM not started
except Exception as e:
print(e) # For debug
result = "-"
return result