blob: c6b9c700dac31de7ad763024dde8d28c3d5cccb7 [file] [log] [blame]
peusterm9c252b62016-01-06 16:59:53 +01001"""
2Distributed Cloud Emulator (dcemulator)
3(c) 2015 by Manuel Peuster <manuel.peuster@upb.de>
4"""
5
6import logging
7import threading
8import zerorpc
9
peustermbd44f4a2016-01-13 14:53:30 +010010logging.basicConfig(level=logging.INFO)
peusterm9c252b62016-01-06 16:59:53 +010011
12
13class ZeroRpcApiEndpoint(object):
peusterme4e89d32016-01-07 09:14:54 +010014 """
15 Simple API endpoint that offers a zerorpc-based
16 interface. This interface will be used by the
17 default command line client.
18 It can be used as a reference to implement
19 REST interfaces providing the same semantics,
20 like e.g. OpenStack compute API.
21 """
peusterm9c252b62016-01-06 16:59:53 +010022
23 def __init__(self, listenip, port):
24 self.dcs = {}
25 self.ip = listenip
26 self.port = port
27 logging.debug("Created API endpoint %s(%s:%d)" % (
28 self.__class__.__name__, self.ip, self.port))
29
30 def connectDatacenter(self, dc):
31 self.dcs[dc.name] = dc
32 logging.info("Connected DC(%s) to API endpoint %s(%s:%d)" % (
33 dc.name, self.__class__.__name__, self.ip, self.port))
34
35 def start(self):
36 thread = threading.Thread(target=self._api_server_thread, args=())
37 thread.daemon = True
38 thread.start()
39 logging.debug("Started API endpoint %s(%s:%d)" % (
40 self.__class__.__name__, self.ip, self.port))
41
42 def _api_server_thread(self):
43 s = zerorpc.Server(MultiDatacenterApi(self.dcs))
44 s.bind("tcp://%s:%d" % (self.ip, self.port))
45 s.run()
46
47
48class MultiDatacenterApi(object):
peusterme4e89d32016-01-07 09:14:54 +010049 """
50 Just pass through the corresponding request to the
51 selected data center. Do not implement provisioning
52 logic here because will will have multiple API
53 endpoint implementations at the end.
54 """
peusterm9c252b62016-01-06 16:59:53 +010055
56 def __init__(self, dcs):
57 self.dcs = dcs
58
59 def compute_action_start(self, dc_name, compute_name):
peusterm4e98b632016-01-12 14:08:07 +010060 # TODO what to return UUID / given name / internal name ?
peusterm70baaf82016-01-06 17:14:40 +010061 logging.debug("RPC CALL: compute start")
peusterm7aae6852016-01-12 14:53:18 +010062 try:
63 return self.dcs.get(dc_name).startCompute(compute_name)
64 except Exception as ex:
65 logging.exception("RPC error.")
66 return ex.message
peusterm9c252b62016-01-06 16:59:53 +010067
68 def compute_action_stop(self, dc_name, compute_name):
peustermbd44f4a2016-01-13 14:53:30 +010069 logging.debug("RPC CALL: compute stop")
peusterm7aae6852016-01-12 14:53:18 +010070 try:
71 return self.dcs.get(dc_name).stopCompute(compute_name)
72 except Exception as ex:
73 logging.exception("RPC error.")
74 return ex.message
peusterm9c252b62016-01-06 16:59:53 +010075
peusterm4e98b632016-01-12 14:08:07 +010076 def compute_list(self, dc_name):
peustermbd44f4a2016-01-13 14:53:30 +010077 logging.debug("RPC CALL: compute list")
peusterm7aae6852016-01-12 14:53:18 +010078 try:
peusterm2ec74e12016-01-13 11:17:53 +010079 if dc_name is None:
80 # return list with all compute nodes in all DCs
81 all_containers = []
82 for dc in self.dcs.itervalues():
83 all_containers += dc.listCompute()
84 return [(c.name, c.getStatus())
85 for c in all_containers]
86 else:
87 # return list of compute nodes for specified DC
88 return [(c.name, c.getStatus())
89 for c in self.dcs.get(dc_name).listCompute()]
peusterm7aae6852016-01-12 14:53:18 +010090 except Exception as ex:
91 logging.exception("RPC error.")
92 return ex.message
peusterm4e98b632016-01-12 14:08:07 +010093
94 def compute_status(self, dc_name, compute_name):
peustermbd44f4a2016-01-13 14:53:30 +010095 logging.debug("RPC CALL: compute status")
peusterm7aae6852016-01-12 14:53:18 +010096 try:
97 return self.dcs.get(
98 dc_name).containers.get(compute_name).getStatus()
99 except Exception as ex:
100 logging.exception("RPC error.")
101 return ex.message