pbesa 2.1__py3-none-any.whl → 4.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. pbesa/__init__.py +4 -3
  2. pbesa/cognitive.py +475 -0
  3. pbesa/kernel/__init__.py +4 -6
  4. pbesa/kernel/adapter.py +165 -0
  5. pbesa/kernel/agent.py +558 -0
  6. pbesa/kernel/io/__init__.py +2 -2
  7. pbesa/kernel/io/system_file.py +38 -0
  8. pbesa/kernel/io/tcp_server.py +23 -0
  9. pbesa/kernel/util.py +217 -0
  10. pbesa/kernel/world.py +43 -0
  11. pbesa/mas.py +565 -0
  12. pbesa/remote/__init__.py +5 -0
  13. pbesa/remote/adm_listener.py +44 -0
  14. pbesa/{middleware/remote/AdmListenerHandler.py → remote/adm_listener_handler.py} +74 -57
  15. pbesa/remote/exceptions.py +18 -0
  16. pbesa/remote/remote_adm.py +42 -0
  17. pbesa/{middleware/remote/RemoteAdmHandler.py → remote/remote_adm_handler.py} +109 -83
  18. pbesa/social/__init__.py +4 -0
  19. pbesa/social/collaborative_team.py +299 -0
  20. pbesa/social/delegator.py +81 -0
  21. pbesa/social/delegator_team.py +334 -0
  22. pbesa/social/dialog.py +153 -0
  23. pbesa/social/dispatcher_team.py +319 -0
  24. pbesa/social/templates.py +18 -0
  25. pbesa/social/worker.py +188 -0
  26. {pbesa-2.1.dist-info → pbesa-4.0.0.dist-info}/LICENSE +21 -21
  27. {pbesa-2.1.dist-info → pbesa-4.0.0.dist-info}/LICENSE.txt +21 -21
  28. pbesa-4.0.0.dist-info/METADATA +8 -0
  29. pbesa-4.0.0.dist-info/RECORD +32 -0
  30. {pbesa-2.1.dist-info → pbesa-4.0.0.dist-info}/WHEEL +5 -5
  31. {pbesa-2.1.dist-info → pbesa-4.0.0.dist-info}/top_level.txt +0 -0
  32. pbesa/engine/__init__.py +0 -2
  33. pbesa/engine/bdi/BDIAg.py +0 -42
  34. pbesa/engine/bdi/BDILevel.py +0 -10
  35. pbesa/engine/bdi/BDIMachine.py +0 -116
  36. pbesa/engine/bdi/Goal.py +0 -28
  37. pbesa/engine/bdi/GoalExe.py +0 -36
  38. pbesa/engine/bdi/__init__.py +0 -5
  39. pbesa/engine/rational/ActionExe.py +0 -35
  40. pbesa/engine/rational/Brain.py +0 -10
  41. pbesa/engine/rational/RationalAg.py +0 -43
  42. pbesa/engine/rational/__init__.py +0 -3
  43. pbesa/kernel/adapter/Adapter.py +0 -26
  44. pbesa/kernel/adapter/FileAdapter.py +0 -23
  45. pbesa/kernel/adapter/__init__.py +0 -2
  46. pbesa/kernel/agent/Action.py +0 -19
  47. pbesa/kernel/agent/Agent.py +0 -91
  48. pbesa/kernel/agent/BehaviorExe.py +0 -33
  49. pbesa/kernel/agent/Channel.py +0 -10
  50. pbesa/kernel/agent/World.py +0 -15
  51. pbesa/kernel/agent/__init__.py +0 -5
  52. pbesa/kernel/io/SystemFile.py +0 -13
  53. pbesa/kernel/io/TCPServer.py +0 -4
  54. pbesa/kernel/system/Adm.py +0 -189
  55. pbesa/kernel/system/Directory.py +0 -36
  56. pbesa/kernel/system/__init__.py +0 -2
  57. pbesa/kernel/util/HashTable.py +0 -62
  58. pbesa/kernel/util/Queue.py +0 -231
  59. pbesa/kernel/util/__init__.py +0 -2
  60. pbesa/middleware/__init__.py +0 -3
  61. pbesa/middleware/adapter/GameAdapter.py +0 -64
  62. pbesa/middleware/adapter/MongoAdapter.py +0 -47
  63. pbesa/middleware/adapter/RESTAdapter.py +0 -52
  64. pbesa/middleware/adapter/SubProcessAdapter.py +0 -30
  65. pbesa/middleware/adapter/WSSAdapter.py +0 -89
  66. pbesa/middleware/adapter/WSSNJAdapter.py +0 -51
  67. pbesa/middleware/adapter/WSSNJHandler.py +0 -23
  68. pbesa/middleware/adapter/__init__.py +0 -7
  69. pbesa/middleware/remote/AdmListener.py +0 -17
  70. pbesa/middleware/remote/RemoteAdm.py +0 -17
  71. pbesa/middleware/remote/__init__.py +0 -4
  72. pbesa/middleware/web/WebAgTK.py +0 -15
  73. pbesa/middleware/web/__init__.py +0 -0
  74. pbesa-2.1.dist-info/METADATA +0 -25
  75. pbesa-2.1.dist-info/RECORD +0 -54
pbesa/mas.py ADDED
@@ -0,0 +1,565 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ ------------------------------------------------------------
4
+ -------------------------- PBESA ---------------------------
5
+ ------------------------------------------------------------
6
+
7
+ @autor AKEN & SIDRE
8
+ @version 3.0.1
9
+ @date 27/07/20
10
+ """
11
+
12
+ # --------------------------------------------------------
13
+ # Define resources
14
+ # --------------------------------------------------------
15
+
16
+ import gc
17
+ import json
18
+ import base64
19
+ import socket
20
+ import traceback
21
+ from time import sleep
22
+ from pymongo import MongoClient
23
+ from .kernel.agent import Agent
24
+ from .kernel.agent import Queue
25
+ from .remote.remote_adm import RemoteAdm
26
+ from .remote.adm_listener import AdmListener
27
+ from .kernel.adapter import Adapter, FileAdapter
28
+
29
+ # ----------------------------------------------------------
30
+ # Defines system component exceptions
31
+ # ----------------------------------------------------------
32
+
33
+ class SystemException(Exception):
34
+ """ Base class for exceptions of system """
35
+ pass
36
+
37
+ # --------------------------------------------------------
38
+ # Define Component
39
+ # --------------------------------------------------------
40
+
41
+ class Directory(object):
42
+ """ Directory class """
43
+
44
+ class __Directory:
45
+ """ Directory singleton class """
46
+
47
+ def __init__(self) -> None:
48
+ """ Directory constructor """
49
+ self.container_list = []
50
+ self.agent_list = []
51
+ self.gateway = None
52
+ self.check_to_list = None
53
+
54
+ def add_container(self, container:str) -> None:
55
+ """ Add container to container list
56
+ @param container Container to add
57
+ """
58
+ self.container_list.append(container)
59
+
60
+ def add_agent(self, agent:Agent) -> None:
61
+ """ Add agent to agent list
62
+ @param agent Agent to add
63
+ """
64
+ self.agent_list.append(agent)
65
+
66
+ def get_containers(self) -> list:
67
+ """ Get container list
68
+ @return list Container list
69
+ """
70
+ return self.container_list
71
+
72
+ def get_agents(self) -> list:
73
+ """ Get agent list
74
+ @return list Agent list
75
+ """
76
+ return self.agent_list
77
+
78
+ def set_agent_list(self, agent_list: list) -> None:
79
+ """ Set agent list
80
+ @param agentList Agent list
81
+ """
82
+ self.agent_list = agent_list
83
+
84
+ def get_agent(self, agent_id: str) -> Agent:
85
+ """ Get agent by id
86
+ @param agentID Agent ID
87
+ @return Agent Agent
88
+ """
89
+ for agent in self.agent_list:
90
+ if agent_id == agent['agent']:
91
+ return agent
92
+ return None
93
+
94
+ def reset_agent_list(self) -> None:
95
+ """ Reset agent list """
96
+ self.agent_list = []
97
+
98
+ def remove_agent(self, agent: Agent) -> None:
99
+ """ Remove agent from agent list """
100
+ for ag in self.agent_list:
101
+ if ag['agent'] == agent:
102
+ self.agent_list.remove(ag)
103
+
104
+ def set_check_list(self, gateway:str, check_to_list:list) -> None:
105
+ """ Set check list
106
+ @param gateway Gateway
107
+ @param checkToList Check list
108
+ """
109
+ self.gateway = gateway
110
+ self.check_to_list = check_to_list
111
+
112
+ def check_full(self, container_name:str) -> None:
113
+ """ Check if container name is in check list
114
+ @param containerName Container name
115
+ """
116
+ if self.check_to_list:
117
+ if container_name in self.check_to_list:
118
+ self.check_to_list.remove(container_name)
119
+ if len(self.check_to_list) == 0:
120
+ self.gateway.put(None)
121
+ else:
122
+ raise SystemException('Container name: "%s" does not match' % container_name)
123
+
124
+ # --------------------------------------------------------
125
+ # Singleton
126
+ # --------------------------------------------------------
127
+
128
+ # Singleton instance
129
+ instance = None
130
+
131
+ def __new__(cls) -> object:
132
+ """ Create new instance """
133
+ if not Directory.instance:
134
+ Directory.instance = Directory.__Directory()
135
+ return Directory.instance
136
+
137
+ def __getattr__(self, name: str) -> object:
138
+ """ Get attribute
139
+ @param name Attribute name
140
+ @return object Attribute
141
+ """
142
+ return getattr(self.instance, name)
143
+
144
+ def __setattr__(self, name:str) -> object:
145
+ """ Set attribute
146
+ @param name Attribute name
147
+ @return object Attribute
148
+ """
149
+ return setattr(self.instance, name)
150
+
151
+ # --------------------------------------------------------
152
+ # Define component
153
+ # --------------------------------------------------------
154
+
155
+ class Adm(object):
156
+ """ Represents the agent container manager """
157
+
158
+ class __Adm:
159
+ """ Singleton design pattern """
160
+
161
+ def __init__(self) -> None:
162
+ """ Default constructor """
163
+ self.val = None
164
+ self.conf = None
165
+ self.adapters = {}
166
+ self.agents_table = {}
167
+ self.container_list = []
168
+ self.__db = None
169
+ self.__client = None
170
+
171
+ def __str__(self) -> str:
172
+ """ To string """
173
+ return repr(self) + self.val
174
+
175
+ def connect_database(self) -> None:
176
+ """Connects to mongo database"""
177
+ database_server = 'localhost'
178
+ database_port = 27017
179
+ if 'database_server' in self.conf['persistence']:
180
+ database_server = self.conf['persistence']['database_server']
181
+ if 'database_port' in self.conf['persistence']:
182
+ database_port = self.conf['persistence']['database_port']
183
+ try:
184
+ self.__client = MongoClient(database_server, database_port)
185
+ self.__db = self.__client[self.conf['persistence']['database_name']]
186
+ # Check if exist mas structure
187
+ collist = self.__db.list_collection_names()
188
+ if not "mas" in collist:
189
+ self.__db.create_collection("mas")
190
+ self.__db.create_collection("agents")
191
+ self.__db.create_collection("agenda")
192
+ self.__db.create_collection("work_memory")
193
+ except:
194
+ name = self.conf['persistence']['database_name']
195
+ raise SystemException(f'[Error, connect_database]: Cannot connect to database: {name}')
196
+
197
+ def start(self) -> None:
198
+ """ Default administrator startup """
199
+ self.conf = {
200
+ "user" : "local",
201
+ "host" : "localhost",
202
+ "port" : 8080,
203
+ "remote" : None
204
+ }
205
+
206
+ def start_by_conf(self, conf:dict) -> None:
207
+ """
208
+ Administrator startup by configuration.
209
+ @param conf configuration dictionary or
210
+ configuration file path
211
+ @exceptions SystemException
212
+ """
213
+ if conf:
214
+ # Sets local everoment from dictionary
215
+ if not isinstance(conf, str):
216
+ if 'user' in conf and 'host' in conf and 'port' in conf:
217
+ if conf['user'] and conf['host'] and conf['port']:
218
+ self.conf = conf
219
+ else:
220
+ raise SystemException('[Warn, startByConf]: Configuration parameters cannot be null')
221
+ if 'persistence' in conf:
222
+ if 'database_name' in conf['persistence'] and conf['persistence']['database_name']:
223
+ if 'user' in conf and 'host' in conf and 'port' in conf:
224
+ self.conf = conf
225
+ else:
226
+ self.conf = {
227
+ "user" : "local",
228
+ "host" : "localhost",
229
+ "port" : 8080,
230
+ "remote" : None,
231
+ "persistence": conf['persistence']
232
+ }
233
+ self.connect_database()
234
+ else:
235
+ raise SystemException('[Warn, startByConf]: Name of databes is requerried')
236
+ else:
237
+ CONF_DIR = conf
238
+ fa = FileAdapter({'alias':'JsonAdapter', 'type': 'JSON', 'path': CONF_DIR})
239
+ fa.setup()
240
+ param = fa.request()
241
+ self.conf = param['conf']
242
+ # Sets remote everoment
243
+ if 'remote' in self.conf and self.conf['remote']:
244
+ remote = self.conf['remote']
245
+ if remote['master_mode']:
246
+ self.remoteAdm = RemoteAdm(self.conf['host'], self.conf['port'])
247
+ self.remoteAdm.start()
248
+ else:
249
+ if 'container_name' in self.conf and 'master_host' in remote and 'master_port' in remote:
250
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
251
+ attempts = remote['attempts']
252
+ data = '{"command": "REGISTER", "name":"' + self.conf['container_name'] + '", "host":"' + self.conf['host'] + '", "port":"'+ str(self.conf['port']) +'"}'
253
+ received = None
254
+ for x in range(1, attempts):
255
+ try:
256
+ sock.connect((remote['master_host'], remote['master_port']))
257
+ sock.sendall(bytes(data + "\n", "utf-8"))
258
+ received = str(sock.recv(1024), "utf-8")
259
+ if received == 'ACK' + "\n":
260
+ break
261
+ except:
262
+ sleep(1)
263
+ finally:
264
+ sock.close()
265
+ if received == 'ACK' + "\n":
266
+ admListener = AdmListener(self.conf['host'], self.conf['port'])
267
+ admListener.start()
268
+ else:
269
+ raise SystemException('[Warn, startByConf]: The administrator could not connect with the administrator master')
270
+ else:
271
+ raise SystemException('[Warn, startByConf]: A parameter is missing. The parameters are: {container_name, master_host, master_port}')
272
+ else:
273
+ raise SystemException('[Warn, startByConf]: The parameter "conf" cannot be NoneType')
274
+
275
+ def kill_agent(self, agent:Agent) -> None:
276
+ """
277
+ Remove an agent of the system.
278
+ @param agent Agent to add
279
+ @exceptions SystemException
280
+ """
281
+ del self.agents_table[agent.id]
282
+ directory = Directory()
283
+ directory.remove_agent(agent.id)
284
+ agent.kill()
285
+ if self.conf['remote']:
286
+ remote = self.conf['remote']
287
+ agents = directory.get_agents()
288
+ dto = '{"command":"UPDATE", "agents" : ' + json.dumps(agents, ensure_ascii=False) + '}'
289
+ if remote['mode'] == 'MASTER':
290
+ containers = directory.get_containers()
291
+ for ctn in containers:
292
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
293
+ try:
294
+ sock.connect( (ctn['ip'], int(ctn['port'])) )
295
+ sock.sendall(bytes(dto + "\n", "utf-8"))
296
+ except:
297
+ raise SystemException('[Warn, killAgent]: Could not update container with IP %s' % ctn['ip'])
298
+ finally:
299
+ sock.close()
300
+ else:
301
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
302
+ master = remote['master']
303
+ try:
304
+ sock.connect((master['master_ip'], master['master_port']))
305
+ sock.sendall(bytes(dto + "\n", "utf-8"))
306
+ except:
307
+ raise SystemException('[Warn, killAgent]: Could not update container master')
308
+ finally:
309
+ sock.close()
310
+ agent = None
311
+ gc.collect()
312
+
313
+ def add_agent(self, agent:Agent) -> None:
314
+ """
315
+ Add an agent to the system.
316
+ @param agent Agent to add
317
+ @exceptions SystemException
318
+ """
319
+ if agent.id in self.agents_table:
320
+ raise SystemException('[Warn, addAgent]: Agent ID: "%s" already exists in container' % agent.id)
321
+ else:
322
+ # Register new agent to container
323
+ self.agents_table[agent.id] = agent
324
+ host = self.conf['host']
325
+ port = self.conf['port']
326
+ if 'remote' in self.conf and self.conf['remote']:
327
+ remote = self.conf['remote']
328
+ directory = Directory()
329
+ agentDTO = {'agent': agent.id, 'host': host, 'port' : port}
330
+ directory.add_agent(agentDTO)
331
+ if 'remote' in self.conf and self.conf['remote']:
332
+ remote = self.conf['remote']
333
+ if remote['master_mode']:
334
+ agents = directory.get_agents()
335
+ dto = '{"command":"UPDATE", "agents": ' + json.dumps(agents, ensure_ascii=False) + '}'
336
+ containers = directory.get_containers()
337
+ for ctn in containers:
338
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
339
+ try:
340
+ sock.connect( (ctn['host'], int(ctn['port'])) )
341
+ sock.sendall(bytes(dto + "\n", "utf-8"))
342
+ except:
343
+ raise SystemException('[Warn, addAgent]: Could not update container with %s host' % ctn['host'])
344
+ finally:
345
+ sock.close()
346
+ else:
347
+ dto = '{"command":"ADD", "agent": ' + json.dumps(agentDTO, ensure_ascii=False) + '}'
348
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
349
+ try:
350
+ sock.connect((remote['master_host'], remote['master_port']))
351
+ sock.sendall(bytes(dto + "\n", "utf-8"))
352
+ except:
353
+ raise SystemException('[Warn, addAgent]: Could not update container master')
354
+ finally:
355
+ sock.close()
356
+ # Persist agent information
357
+ if 'persistence' in self.conf:
358
+ agent_count = self.__db["agents"].count_documents({'agent_id': agent.id})
359
+ if agent_count == 0:
360
+ # Create new agent document
361
+ self.__db["agents"].insert_one({'agent_id': agent.id})
362
+ self.__db.create_collection(agent.id)
363
+ # Create new agent state document
364
+ self.__db[agent.id].insert_one(agent.state)
365
+ else:
366
+ # Get current state
367
+ state_list = self.__db[agent.id].find({})
368
+ agent.state = state_list[0]
369
+
370
+ def send_event(self, agent_id:str, event:any, data:any) -> bool:
371
+ """
372
+ Send an event to another agent.
373
+ @param agentID Destination agent ID
374
+ @param event Event to send
375
+ @param data Event data
376
+ @return :bool True if the submission was
377
+ successful | False otherwise
378
+ @exceptions SystemException
379
+ """
380
+ if agent_id in self.agents_table:
381
+ ag = self.agents_table[agent_id]
382
+ ag.send_event(event, data)
383
+ return True
384
+ else:
385
+ if 'remote' in self.conf and self.conf['remote']:
386
+ remote = self.conf['remote']
387
+ attempts = remote['attempts']
388
+ agent = Directory().get_agent(agent_id)
389
+ received = None
390
+ if agent:
391
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
392
+ aux = 'None'
393
+ if data:
394
+ data = json.dumps(data)
395
+ data = data.encode('utf-8')
396
+ data = base64.b64encode(data)
397
+ aux = data.decode('utf-8')
398
+ dto = '{"command": "SENDEVENT", "id":"' + agent_id + '", "event":"' + event + '", "data":"'+ aux +'"}'
399
+ for it in range(1, attempts):
400
+ try:
401
+ sock.connect((agent['host'], agent['port']))
402
+ sock.sendall(bytes(dto + "\n", "utf-8"))
403
+ received = str(sock.recv(1024), "utf-8")
404
+ if received == 'ACK' + "\n":
405
+ break
406
+ except:
407
+ traceback.print_exc()
408
+ sleep(1)
409
+ finally:
410
+ sock.close()
411
+ if received == 'ACK' + "\n":
412
+ return True
413
+ else:
414
+ raise SystemException('[Warn, send_event]: The event could not be sent to the agent with the ID: %s ' % agent_id)
415
+ else:
416
+ raise SystemException('[Warn, send_event]: An agent with the ID %s could not be found in the system' % agent_id)
417
+
418
+ def add_adapter(self, id:str, adapter:Adapter) -> None:
419
+ """ Add an adapter to the system
420
+ @param id Adapter ID
421
+ @param adapter Adapter to add
422
+ """
423
+ self.adapters[id] = adapter
424
+
425
+ def get_adapter(self, id:str) -> Adapter:
426
+ """ Get an adapter from the system
427
+ @param id Adapter ID
428
+ @return Adapter Adapter
429
+ """
430
+ return self.adapters[id]
431
+
432
+ def get_conf(self) -> dict:
433
+ """ Get configuration
434
+ @return dict Configuration
435
+ """
436
+ return self.conf
437
+
438
+ def add_container(self, container:str) -> None:
439
+ """ Add a container to the system
440
+ @param container Container to add
441
+ """
442
+ self.container_list.append(container)
443
+
444
+ def move_agent(self, agent_id:str, container:str) -> None:
445
+ """
446
+ Add an agent to the system.
447
+ @param agent Agent to add
448
+ @exceptions SystemException
449
+ """
450
+ ag = self.agents_table[agent_id]
451
+ ag.finalize()
452
+ dto = ag.toDTO()
453
+ containers = Directory().get_containers()
454
+ for ctn in containers:
455
+ if container == ctn['name']:
456
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
457
+ try:
458
+ sock.connect( (ctn['host'], int(ctn['port'])) )
459
+ sock.sendall(bytes(dto + "\n", "utf-8"))
460
+ except:
461
+ raise SystemException('[Error, moveAgent]: Could not update container with IP %s' % ctn['host'])
462
+ finally:
463
+ sock.close()
464
+ break
465
+ self.agents_table[agent_id] = None
466
+ Directory().remove_agent(agent_id)
467
+
468
+ def set_end_point(self, agent_id:str, socket:socket) -> None:
469
+ """ Set the endpoint of an agent
470
+ @param agentID Agent ID
471
+ @param socket Socket
472
+ """
473
+ ag = self.agents_table[agent_id]
474
+ ag.set_socket(socket)
475
+
476
+ def call_agent(self, agent_id:str, data:any) -> any:
477
+ """
478
+ Call a social agent.
479
+ @param data Call data
480
+ """
481
+ if agent_id in self.agents_table:
482
+ ag = self.agents_table[agent_id]
483
+ if ag.is_social():
484
+ if ag.is_block():
485
+ queue = Queue(1)
486
+ dto = {
487
+ 'dto': data,
488
+ 'gateway': queue
489
+ }
490
+ ag.send_event('delegate', dto)
491
+ result = queue.get()
492
+ queue.task_done()
493
+ return result
494
+ else:
495
+ raise SystemException('[Warn, callAgent]: The "callAgent" method is only for blocking controllers')
496
+ else:
497
+ raise SystemException('[Warn, callAgent]: Only social agents can be invoked in this method')
498
+ else:
499
+ raise SystemException('[Warn, callAgent]: An agent with the ID %s could not be found in the system' % agent_id)
500
+
501
+ def submit_agent(self, agent_id:str, data:any) -> None:
502
+ """
503
+ Call a social agent.
504
+ @param data Call data
505
+ """
506
+ if agent_id in self.agents_table:
507
+ ag = self.agents_table[agent_id]
508
+ if ag.is_social():
509
+ if not ag.is_block():
510
+ ag.send_event('delegate', data)
511
+ else:
512
+ raise SystemException('[Warn, submitAgent]: The "submitAgent" method is only for non-blocking controllers')
513
+ else:
514
+ raise SystemException('[Warn, submitAgent]: Only social agents can be invoked in this method')
515
+ else:
516
+ raise SystemException('[Warn, submitAgent]: An agent with the ID %s could not be found in the system' % agent_id)
517
+
518
+ def wait_full(self, container_list) -> None:
519
+ """ Wait for the container list to be full
520
+ @param containerList Container list
521
+ """
522
+ gateway = Queue(1)
523
+ Directory().set_check_list(gateway, container_list)
524
+ gateway.get()
525
+ gateway.task_done()
526
+
527
+ def destroy(self) -> None:
528
+ """ Destroy the administrator """
529
+ for agent in self.agents_table:
530
+ self.kill_agent(agent)
531
+ self.val = None
532
+ self.conf = None
533
+ self.adapters = None
534
+ self.agents_table = None
535
+ self.container_list = None
536
+ if self.__db:
537
+ self.__client.close()
538
+ self.__client = None
539
+ self.__db = None
540
+ gc.collect()
541
+
542
+ def get_db_connection(self) -> MongoClient:
543
+ """ Get database connection """
544
+ return self.__db
545
+
546
+ # ----------------------------------------------------
547
+ # Defines singleton instance
548
+ # ----------------------------------------------------
549
+
550
+ # Singleton instance
551
+ instance = None
552
+
553
+ def __new__(cls) -> __Adm:
554
+ """ Singleton design pattern """
555
+ if not Adm.instance:
556
+ Adm.instance = Adm.__Adm()
557
+ return Adm.instance
558
+
559
+ def __getattr__(self, name: str) -> any:
560
+ """ Get attribute """
561
+ return getattr(self.instance, name)
562
+
563
+ def __setattr__(self, name: str) -> None:
564
+ """ Set attribute """
565
+ return setattr(self.instance, name)
@@ -0,0 +1,5 @@
1
+ from .adm_listener import AdmListener
2
+ from .adm_listener_handler import AdmListenerHandler
3
+ from .remote_adm import RemoteAdm
4
+ from .remote_adm_handler import RemoteAdmHandler
5
+ from .exceptions import *
@@ -0,0 +1,44 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ ----------------------------------------------------------
4
+ -------------------------- PBESA -------------------------
5
+ ----------------------------------------------------------
6
+
7
+ @autor AKEN
8
+ @version 4.0.0
9
+ @date 08/08/24
10
+ """
11
+
12
+ # --------------------------------------------------------
13
+ # Define resources
14
+ # --------------------------------------------------------
15
+
16
+ import socketserver
17
+ from threading import Thread
18
+ from .adm_listener_handler import AdmListenerHandler
19
+
20
+ # --------------------------------------------------------
21
+ # Define component
22
+ # --------------------------------------------------------
23
+
24
+ class AdmListener(Thread):
25
+ """ ADM Listener class """
26
+
27
+ # IP
28
+ IP = None
29
+ # PORT
30
+ PORT = None
31
+
32
+ def __init__(self, ip:str, port:int) -> None:
33
+ """ Constructor
34
+ :param ip: IP
35
+ :param port: PORT
36
+ """
37
+ self.IP = ip
38
+ self.PORT = port
39
+ super().__init__()
40
+
41
+ def run(self) -> None:
42
+ """ Run """
43
+ server = socketserver.TCPServer((self.IP, self.PORT), AdmListenerHandler)
44
+ server.serve_forever()