Merge pull request #136 from stevenvanrossem/master
[osm/vim-emu.git] / src / emuvim / api / zerorpc / compute.py
1 """
2 Copyright (c) 2015 SONATA-NFV and Paderborn University
3 ALL RIGHTS RESERVED.
4
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 Neither the name of the SONATA-NFV [, ANY ADDITIONAL AFFILIATION]
18 nor the names of its contributors may be used to endorse or promote
19 products derived from this software without specific prior written
20 permission.
21
22 This work has been performed in the framework of the SONATA project,
23 funded by the European Commission under Grant number 671517 through
24 the Horizon 2020 and 5G-PPP programmes. The authors would like to
25 acknowledge the contributions of their colleagues of the SONATA
26 partner consortium (www.sonata-nfv.eu).
27 """
28 """
29 Distributed Cloud Emulator (dcemulator)
30 (c) 2015 by Manuel Peuster <manuel.peuster@upb.de>
31 """
32
33 import logging
34 import threading
35 import zerorpc
36
37 logging.basicConfig(level=logging.INFO)
38
39
40 class ZeroRpcApiEndpoint(object):
41 """
42 Simple API endpoint that offers a zerorpc-based
43 interface. This interface will be used by the
44 default command line client.
45 It can be used as a reference to implement
46 REST interfaces providing the same semantics,
47 like e.g. OpenStack compute API.
48 """
49
50 def __init__(self, listenip, port):
51 self.dcs = {}
52 self.ip = listenip
53 self.port = port
54 logging.debug("Created API endpoint %s(%s:%d)" % (
55 self.__class__.__name__, self.ip, self.port))
56
57 def connectDatacenter(self, dc):
58 self.dcs[dc.label] = dc
59 logging.info("Connected DC(%s) to API endpoint %s(%s:%d)" % (
60 dc.label, self.__class__.__name__, self.ip, self.port))
61
62 def start(self):
63 thread = threading.Thread(target=self._api_server_thread, args=())
64 thread.daemon = True
65 thread.start()
66 logging.debug("Started API endpoint %s(%s:%d)" % (
67 self.__class__.__name__, self.ip, self.port))
68
69 def _api_server_thread(self):
70 s = zerorpc.Server(MultiDatacenterApi(self.dcs))
71 s.bind("tcp://%s:%d" % (self.ip, self.port))
72 s.run()
73
74
75 class MultiDatacenterApi(object):
76 """
77 Just pass through the corresponding request to the
78 selected data center. Do not implement provisioning
79 logic here because will will have multiple API
80 endpoint implementations at the end.
81 """
82
83 def __init__(self, dcs):
84 self.dcs = dcs
85
86 def compute_action_start(self, dc_label, compute_name, image, network, command):
87 """
88 Start a new compute instance: A docker container (note: zerorpc does not support keyword arguments)
89 :param dc_label: name of the DC
90 :param compute_name: compute container name
91 :param image: image name
92 :param command: command to execute
93 :param network: list of all interface of the vnf, with their parameters (id=id1,ip=x.x.x.x/x),...
94 :return: networks list({"id":"input","ip": "10.0.0.254/8"}, {"id":"output","ip": "11.0.0.254/24"})
95 """
96 # TODO what to return UUID / given name / internal name ?
97 logging.debug("RPC CALL: compute start")
98 try:
99 c = self.dcs.get(dc_label).startCompute(
100 compute_name, image=image, command=command, network=network)
101 #return str(c.name)
102 # return docker inspect dict
103 return c.getStatus()
104 except Exception as ex:
105 logging.exception("RPC error.")
106 return ex.message
107
108 def compute_action_stop(self, dc_label, compute_name):
109 logging.debug("RPC CALL: compute stop")
110 try:
111 return self.dcs.get(dc_label).stopCompute(compute_name)
112 except Exception as ex:
113 logging.exception("RPC error.")
114 return ex.message
115
116 def compute_list(self, dc_label):
117 logging.debug("RPC CALL: compute list")
118 try:
119 if dc_label is None:
120 # return list with all compute nodes in all DCs
121 all_containers = []
122 for dc in self.dcs.itervalues():
123 all_containers += dc.listCompute()
124 return [(c.name, c.getStatus())
125 for c in all_containers]
126 else:
127 # return list of compute nodes for specified DC
128 return [(c.name, c.getStatus())
129 for c in self.dcs.get(dc_label).listCompute()]
130 except Exception as ex:
131 logging.exception("RPC error.")
132 return ex.message
133
134 def compute_status(self, dc_label, compute_name):
135 logging.debug("RPC CALL: compute status")
136 try:
137 return self.dcs.get(
138 dc_label).containers.get(compute_name).getStatus()
139 except Exception as ex:
140 logging.exception("RPC error.")
141 return ex.message
142
143 def datacenter_list(self):
144 logging.debug("RPC CALL: datacenter list")
145 try:
146 return [d.getStatus() for d in self.dcs.itervalues()]
147 except Exception as ex:
148 logging.exception("RPC error.")
149 return ex.message
150
151 def datacenter_status(self, dc_label):
152 logging.debug("RPC CALL: datacenter status")
153 try:
154 return self.dcs.get(dc_label).getStatus()
155 except Exception as ex:
156 logging.exception("RPC error.")
157 return ex.message
158
159