3 # Copyright 2016 RIFT.IO Inc
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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.
25 from gi
import require_version
26 require_version('RwCal', '1.0')
28 from gi
.repository
import (
36 import rift
.cal
.rwcal_status
as rwcal_status
39 logger
= logging
.getLogger('rwcal.cloudsimproxy')
42 rwstatus_exception_map
= { IndexError: RwTypes
.RwStatus
.NOTFOUND
,
43 KeyError: RwTypes
.RwStatus
.NOTFOUND
,
44 NotImplementedError: RwTypes
.RwStatus
.NOT_IMPLEMENTED
,}
46 rwstatus
= rw_status
.rwstatus_from_exc_map(rwstatus_exception_map
)
47 rwcalstatus
= rwcal_status
.rwcalstatus_from_exc_map(rwstatus_exception_map
)
50 class CloudsimProxyError(Exception):
54 class CloudSimProxyPlugin(GObject
.Object
, RwCal
.Cloud
):
55 DEFAULT_PROXY_HOST
= "localhost"
56 DEFAULT_PROXY_PORT
= 9002
61 self
._port
= CloudSimProxyPlugin
.DEFAULT_PROXY_PORT
65 if self
._session
is None:
66 self
._session
= requests
.Session()
76 if self
._host
is not None:
77 if host
!= self
._host
:
78 raise CloudsimProxyError("Cloudsim host changed during execution")
82 def _set_host_from_account(self
, account
):
83 self
.host
= account
.cloudsim_proxy
.host
85 def _proxy_rpc_call(self
, api
, **kwargs
):
86 url
= "http://{host}:{port}/api/{api}".format(
93 for key
, val
in kwargs
.items():
96 logger
.debug("Sending post to url %s with json data: %s", url
, post_dict
)
97 r
= self
.session
.post(url
, json
=post_dict
)
100 response_dict
= r
.json()
101 logger
.debug("Got json response: %s", response_dict
)
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
)
113 return_vals
.append(value
)
115 logger
.debug("Returning RPC return values: %s", return_vals
)
117 if len(return_vals
) == 0:
120 elif len(return_vals
) == 1:
121 return return_vals
[0]
124 return tuple(return_vals
[1:])
127 def do_init(self
, rwlog_ctx
):
130 category
="rw-cal-log",
131 subcategory
="cloudsimproxy",
136 @rwstatus(ret_on_failure
=[None])
137 def do_get_management_network(self
, account
):
138 """Returns the management network
141 account - a cloud account
148 self
._set
_host
_from
_account
(account
)
149 return self
._proxy
_rpc
_call
("get_management_network")
152 def do_create_tenant(self
, account
, name
):
156 @param name - name to assign to the tenant.
158 raise NotImplementedError()
161 def do_delete_tenant(self
, account
, tenant_id
):
165 @param tenant_id - id of tenant to be deleted.
167 raise NotImplementedError()
169 @rwstatus(ret_on_failure
=[[]])
170 def do_get_tenant_list(self
, account
):
175 raise NotImplementedError()
178 def do_create_role(self
, account
, name
):
182 @param name - name to assign to the role.
184 raise NotImplementedError()
187 def do_delete_role(self
, account
, role_id
):
191 @param role_id - id of role to be deleted.
193 raise NotImplementedError()
195 @rwstatus(ret_on_failure
=[[]])
196 def do_get_role_list(self
, account
):
201 raise NotImplementedError()
203 @rwstatus(ret_on_failure
=[None])
204 def do_create_image(self
, account
, image
):
205 """Create a new image
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.
211 account - a cloud account
212 image - an ImageInfo object
215 An RWErrorDuplicate is raised if create_image is called and there
219 The UUID of the new image
222 self
._set
_host
_from
_account
(account
)
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
)
233 image_dict
= image
.as_dict()
234 del image_dict
["fileno"]
236 image_dict
= image
.as_dict()
238 return self
._proxy
_rpc
_call
("create_image", image
=image_dict
)
241 def do_delete_image(self
, account
, image_id
):
244 This function will remove the record of the image from the CAL and
245 destroy the associated container.
248 account - a cloud account
249 image_id - the UUID of the image to delete
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.
257 self
._set
_host
_from
_account
(account
)
258 return self
._proxy
_rpc
_call
("delete_image")
260 @rwstatus(ret_on_failure
=[None])
261 def do_get_image(self
, account
, image_id
):
262 """Returns the specified image
265 account - a cloud account
266 image_id - the UUID of the image to retrieve
269 An RWErrorNotFound exception is raised if the image_id does not
270 match any of the known images.
276 self
._set
_host
_from
_account
(account
)
277 return self
._proxy
_rpc
_call
("get_image", image_id
=image_id
)
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")
286 def do_create_vm(self
, account
, vm
):
290 vm - the VM info used to define the desire VM
293 An RWErrorFailure is raised if there is not
296 a string containing the unique id of the created VM
299 self
._set
_host
_from
_account
(account
)
300 return self
._proxy
_rpc
_call
("create_vm", vm
=vm
.as_dict())
303 def do_start_vm(self
, account
, vm_id
):
304 """Starts the specified VM
307 vm_id - the id of the vm to start
310 An RWErrorNotFound is raised if the specified vm id is not known to
314 self
._set
_host
_from
_account
(account
)
315 return self
._proxy
_rpc
_call
("start_vm", vm_id
=vm_id
)
318 def do_stop_vm(self
, account
, vm_id
):
319 """Stops the specified VM
322 vm_id - the id of the vm to stop
325 An RWErrorNotFound is raised if the specified vm id is not known to
329 self
._set
_host
_from
_account
(account
)
330 return self
._proxy
_rpc
_call
("stop_vm", vm_id
=vm_id
)
333 def do_delete_vm(self
, account
, vm_id
):
334 """Deletes the specified VM
337 vm_id - the id of the vm to delete
340 An RWErrorNotFound is raised if the specified vm id is not known to
344 self
._set
_host
_from
_account
(account
)
345 return self
._proxy
_rpc
_call
("delete_vm", vm_id
=vm_id
)
348 def do_reboot_vm(self
, account
, vm_id
):
350 reboot a virtual machine.
352 @param vm_id - Instance id of VM to be deleted.
354 self
._set
_host
_from
_account
(account
)
355 return self
._proxy
_rpc
_call
("reboot_vm", vm_id
=vm_id
)
358 def do_get_vm(self
, account
, vm_id
):
359 """Returns the specified VM
362 vm_id - the id of the vm to return
365 An RWErrorNotFound is raised if the specified vm id is not known to
372 self
._set
_host
_from
_account
(account
)
373 return self
._proxy
_rpc
_call
("get_vm", vm_id
=vm_id
)
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
380 a list of VMInfoItem objects
383 self
._set
_host
_from
_account
(account
)
384 return self
._proxy
_rpc
_call
("get_vm_list")
387 def do_create_flavor(self
, account
, flavor
):
391 @param flavor - Flavor object
393 self
._set
_host
_from
_account
(account
)
394 return self
._proxy
_rpc
_call
("create_flavor", flavor
=flavor
.as_dict())
397 def do_delete_flavor(self
, account
, flavor_id
):
401 @param flavor_id - Flavor id to be deleted.
403 self
._set
_host
_from
_account
(account
)
404 return self
._proxy
_rpc
_call
("delete_flavor", flavor_id
=flavor_id
)
406 @rwstatus(ret_on_failure
=[None])
407 def do_get_flavor(self
, account
, flavor_id
):
409 Return the specified flavor
411 @param flavor_id - the id of the flavor to return
413 self
._set
_host
_from
_account
(account
)
414 return self
._proxy
_rpc
_call
("get_flavor", flavor_id
=flavor_id
)
416 @rwstatus(ret_on_failure
=[[]])
417 def do_get_flavor_list(self
, account
):
419 Return a list of flavors
421 self
._set
_host
_from
_account
(account
)
422 return self
._proxy
_rpc
_call
("get_flavor_list")
425 def do_add_host(self
, account
, host
):
426 raise NotImplementedError()
429 def do_remove_host(self
, account
, host_id
):
430 raise NotImplementedError()
432 @rwstatus(ret_on_failure
=[None])
433 def do_get_host(self
, account
, host_id
):
434 raise NotImplementedError()
436 @rwstatus(ret_on_failure
=[[]])
437 def do_get_host_list(self
, account
):
438 raise NotImplementedError()
441 def do_create_port(self
, account
, port
):
442 """Create a port between a network and a virtual machine
445 account - a cloud account
446 port - a description of port to create
449 Raises an RWErrorNotFound exception if either the network or the VM
450 associated with the port cannot be found.
453 the ID of the newly created port.
456 self
._set
_host
_from
_account
(account
)
457 return self
._proxy
_rpc
_call
("create_port", port
=port
.as_dict())
460 def do_delete_port(self
, account
, port_id
):
461 """Delete the specified port
464 account - a cloud account
465 port_id - the ID of the port to delete
468 A RWErrorNotFound exception is raised if the specified port cannot
472 self
._set
_host
_from
_account
(account
)
473 return self
._proxy
_rpc
_call
("delete_port", port_id
=port_id
)
475 @rwstatus(ret_on_failure
=[None])
476 def do_get_port(self
, account
, port_id
):
477 """Return the specified port
480 account - a cloud account
481 port_id - the ID of the port to return
484 A RWErrorNotFound exception is raised if the specified port cannot
491 self
._set
_host
_from
_account
(account
)
492 return self
._proxy
_rpc
_call
("get_port", port_id
=port_id
)
494 @rwstatus(ret_on_failure
=[[]])
495 def do_get_port_list(self
, account
):
496 """Returns a list of ports"""
498 self
._set
_host
_from
_account
(account
)
499 return self
._proxy
_rpc
_call
("get_port_list")
502 def do_create_network(self
, account
, network
):
506 account - a cloud account
507 network - a description of the network to create
510 The ID of the newly created network
513 self
._set
_host
_from
_account
(account
)
514 return self
._proxy
_rpc
_call
("create_network", network
=network
.as_dict())
517 def do_delete_network(self
, account
, network_id
):
520 account - a cloud account
521 network_id - the UUID of the network to delete
524 An RWErrorNotFound is raised if the specified network cannot be
528 self
._set
_host
_from
_account
(account
)
529 return self
._proxy
_rpc
_call
("delete_network", network_id
=network_id
)
531 @rwstatus(ret_on_failure
=[None])
532 def do_get_network(self
, account
, network_id
):
533 """Returns the specified network
536 account - a cloud account
537 network_id - the UUID of the network to delete
540 An RWErrorNotFound is raised if the specified network cannot be
544 The specified network
547 self
._set
_host
_from
_account
(account
)
548 return self
._proxy
_rpc
_call
("get_network", network_id
=network_id
)
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")
556 @rwstatus(ret_on_failure
=[None])
557 def do_validate_cloud_creds(self
, account
):
559 Validates the cloud account credentials for the specified account.
560 If creds are not valid, returns an error code & reason string
562 account - a cloud account to validate
565 Validation Code and Details String
567 self
._set
_host
_from
_account
(account
)
569 status
= RwcalYang
.CloudConnectionStatus()
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
)
576 status
.status
= "success"
577 status
.details
= "Connection was successful"
581 @rwstatus(ret_on_failure
=[""])
582 def do_create_virtual_link(self
, account
, link_params
):
583 """Create a new virtual link
586 account - a cloud account
587 link_params - information that defines the type of VDU to create
592 self
._set
_host
_from
_account
(account
)
593 return self
._proxy
_rpc
_call
("create_virtual_link", link_params
=link_params
.as_dict())
595 @rwstatus(ret_on_failure
=[None])
596 def do_get_virtual_link(self
, account
, link_id
):
597 """Get information about virtual link.
600 account - a cloud account
601 link_id - id for the virtual-link
604 Object of type RwcalYang.VirtualLinkInfoParams
606 self
._set
_host
_from
_account
(account
)
607 return self
._proxy
_rpc
_call
("get_virtual_link", link_id
=link_id
)
609 @rwstatus(ret_on_failure
=[[]])
610 def do_get_virtual_link_list(self
, account
):
611 """Returns the a list of the Virtual links
614 a list of RwcalYang.VirtualLinkInfoParams objects
617 self
._set
_host
_from
_account
(account
)
618 return self
._proxy
_rpc
_call
("get_virtual_link_list")
620 @rwstatus(ret_on_failure
=[None])
621 def do_delete_virtual_link(self
, account
, link_id
):
622 """Delete the virtual link
625 account - a cloud account
626 link_id - id for the virtual-link
628 self
._set
_host
_from
_account
(account
)
629 return self
._proxy
_rpc
_call
("delete_virtual_link", link_id
=link_id
)
631 @rwcalstatus(ret_on_failure
=[""])
632 def do_create_virtual_link(self
, account
, link_params
):
633 """Create a new virtual link
636 account - a cloud account
637 link_params - information that defines the type of VDU to create
642 self
._set
_host
_from
_account
(account
)
643 return self
._proxy
_rpc
_call
("create_virtual_link", link_params
=link_params
.as_dict())
645 @rwcalstatus(ret_on_failure
=[""])
646 def do_create_vdu(self
, account
, vdu_init
):
647 """Create a new virtual deployment unit
650 account - a cloud account
651 vdu_init - information about VDU to create (RwcalYang.VDUInitParams)
656 self
._set
_host
_from
_account
(account
)
657 return self
._proxy
_rpc
_call
("create_vdu", vdu_params
=vdu_init
.as_dict())
660 def do_modify_vdu(self
, account
, vdu_modify
):
661 """Modify Properties of existing virtual deployment unit
664 account - a cloud account
665 vdu_modify - Information about VDU Modification (RwcalYang.VDUModifyParams)
667 self
._set
_host
_from
_account
(account
)
668 return self
._proxy
_rpc
_call
("modify_vdu", vdu_params
=vdu_modify
.as_dict())
671 def do_delete_vdu(self
, account
, vdu_id
):
672 """Delete a virtual deployment unit
675 account - a cloud account
676 vdu_id - id for the vdu to be deleted
681 self
._set
_host
_from
_account
(account
)
682 return self
._proxy
_rpc
_call
("delete_vdu", vdu_id
=vdu_id
)
684 @rwstatus(ret_on_failure
=[None])
685 def do_get_vdu(self
, account
, vdu_id
):
686 """Get information about a virtual deployment unit.
689 account - a cloud account
690 vdu_id - id for the vdu
693 Object of type RwcalYang.VDUInfoParams
695 self
._set
_host
_from
_account
(account
)
696 return self
._proxy
_rpc
_call
("get_vdu", vdu_id
=vdu_id
)
698 @rwstatus(ret_on_failure
=[None])
699 def do_get_vdu_list(self
, account
):
700 """Get information about all the virtual deployment units
703 account - a cloud account
706 A list of objects of type RwcalYang.VDUInfoParams
708 self
._set
_host
_from
_account
(account
)
709 return self
._proxy
_rpc
_call
("get_vdu_list")