d81c6f367e76156ce5dbe6a9aa883f5a465a332f
[osm/SO.git] / rwcal / plugins / vala / rwcal_cloudsimproxy / rwcal_cloudsimproxy.py
1
2 #
3 # Copyright 2016 RIFT.IO Inc
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
18 import logging
19 import os
20 import shutil
21 import tempfile
22
23 import requests
24
25 from gi import require_version
26 require_version('RwCal', '1.0')
27
28 from gi.repository import (
29 GObject,
30 RwCal,
31 RwTypes,
32 RwcalYang,
33 )
34
35 import rw_status
36 import rift.cal.rwcal_status as rwcal_status
37 import rwlogger
38
39 logger = logging.getLogger('rwcal.cloudsimproxy')
40
41
42 rwstatus_exception_map = { IndexError: RwTypes.RwStatus.NOTFOUND,
43 KeyError: RwTypes.RwStatus.NOTFOUND,
44 NotImplementedError: RwTypes.RwStatus.NOT_IMPLEMENTED,}
45
46 rwstatus = rw_status.rwstatus_from_exc_map(rwstatus_exception_map)
47 rwcalstatus = rwcal_status.rwcalstatus_from_exc_map(rwstatus_exception_map)
48
49
50 class CloudsimProxyError(Exception):
51 pass
52
53
54 class CloudSimProxyPlugin(GObject.Object, RwCal.Cloud):
55 DEFAULT_PROXY_HOST = "localhost"
56 DEFAULT_PROXY_PORT = 9002
57
58 def __init__(self):
59 self._session = None
60 self._host = None
61 self._port = CloudSimProxyPlugin.DEFAULT_PROXY_PORT
62
63 @property
64 def session(self):
65 if self._session is None:
66 self._session = requests.Session()
67
68 return self._session
69
70 @property
71 def host(self):
72 return self._host
73
74 @host.setter
75 def host(self, host):
76 if self._host is not None:
77 if host != self._host:
78 raise CloudsimProxyError("Cloudsim host changed during execution")
79
80 self._host = host
81
82 def _set_host_from_account(self, account):
83 self.host = account.cloudsim_proxy.host
84
85 def _proxy_rpc_call(self, api, **kwargs):
86 url = "http://{host}:{port}/api/{api}".format(
87 host=self._host,
88 port=self._port,
89 api=api,
90 )
91
92 post_dict = {}
93 for key, val in kwargs.items():
94 post_dict[key] = val
95
96 logger.debug("Sending post to url %s with json data: %s", url, post_dict)
97 r = self.session.post(url, json=post_dict)
98 r.raise_for_status()
99
100 response_dict = r.json()
101 logger.debug("Got json response: %s", response_dict)
102
103 return_vals = []
104 for return_val in response_dict["return_vals"]:
105 value = return_val["value"]
106 proto_type = return_val["proto_type"]
107 if proto_type is not None:
108 gi_cls = getattr(RwcalYang, proto_type)
109 logger.debug("Deserializing into %s", proto_type)
110 gi_obj = gi_cls.from_dict(value)
111 value = gi_obj
112
113 return_vals.append(value)
114
115 logger.debug("Returning RPC return values: %s", return_vals)
116
117 if len(return_vals) == 0:
118 return None
119
120 elif len(return_vals) == 1:
121 return return_vals[0]
122
123 else:
124 return tuple(return_vals[1:])
125
126 @rwstatus
127 def do_init(self, rwlog_ctx):
128 logger.addHandler(
129 rwlogger.RwLogger(
130 category="rw-cal-log",
131 subcategory="cloudsimproxy",
132 log_hdl=rwlog_ctx,
133 )
134 )
135
136 @rwstatus(ret_on_failure=[None])
137 def do_get_management_network(self, account):
138 """Returns the management network
139
140 Arguments:
141 account - a cloud account
142
143 Returns:
144 a NetworkInfo object
145
146 """
147
148 self._set_host_from_account(account)
149 return self._proxy_rpc_call("get_management_network")
150
151 @rwstatus
152 def do_create_tenant(self, account, name):
153 """
154 Create a new tenant.
155
156 @param name - name to assign to the tenant.
157 """
158 raise NotImplementedError()
159
160 @rwstatus
161 def do_delete_tenant(self, account, tenant_id):
162 """
163 delete a tenant.
164
165 @param tenant_id - id of tenant to be deleted.
166 """
167 raise NotImplementedError()
168
169 @rwstatus(ret_on_failure=[[]])
170 def do_get_tenant_list(self, account):
171 """
172 List tenants.
173
174 """
175 raise NotImplementedError()
176
177 @rwstatus
178 def do_create_role(self, account, name):
179 """
180 Create a new role.
181
182 @param name - name to assign to the role.
183 """
184 raise NotImplementedError()
185
186 @rwstatus
187 def do_delete_role(self, account, role_id):
188 """
189 delete a role.
190
191 @param role_id - id of role to be deleted.
192 """
193 raise NotImplementedError()
194
195 @rwstatus(ret_on_failure=[[]])
196 def do_get_role_list(self, account):
197 """
198 List roles.
199
200 """
201 raise NotImplementedError()
202
203 @rwstatus(ret_on_failure=[None])
204 def do_create_image(self, account, image):
205 """Create a new image
206
207 Creates a new container based upon the template and tarfile specified.
208 Only one image is currently supported for a given instance of the CAL.
209
210 Arguments:
211 account - a cloud account
212 image - an ImageInfo object
213
214 Raises:
215 An RWErrorDuplicate is raised if create_image is called and there
216 is already an image.
217
218 Returns:
219 The UUID of the new image
220
221 """
222 self._set_host_from_account(account)
223
224 if image.has_field("fileno"):
225 logger.debug("Got fileno for cloudsim image create")
226 new_fileno = os.dup(image.fileno)
227 read_hdl = os.fdopen(new_fileno, 'rb')
228 write_hdl = tempfile.NamedTemporaryFile()
229 image.location = write_hdl.name
230 logger.debug("Created temporary file to store the cloudsim image: %s", image.location)
231 shutil.copyfileobj(read_hdl, write_hdl)
232
233 image_dict = image.as_dict()
234 del image_dict["fileno"]
235 else:
236 image_dict = image.as_dict()
237
238 return self._proxy_rpc_call("create_image", image=image_dict)
239
240 @rwstatus
241 def do_delete_image(self, account, image_id):
242 """Deletes an image
243
244 This function will remove the record of the image from the CAL and
245 destroy the associated container.
246
247 Arguments:
248 account - a cloud account
249 image_id - the UUID of the image to delete
250
251 Raises:
252 An RWErrorNotEmpty exception is raised if there are VMs based on
253 this image (the VMs need to be deleted first). An RWErrorNotFound
254 is raised if the image_id does not match any of the known images.
255
256 """
257 self._set_host_from_account(account)
258 return self._proxy_rpc_call("delete_image")
259
260 @rwstatus(ret_on_failure=[None])
261 def do_get_image(self, account, image_id):
262 """Returns the specified image
263
264 Arguments:
265 account - a cloud account
266 image_id - the UUID of the image to retrieve
267
268 Raises:
269 An RWErrorNotFound exception is raised if the image_id does not
270 match any of the known images.
271
272 Returns:
273 An image object
274
275 """
276 self._set_host_from_account(account)
277 return self._proxy_rpc_call("get_image", image_id=image_id)
278
279 @rwstatus(ret_on_failure=[[]])
280 def do_get_image_list(self, account):
281 """Returns a list of images"""
282 self._set_host_from_account(account)
283 return self._proxy_rpc_call("get_image_list")
284
285 @rwstatus
286 def do_create_vm(self, account, vm):
287 """Create a VM
288
289 Arguments:
290 vm - the VM info used to define the desire VM
291
292 Raises:
293 An RWErrorFailure is raised if there is not
294
295 Returns:
296 a string containing the unique id of the created VM
297
298 """
299 self._set_host_from_account(account)
300 return self._proxy_rpc_call("create_vm", vm=vm.as_dict())
301
302 @rwstatus
303 def do_start_vm(self, account, vm_id):
304 """Starts the specified VM
305
306 Arguments:
307 vm_id - the id of the vm to start
308
309 Raises:
310 An RWErrorNotFound is raised if the specified vm id is not known to
311 this driver.
312
313 """
314 self._set_host_from_account(account)
315 return self._proxy_rpc_call("start_vm", vm_id=vm_id)
316
317 @rwstatus
318 def do_stop_vm(self, account, vm_id):
319 """Stops the specified VM
320
321 Arguments:
322 vm_id - the id of the vm to stop
323
324 Raises:
325 An RWErrorNotFound is raised if the specified vm id is not known to
326 this driver.
327
328 """
329 self._set_host_from_account(account)
330 return self._proxy_rpc_call("stop_vm", vm_id=vm_id)
331
332 @rwstatus
333 def do_delete_vm(self, account, vm_id):
334 """Deletes the specified VM
335
336 Arguments:
337 vm_id - the id of the vm to delete
338
339 Raises:
340 An RWErrorNotFound is raised if the specified vm id is not known to
341 this driver.
342
343 """
344 self._set_host_from_account(account)
345 return self._proxy_rpc_call("delete_vm", vm_id=vm_id)
346
347 @rwstatus
348 def do_reboot_vm(self, account, vm_id):
349 """
350 reboot a virtual machine.
351
352 @param vm_id - Instance id of VM to be deleted.
353 """
354 self._set_host_from_account(account)
355 return self._proxy_rpc_call("reboot_vm", vm_id=vm_id)
356
357 @rwstatus
358 def do_get_vm(self, account, vm_id):
359 """Returns the specified VM
360
361 Arguments:
362 vm_id - the id of the vm to return
363
364 Raises:
365 An RWErrorNotFound is raised if the specified vm id is not known to
366 this driver.
367
368 Returns:
369 a VMInfoItem object
370
371 """
372 self._set_host_from_account(account)
373 return self._proxy_rpc_call("get_vm", vm_id=vm_id)
374
375 @rwstatus(ret_on_failure=[[]])
376 def do_get_vm_list(self, account):
377 """Returns the a list of the VMs known to the driver
378
379 Returns:
380 a list of VMInfoItem objects
381
382 """
383 self._set_host_from_account(account)
384 return self._proxy_rpc_call("get_vm_list")
385
386 @rwstatus
387 def do_create_flavor(self, account, flavor):
388 """
389 create new flavor.
390
391 @param flavor - Flavor object
392 """
393 self._set_host_from_account(account)
394 return self._proxy_rpc_call("create_flavor", flavor=flavor.as_dict())
395
396 @rwstatus
397 def do_delete_flavor(self, account, flavor_id):
398 """
399 Delete flavor.
400
401 @param flavor_id - Flavor id to be deleted.
402 """
403 self._set_host_from_account(account)
404 return self._proxy_rpc_call("delete_flavor", flavor_id=flavor_id)
405
406 @rwstatus(ret_on_failure=[None])
407 def do_get_flavor(self, account, flavor_id):
408 """
409 Return the specified flavor
410
411 @param flavor_id - the id of the flavor to return
412 """
413 self._set_host_from_account(account)
414 return self._proxy_rpc_call("get_flavor", flavor_id=flavor_id)
415
416 @rwstatus(ret_on_failure=[[]])
417 def do_get_flavor_list(self, account):
418 """
419 Return a list of flavors
420 """
421 self._set_host_from_account(account)
422 return self._proxy_rpc_call("get_flavor_list")
423
424 @rwstatus
425 def do_add_host(self, account, host):
426 raise NotImplementedError()
427
428 @rwstatus
429 def do_remove_host(self, account, host_id):
430 raise NotImplementedError()
431
432 @rwstatus(ret_on_failure=[None])
433 def do_get_host(self, account, host_id):
434 raise NotImplementedError()
435
436 @rwstatus(ret_on_failure=[[]])
437 def do_get_host_list(self, account):
438 raise NotImplementedError()
439
440 @rwstatus
441 def do_create_port(self, account, port):
442 """Create a port between a network and a virtual machine
443
444 Arguments:
445 account - a cloud account
446 port - a description of port to create
447
448 Raises:
449 Raises an RWErrorNotFound exception if either the network or the VM
450 associated with the port cannot be found.
451
452 Returns:
453 the ID of the newly created port.
454
455 """
456 self._set_host_from_account(account)
457 return self._proxy_rpc_call("create_port", port=port.as_dict())
458
459 @rwstatus
460 def do_delete_port(self, account, port_id):
461 """Delete the specified port
462
463 Arguments:
464 account - a cloud account
465 port_id - the ID of the port to delete
466
467 Raises:
468 A RWErrorNotFound exception is raised if the specified port cannot
469 be found.
470
471 """
472 self._set_host_from_account(account)
473 return self._proxy_rpc_call("delete_port", port_id=port_id)
474
475 @rwstatus(ret_on_failure=[None])
476 def do_get_port(self, account, port_id):
477 """Return the specified port
478
479 Arguments:
480 account - a cloud account
481 port_id - the ID of the port to return
482
483 Raises:
484 A RWErrorNotFound exception is raised if the specified port cannot
485 be found.
486
487 Returns:
488 The specified port.
489
490 """
491 self._set_host_from_account(account)
492 return self._proxy_rpc_call("get_port", port_id=port_id)
493
494 @rwstatus(ret_on_failure=[[]])
495 def do_get_port_list(self, account):
496 """Returns a list of ports"""
497
498 self._set_host_from_account(account)
499 return self._proxy_rpc_call("get_port_list")
500
501 @rwstatus
502 def do_create_network(self, account, network):
503 """Create a network
504
505 Arguments:
506 account - a cloud account
507 network - a description of the network to create
508
509 Returns:
510 The ID of the newly created network
511
512 """
513 self._set_host_from_account(account)
514 return self._proxy_rpc_call("create_network", network=network.as_dict())
515
516 @rwstatus
517 def do_delete_network(self, account, network_id):
518 """
519 Arguments:
520 account - a cloud account
521 network_id - the UUID of the network to delete
522
523 Raises:
524 An RWErrorNotFound is raised if the specified network cannot be
525 found.
526
527 """
528 self._set_host_from_account(account)
529 return self._proxy_rpc_call("delete_network", network_id=network_id)
530
531 @rwstatus(ret_on_failure=[None])
532 def do_get_network(self, account, network_id):
533 """Returns the specified network
534
535 Arguments:
536 account - a cloud account
537 network_id - the UUID of the network to delete
538
539 Raises:
540 An RWErrorNotFound is raised if the specified network cannot be
541 found.
542
543 Returns:
544 The specified network
545
546 """
547 self._set_host_from_account(account)
548 return self._proxy_rpc_call("get_network", network_id=network_id)
549
550 @rwstatus(ret_on_failure=[[]])
551 def do_get_network_list(self, account):
552 """Returns a list of network objects"""
553 self._set_host_from_account(account)
554 return self._proxy_rpc_call("get_network_list")
555
556 @rwstatus(ret_on_failure=[None])
557 def do_validate_cloud_creds(self, account):
558 """
559 Validates the cloud account credentials for the specified account.
560 If creds are not valid, returns an error code & reason string
561 Arguments:
562 account - a cloud account to validate
563
564 Returns:
565 Validation Code and Details String
566 """
567 self._set_host_from_account(account)
568
569 status = RwcalYang.CloudConnectionStatus()
570 try:
571 self._proxy_rpc_call("get_vm_list")
572 except Exception as e:
573 status.status = "failure"
574 status.details = "connection to cloudsim server failed: %s" % str(e)
575 else:
576 status.status = "success"
577 status.details = "Connection was successful"
578
579 return status
580
581 @rwstatus(ret_on_failure=[""])
582 def do_create_virtual_link(self, account, link_params):
583 """Create a new virtual link
584
585 Arguments:
586 account - a cloud account
587 link_params - information that defines the type of VDU to create
588
589 Returns:
590 The vdu_id
591 """
592 self._set_host_from_account(account)
593 return self._proxy_rpc_call("create_virtual_link", link_params=link_params.as_dict())
594
595 @rwstatus(ret_on_failure=[None])
596 def do_get_virtual_link(self, account, link_id):
597 """Get information about virtual link.
598
599 Arguments:
600 account - a cloud account
601 link_id - id for the virtual-link
602
603 Returns:
604 Object of type RwcalYang.VirtualLinkInfoParams
605 """
606 self._set_host_from_account(account)
607 return self._proxy_rpc_call("get_virtual_link", link_id=link_id)
608
609 @rwstatus(ret_on_failure=[[]])
610 def do_get_virtual_link_list(self, account):
611 """Returns the a list of the Virtual links
612
613 Returns:
614 a list of RwcalYang.VirtualLinkInfoParams objects
615
616 """
617 self._set_host_from_account(account)
618 return self._proxy_rpc_call("get_virtual_link_list")
619
620 @rwstatus(ret_on_failure=[None])
621 def do_delete_virtual_link(self, account, link_id):
622 """Delete the virtual link
623
624 Arguments:
625 account - a cloud account
626 link_id - id for the virtual-link
627 """
628 self._set_host_from_account(account)
629 return self._proxy_rpc_call("delete_virtual_link", link_id=link_id)
630
631 @rwcalstatus(ret_on_failure=[""])
632 def do_create_virtual_link(self, account, link_params):
633 """Create a new virtual link
634
635 Arguments:
636 account - a cloud account
637 link_params - information that defines the type of VDU to create
638
639 Returns:
640 The vdu_id
641 """
642 self._set_host_from_account(account)
643 return self._proxy_rpc_call("create_virtual_link", link_params=link_params.as_dict())
644
645 @rwcalstatus(ret_on_failure=[""])
646 def do_create_vdu(self, account, vdu_init):
647 """Create a new virtual deployment unit
648
649 Arguments:
650 account - a cloud account
651 vdu_init - information about VDU to create (RwcalYang.VDUInitParams)
652
653 Returns:
654 The vdu_id
655 """
656 self._set_host_from_account(account)
657 return self._proxy_rpc_call("create_vdu", vdu_params=vdu_init.as_dict())
658
659 @rwstatus
660 def do_modify_vdu(self, account, vdu_modify):
661 """Modify Properties of existing virtual deployment unit
662
663 Arguments:
664 account - a cloud account
665 vdu_modify - Information about VDU Modification (RwcalYang.VDUModifyParams)
666 """
667 self._set_host_from_account(account)
668 return self._proxy_rpc_call("modify_vdu", vdu_params=vdu_modify.as_dict())
669
670 @rwstatus
671 def do_delete_vdu(self, account, vdu_id):
672 """Delete a virtual deployment unit
673
674 Arguments:
675 account - a cloud account
676 vdu_id - id for the vdu to be deleted
677
678 Returns:
679 None
680 """
681 self._set_host_from_account(account)
682 return self._proxy_rpc_call("delete_vdu", vdu_id=vdu_id)
683
684 @rwstatus(ret_on_failure=[None])
685 def do_get_vdu(self, account, vdu_id, mgmt_network = None):
686 """Get information about a virtual deployment unit.
687
688 Arguments:
689 account - a cloud account
690 vdu_id - id for the vdu
691
692 Returns:
693 Object of type RwcalYang.VDUInfoParams
694 """
695 self._set_host_from_account(account)
696 return self._proxy_rpc_call("get_vdu", vdu_id=vdu_id)
697
698 @rwstatus(ret_on_failure=[None])
699 def do_get_vdu_list(self, account):
700 """Get information about all the virtual deployment units
701
702 Arguments:
703 account - a cloud account
704
705 Returns:
706 A list of objects of type RwcalYang.VDUInfoParams
707 """
708 self._set_host_from_account(account)
709 return self._proxy_rpc_call("get_vdu_list")