Coverage for flexnetsim/controller.py: 100%

71 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-07-22 20:03 +0000

1import os 

2import sys 

3from .network import Network 

4from .connection import Connection 

5from .bitrate import Bitrate 

6from enum import Enum 

7import json 

8 

9 

10class Controller: 

11 """ 

12 This class allows you to create the object Controller and manipulate it by 

13 its methods. The importance of this object is that it handles connection 

14 requests generated inside the Simulator by executing an allocation algorithm 

15 from the Allocator object on the network. Once the process is completed, it 

16 returns the result to the simulator. The Controller is the link between the 

17 Simulator and the Network. 

18 

19 Attributes: 

20 network (Network): Object that contains all the information about the network,  

21 nodes, routes, path length and slots. 

22 

23 allocator (Allocator): The Allocator object handles the assignment of connections  

24 inside a Network. 

25 

26 path (list(list(list))): Paths in the network. These are represented by three lists 

27 [source][destination][path]. Source and destination are Nodes, and [path] is the path 

28 between this two nodes, these nodes may have zero or more available paths. For example: 

29 source node = 2, destination node = 5, and path number 2. The result is the path [2,4,6,8,5]. 

30 

31 connections (list(Connection)): List of Connection objects. Connection contains the  

32 information regarding the connections that are made between the nodes on a network  

33 during the allocation process. 

34 

35 

36 allocationStatus (status): Result of the allocation process, whether the 

37 allocation was succesful or not. This is type allocationStatus, there are 

38 three states: ALLOCATED, NOT_ALLOCATED, NA (not assigned). 

39 

40 """ 

41 status = Enum("status", "ALLOCATED NOT_ALLOCATED NA") 

42 

43 def __init__(self, network: Network = None): 

44 """ 

45 Init method of class Controller. 

46 

47 Args: 

48 network (:obj: Network, optional): Network object with all the information about the network,  

49 nodes, routes, path length and slots. 

50 

51 """ 

52 self.__network = network 

53 self.__allocator = None 

54 self.__path = None 

55 self.__connections = list() 

56 self.__allocationStatus = None 

57 

58 @property 

59 def network(self): 

60 """ 

61 Get or set the attribute network.  

62 """ 

63 return self.__network 

64 

65 @network.setter 

66 def network(self, network): 

67 if type(network) == Network: 

68 self.__network = network 

69 else: 

70 raise AttributeError("You must pass a Network object") 

71 

72 @property 

73 def allocator(self): 

74 """ 

75 Get or set the attribute allocator.  

76 """ 

77 return self.__allocator 

78 

79 @allocator.setter 

80 def allocator(self, allocator): 

81 self.__allocator = allocator 

82 

83 def assignConnection(self, src, dst, bit_rate, id_connection): 

84 """ 

85 Assigns a connection between a source and a destination node through 

86 an allocation method from the Allocator. It creates a connection object 

87 with idConnection as its id, upon which the connections between nodes are 

88 generated. 

89 

90 Args: 

91 src (int): The source node of the connection 

92 

93 dst (int): The destination node of the connection 

94 

95 bit_rate (BitRate): BitRate object of the connection 

96 

97 id_connection (int): The id of the new connection object. It serves to 

98 identify the connection within the attribute connections. 

99 

100 Returns: 

101 The result of the allocation process, whether the 

102 allocation was succesful or not. This is type allocationStatus, there are 

103 three states: ALLOCATED, NOT_ALLOCATED, NA (not assigned). 

104 

105 """ 

106 

107 connection = Connection(id_connection) 

108 self.__allocationStatus, connection = self.__allocator( 

109 src, dst, bit_rate, connection, self.__network, self.__path) 

110 if self.__allocationStatus == Controller.status.ALLOCATED: 

111 self.__connections.append(connection) 

112 for i in range(0, len(connection.links)): 

113 for j in range(0, len(connection.slots[i])): 

114 self.__network.use_slot( 

115 connection.links[i], slot_pos=connection.slots[i][j]) 

116 

117 return self.__allocationStatus 

118 

119 def unassignConnection(self, id_connection): 

120 """ 

121 Unnasigns the requested connection making the resources that were 

122 being used become available again. It deactivates the slots that were 

123 taken in the connection. 

124 

125 Args: 

126 id_connection (int): The id of the new connection object. It serves to 

127 identify the connection within the attribute connections. 

128 

129 Returns: 

130 Number zero if unsuccessful. 

131 

132 """ 

133 

134 for i in range(0, len(self.__connections)): 

135 if self.__connections[i].id == id_connection: 

136 for j in range(0, len(self.__connections[i].links)): 

137 for k in range(0, len(self.__connections[i].slots[j])): 

138 self.__network.unuse_slot( 

139 self.__connections[i].links[j], slot_pos=self.__connections[i].slots[j][k]) 

140 self.__connections.pop(i) 

141 break 

142 return 0 

143 

144 # the file is within a folder called json 

145 def set_paths(self, file_name): 

146 """ 

147 Sets the path attribute from the routes on a JSON file. From this 

148 file, the method creates the paths attribute based on an lists of routes. This 

149 lists contains the source and destination nodes, as well as an list with all 

150 the existing paths between them. The path attribute is important because it is 

151 all the nodes and the respective routes that link them. 

152 

153 In the example below, the network consists of three nodes: 0, 1 and 2. Node 

154 0 is connected to node 1 directly and through node 2, to which it's directly 

155 connected as well. Node 2 is connected directly to node one. All the 

156 connections are unidirectional. 

157 

158 Args: 

159 file_name (str): Name of the JSON file that contains the routes. Example of 

160 this: "routes.json" 

161 

162 Example: 

163 code-block:: JSON 

164 { 

165 "name": "Example routes between 3 nodes", 

166 "alias": "example", 

167 "routes": [ 

168 { 

169 "src": 0, 

170 "dst": 1, 

171 "paths": [ 

172 [ 

173 0, 

174 1 

175 ], 

176 [ 

177 0, 

178 2, 

179 1 

180 ] 

181 ] 

182 }, 

183 { 

184 "src": 0, 

185 "dst": 2, 

186 "paths": [ 

187 [ 

188 0, 

189 2 

190 ] 

191 ] 

192 }, 

193 { 

194 "src": 2, 

195 "dst": 1, 

196 "paths": [ 

197 [ 

198 2, 

199 1 

200 ] 

201 ] 

202 } 

203 ] 

204 }; 

205 

206 """ 

207 

208 self.__path = [] 

209 

210 f = open(file_name) 

211 data = json.load(f) 

212 

213 numberOfNodes = self.__network.node_counter 

214 

215 # set list for paths 

216 for i in range(numberOfNodes): 

217 self.__path.append([]) 

218 for t in range(numberOfNodes): 

219 self.__path[i].append([]) 

220 

221 routesNumber = len(data["routes"]) 

222 

223 for i in range(routesNumber): 

224 pathsNumber = len(data["routes"][i]["paths"]) 

225 src = data["routes"][i]["src"] 

226 dst = data["routes"][i]["dst"] 

227 

228 for m in range(pathsNumber): 

229 self.__path[src][dst].append([]) 

230 

231 for b in range(pathsNumber): 

232 nodesPathNumber = len(data["routes"][i]["paths"][b]) 

233 lastNode = nodesPathNumber - 1 

234 for c in range(lastNode): 

235 actNode = data["routes"][i]["paths"][b][c] 

236 nextNode = data["routes"][i]["paths"][b][c + 1] 

237 idLink = self.__network.is_connected(actNode, nextNode) 

238 self.__path[src][dst][b].append(idLink)