1 # -*- coding: utf-8 -*-
4 # Copyright 2015 Telefonica Investigacion y Desarrollo, S.A.U.
5 # This file is part of openmano
8 # Licensed under the Apache License, Version 2.0 (the "License"); you may
9 # not use this file except in compliance with the License. You may obtain
10 # a copy of the License at
12 # http://www.apache.org/licenses/LICENSE-2.0
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17 # License for the specific language governing permissions and limitations
20 # For those usages not covered by the Apache License, Version 2.0 please
21 # contact with: nfvlabs@tid.es
25 vimconnector implements all the methods to interact with openvim using the openvim API.
27 __author__
= "Alfonso Tierno, Gerardo Garcia"
28 __date__
= "$26-aug-2014 11:09:29$"
33 from urllib
.parse
import quote
35 from jsonschema
import exceptions
as js_e
, validate
as js_v
36 from osm_ro
.openmano_schemas
import (
44 from osm_ro_plugin
import vimconn
48 """contain the openvim virtual machine status to openmano status"""
49 vmStatus2manoFormat
= {
52 "SUSPENDED": "SUSPENDED",
53 "INACTIVE": "INACTIVE",
58 netStatus2manoFormat
= {
60 "INACTIVE": "INACTIVE",
82 "required": ["id", "name"],
90 "required": ["id", "name"],
92 new_host_response_schema
= {
93 "title": "host response information schema",
94 "$schema": "http://json-schema.org/draft-04/schema#",
96 "properties": {"host": host_schema
},
98 "additionalProperties": False,
101 get_images_response_schema
= {
102 "title": "openvim images response information schema",
103 "$schema": "http://json-schema.org/draft-04/schema#",
108 "items": image_schema
,
111 "required": ["images"],
112 "additionalProperties": False,
115 get_hosts_response_schema
= {
116 "title": "openvim hosts response information schema",
117 "$schema": "http://json-schema.org/draft-04/schema#",
122 "items": host_schema
,
125 "required": ["hosts"],
126 "additionalProperties": False,
129 get_host_detail_response_schema
= (
130 new_host_response_schema
# TODO: Content is not parsed yet
133 get_server_response_schema
= {
134 "title": "openvim server response information schema",
135 "$schema": "http://json-schema.org/draft-04/schema#",
140 "items": server_schema
,
143 "required": ["servers"],
144 "additionalProperties": False,
147 new_tenant_response_schema
= {
148 "title": "tenant response information schema",
149 "$schema": "http://json-schema.org/draft-04/schema#",
156 "name": nameshort_schema
,
157 "description": description_schema
,
158 "enabled": {"type": "boolean"},
163 "required": ["tenant"],
164 "additionalProperties": False,
167 new_network_response_schema
= {
168 "title": "network response information schema",
169 "$schema": "http://json-schema.org/draft-04/schema#",
179 "enum": ["bridge_man", "bridge_data", "data", "ptp"],
181 "shared": {"type": "boolean"},
182 "tenant_id": id_schema
,
183 "admin_state_up": {"type": "boolean"},
184 "vlan": vlan1000_schema
,
189 "required": ["network"],
190 "additionalProperties": False,
194 # get_network_response_schema = {
195 # "title":"get network response information schema",
196 # "$schema": "http://json-schema.org/draft-04/schema#",
203 # "name":name_schema,
204 # "type":{"type":"string", "enum":["bridge_man","bridge_data","data", "ptp"]},
205 # "shared":{"type":"boolean"},
206 # "tenant_id":id_schema,
207 # "admin_state_up":{"type":"boolean"},
208 # "vlan":vlan1000_schema
213 # "required": ["network"],
214 # "additionalProperties": False
218 new_port_response_schema
= {
219 "title": "port response information schema",
220 "$schema": "http://json-schema.org/draft-04/schema#",
231 "required": ["port"],
232 "additionalProperties": False,
235 get_flavor_response_schema
= {
236 "title": "openvim flavors response information schema",
237 "$schema": "http://json-schema.org/draft-04/schema#",
245 "extended": {"type": "object"},
247 "required": ["id", "name"],
250 "required": ["flavor"],
251 "additionalProperties": False,
254 new_flavor_response_schema
= {
255 "title": "flavor response information schema",
256 "$schema": "http://json-schema.org/draft-04/schema#",
267 "required": ["flavor"],
268 "additionalProperties": False,
271 get_image_response_schema
= {
272 "title": "openvim images response information schema",
273 "$schema": "http://json-schema.org/draft-04/schema#",
282 "required": ["id", "name"],
285 "required": ["flavor"],
286 "additionalProperties": False,
288 new_image_response_schema
= {
289 "title": "image response information schema",
290 "$schema": "http://json-schema.org/draft-04/schema#",
301 "required": ["image"],
302 "additionalProperties": False,
305 new_vminstance_response_schema
= {
306 "title": "server response information schema",
307 "$schema": "http://json-schema.org/draft-04/schema#",
318 "required": ["server"],
319 "additionalProperties": False,
322 get_processor_rankings_response_schema
= {
323 "title": "processor rankings information schema",
324 "$schema": "http://json-schema.org/draft-04/schema#",
331 "properties": {"model": description_schema
, "value": integer0_schema
},
332 "additionalProperties": False,
333 "required": ["model", "value"],
336 "additionalProperties": False,
337 "required": ["rankings"],
342 class vimconnector(vimconn
.VimConnector
):
357 vimconn
.VimConnector
.__init
__(
371 self
.headers_req
= {"content-type": "application/json"}
372 self
.logger
= logging
.getLogger("ro.vim.openvim")
373 self
.persistent_info
= persistent_info
375 self
.tenant
= tenant_id
377 def __setitem__(self
, index
, value
):
378 """Set individuals parameters
379 Throw TypeError, KeyError
381 if index
== "tenant_id":
383 elif index
== "tenant_name":
385 vimconn
.VimConnector
.__setitem
__(self
, index
, value
)
387 def _get_my_tenant(self
):
388 """Obtain uuid of my tenant from name"""
392 url
= self
.url
+ "/tenants?name=" + quote(self
.tenant_name
)
393 self
.logger
.info("Getting VIM tenant_id GET %s", url
)
394 vim_response
= requests
.get(url
, headers
=self
.headers_req
)
395 self
._check
_http
_request
_response
(vim_response
)
397 tenant_list
= vim_response
.json()["tenants"]
398 if len(tenant_list
) == 0:
399 raise vimconn
.VimConnNotFoundException(
400 "No tenant found for name '{}'".format(self
.tenant_name
)
402 elif len(tenant_list
) > 1:
403 raise vimconn
.VimConnConflictException(
404 "More that one tenant found for name '{}'".format(self
.tenant_name
)
406 self
.tenant
= tenant_list
[0]["id"]
408 except Exception as e
:
409 raise vimconn
.VimConnUnexpectedResponse(
410 "Get VIM tenant {} '{}'".format(type(e
).__name
__, str(e
))
413 def _format_jsonerror(self
, http_response
):
414 # DEPRECATED, to delete in the future
416 data
= http_response
.json()
417 return data
["error"]["description"]
419 return http_response
.text
421 def _format_in(self
, http_response
, schema
):
422 # DEPRECATED, to delete in the future
424 client_data
= http_response
.json()
425 js_v(client_data
, schema
)
426 # print "Input data: ", str(client_data)
427 return True, client_data
428 except js_e
.ValidationError
as exc
:
430 "validate_in error, jsonschema exception ", exc
.message
, "at", exc
.path
433 "validate_in error, jsonschema exception ",
439 def _remove_extra_items(self
, data
, schema
):
441 if type(data
) is tuple or type(data
) is list:
443 a
= self
._remove
_extra
_items
(d
, schema
["items"])
446 elif type(data
) is dict:
448 for k
in data
.keys():
449 if "properties" not in schema
or k
not in schema
["properties"].keys():
453 a
= self
._remove
_extra
_items
(data
[k
], schema
["properties"][k
])
455 deleted
.append({k
: a
})
458 if len(deleted
) == 0:
460 elif len(deleted
) == 1:
465 def _format_request_exception(self
, request_exception
):
466 """Transform a request exception into a vimconn exception"""
467 if isinstance(request_exception
, js_e
.ValidationError
):
468 raise vimconn
.VimConnUnexpectedResponse(
469 "jsonschema exception '{}' at '{}'".format(
470 request_exception
.message
, request_exception
.path
473 elif isinstance(request_exception
, requests
.exceptions
.HTTPError
):
474 raise vimconn
.VimConnUnexpectedResponse(
475 type(request_exception
).__name
__ + ": " + str(request_exception
)
478 raise vimconn
.VimConnConnectionException(
479 type(request_exception
).__name
__ + ": " + str(request_exception
)
482 def _check_http_request_response(self
, request_response
):
483 """Raise a vimconn exception if the response is not Ok"""
484 if request_response
.status_code
>= 200 and request_response
.status_code
< 300:
486 if request_response
.status_code
== vimconn
.HTTP_Unauthorized
:
487 raise vimconn
.VimConnAuthException(request_response
.text
)
488 elif request_response
.status_code
== vimconn
.HTTP_Not_Found
:
489 raise vimconn
.VimConnNotFoundException(request_response
.text
)
490 elif request_response
.status_code
== vimconn
.HTTP_Conflict
:
491 raise vimconn
.VimConnConflictException(request_response
.text
)
493 raise vimconn
.VimConnUnexpectedResponse(
494 "VIM HTTP_response {}, {}".format(
495 request_response
.status_code
, str(request_response
.text
)
499 def new_tenant(self
, tenant_name
, tenant_description
):
500 """Adds a new tenant to VIM with this name and description, returns the tenant identifier"""
501 # print "VIMConnector: Adding a new tenant to VIM"
505 "description": tenant_description
,
509 payload_req
= json
.dumps(payload_dict
)
511 url
= self
.url_admin
+ "/tenants"
512 self
.logger
.info("Adding a new tenant %s", url
)
513 vim_response
= requests
.post(
514 url
, headers
=self
.headers_req
, data
=payload_req
516 self
._check
_http
_request
_response
(vim_response
)
517 self
.logger
.debug(vim_response
.text
)
518 # print json.dumps(vim_response.json(), indent=4)
519 response
= vim_response
.json()
520 js_v(response
, new_tenant_response_schema
)
521 # r = self._remove_extra_items(response, new_tenant_response_schema)
523 # self.logger.warn("Warning: remove extra items %s", str(r))
524 tenant_id
= response
["tenant"]["id"]
526 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
527 self
._format
_request
_exception
(e
)
529 def delete_tenant(self
, tenant_id
):
530 """Delete a tenant from VIM. Returns the old tenant identifier"""
532 url
= self
.url_admin
+ "/tenants/" + tenant_id
533 self
.logger
.info("Delete a tenant DELETE %s", url
)
534 vim_response
= requests
.delete(url
, headers
=self
.headers_req
)
535 self
._check
_http
_request
_response
(vim_response
)
536 self
.logger
.debug(vim_response
.text
)
537 # print json.dumps(vim_response.json(), indent=4)
539 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
540 self
._format
_request
_exception
(e
)
542 def get_tenant_list(self
, filter_dict
={}):
543 """Obtain tenants of VIM
544 filter_dict can contain the following keys:
545 name: filter by tenant name
546 id: filter by tenant uuid/id
548 Returns the tenant list of dictionaries: [{'name':'<name>, 'id':'<id>, ...}, ...]
551 filterquery_text
= ""
552 for k
, v
in filter_dict
.items():
553 filterquery
.append(str(k
) + "=" + str(v
))
554 if len(filterquery
) > 0:
555 filterquery_text
= "?" + "&".join(filterquery
)
557 url
= self
.url
+ "/tenants" + filterquery_text
558 self
.logger
.info("get_tenant_list GET %s", url
)
559 vim_response
= requests
.get(url
, headers
=self
.headers_req
)
560 self
._check
_http
_request
_response
(vim_response
)
561 self
.logger
.debug(vim_response
.text
)
562 # print json.dumps(vim_response.json(), indent=4)
563 return vim_response
.json()["tenants"]
564 except requests
.exceptions
.RequestException
as e
:
565 self
._format
_request
_exception
(e
)
573 provider_network_profile
=None,
574 ): # , **vim_specific):
575 """Adds a tenant network to VIM
577 'net_name': name of the network
579 'bridge': overlay isolated network
580 'data': underlay E-LAN network for Passthrough and SRIOV interfaces
581 'ptp': underlay E-LINE network for Passthrough and SRIOV interfaces.
582 'ip_profile': is a dict containing the IP parameters of the network
583 'ip_version': can be "IPv4" or "IPv6" (Currently only IPv4 is implemented)
584 'subnet_address': ip_prefix_schema, that is X.X.X.X/Y
585 'gateway_address': (Optional) ip_schema, that is X.X.X.X
586 'dns_address': (Optional) comma separated list of ip_schema, e.g. X.X.X.X[,X,X,X,X]
587 'dhcp_enabled': True or False
588 'dhcp_start_address': ip_schema, first IP to grant
589 'dhcp_count': number of IPs to grant.
590 'shared': if this network can be seen/use by other tenants/organization
591 'provider_network_profile': (optional) contains {segmentation-id: vlan, provider-network: vim_netowrk}
592 Returns a tuple with the network identifier and created_items, or raises an exception on error
593 created_items can be None or a dictionary where this method can include key-values that will be passed to
594 the method delete_network. Can be used to store created segments, created l2gw connections, etc.
595 Format is vimconnector dependent, but do not use nested dictionaries and a value of None should be the same
600 if provider_network_profile
:
601 vlan
= provider_network_profile
.get("segmentation-id")
603 self
._get
_my
_tenant
()
604 if net_type
== "bridge":
605 net_type
= "bridge_data"
609 "tenant_id": self
.tenant
,
613 payload_req
["provider:vlan"] = vlan
614 # payload_req.update(vim_specific)
615 url
= self
.url
+ "/networks"
617 "Adding a new network POST: %s DATA: %s", url
, str(payload_req
)
619 vim_response
= requests
.post(
620 url
, headers
=self
.headers_req
, data
=json
.dumps({"network": payload_req
})
622 self
._check
_http
_request
_response
(vim_response
)
623 self
.logger
.debug(vim_response
.text
)
624 # print json.dumps(vim_response.json(), indent=4)
625 response
= vim_response
.json()
626 js_v(response
, new_network_response_schema
)
627 # r = self._remove_extra_items(response, new_network_response_schema)
629 # self.logger.warn("Warning: remove extra items %s", str(r))
630 network_id
= response
["network"]["id"]
631 return network_id
, created_items
632 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
633 self
._format
_request
_exception
(e
)
635 def get_network_list(self
, filter_dict
={}):
636 """Obtain tenant networks of VIM
642 admin_state_up: boolean
644 Returns the network list of dictionaries
647 if "tenant_id" not in filter_dict
:
648 filter_dict
["tenant_id"] = self
._get
_my
_tenant
()
649 elif not filter_dict
["tenant_id"]:
650 del filter_dict
["tenant_id"]
652 filterquery_text
= ""
653 for k
, v
in filter_dict
.items():
654 filterquery
.append(str(k
) + "=" + str(v
))
655 if len(filterquery
) > 0:
656 filterquery_text
= "?" + "&".join(filterquery
)
657 url
= self
.url
+ "/networks" + filterquery_text
658 self
.logger
.info("Getting network list GET %s", url
)
659 vim_response
= requests
.get(url
, headers
=self
.headers_req
)
660 self
._check
_http
_request
_response
(vim_response
)
661 self
.logger
.debug(vim_response
.text
)
662 # print json.dumps(vim_response.json(), indent=4)
663 response
= vim_response
.json()
664 return response
["networks"]
665 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
666 self
._format
_request
_exception
(e
)
668 def get_network(self
, net_id
):
669 """Obtain network details of network id"""
671 url
= self
.url
+ "/networks/" + net_id
672 self
.logger
.info("Getting network GET %s", url
)
673 vim_response
= requests
.get(url
, headers
=self
.headers_req
)
674 self
._check
_http
_request
_response
(vim_response
)
675 self
.logger
.debug(vim_response
.text
)
676 # print json.dumps(vim_response.json(), indent=4)
677 response
= vim_response
.json()
678 return response
["network"]
679 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
680 self
._format
_request
_exception
(e
)
682 def delete_network(self
, net_id
, created_items
=None):
684 Removes a tenant network from VIM and its associated elements
685 :param net_id: VIM identifier of the network, provided by method new_network
686 :param created_items: dictionary with extra items to be deleted. provided by method new_network
687 Returns the network identifier or raises an exception upon error or when network is not found
690 self
._get
_my
_tenant
()
691 url
= self
.url
+ "/networks/" + net_id
692 self
.logger
.info("Deleting VIM network DELETE %s", url
)
693 vim_response
= requests
.delete(url
, headers
=self
.headers_req
)
694 self
._check
_http
_request
_response
(vim_response
)
695 # self.logger.debug(vim_response.text)
696 # print json.dumps(vim_response.json(), indent=4)
698 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
699 self
._format
_request
_exception
(e
)
701 def get_flavor(self
, flavor_id
):
702 """Obtain flavor details from the VIM"""
704 self
._get
_my
_tenant
()
705 url
= self
.url
+ "/" + self
.tenant
+ "/flavors/" + flavor_id
706 self
.logger
.info("Getting flavor GET %s", url
)
707 vim_response
= requests
.get(url
, headers
=self
.headers_req
)
708 self
._check
_http
_request
_response
(vim_response
)
709 self
.logger
.debug(vim_response
.text
)
710 # print json.dumps(vim_response.json(), indent=4)
711 response
= vim_response
.json()
712 js_v(response
, get_flavor_response_schema
)
713 r
= self
._remove
_extra
_items
(response
, get_flavor_response_schema
)
715 self
.logger
.warn("Warning: remove extra items %s", str(r
))
716 return response
["flavor"]
717 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
718 self
._format
_request
_exception
(e
)
720 def new_flavor(self
, flavor_data
):
721 """Adds a tenant flavor to VIM"""
722 """Returns the flavor identifier"""
724 new_flavor_dict
= flavor_data
.copy()
725 for device
in new_flavor_dict
.get("extended", {}).get("devices", ()):
726 if "image name" in device
:
727 del device
["image name"]
730 numas
= new_flavor_dict
.get("extended", {}).get("numas")
733 # translate memory, cpus to EPA
736 and "threads" not in numa
737 and "paired-threads" not in numa
739 numa
["paired-threads"] = new_flavor_dict
["vcpus"]
740 if "memory" not in numa
:
741 numa
["memory"] = int(math
.ceil(new_flavor_dict
["ram"] / 1024.0))
742 for iface
in numa
.get("interfaces", ()):
743 if not iface
.get("bandwidth"):
744 iface
["bandwidth"] = "1 Mbps"
746 new_flavor_dict
["name"] = flavor_data
["name"][:64]
747 self
._get
_my
_tenant
()
748 payload_req
= json
.dumps({"flavor": new_flavor_dict
})
749 url
= self
.url
+ "/" + self
.tenant
+ "/flavors"
750 self
.logger
.info("Adding a new VIM flavor POST %s", url
)
751 vim_response
= requests
.post(
752 url
, headers
=self
.headers_req
, data
=payload_req
754 self
._check
_http
_request
_response
(vim_response
)
755 self
.logger
.debug(vim_response
.text
)
756 # print json.dumps(vim_response.json(), indent=4)
757 response
= vim_response
.json()
758 js_v(response
, new_flavor_response_schema
)
759 r
= self
._remove
_extra
_items
(response
, new_flavor_response_schema
)
761 self
.logger
.warn("Warning: remove extra items %s", str(r
))
762 flavor_id
= response
["flavor"]["id"]
764 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
765 self
._format
_request
_exception
(e
)
767 def delete_flavor(self
, flavor_id
):
768 """Deletes a tenant flavor from VIM"""
769 """Returns the old flavor_id"""
771 self
._get
_my
_tenant
()
772 url
= self
.url
+ "/" + self
.tenant
+ "/flavors/" + flavor_id
773 self
.logger
.info("Deleting VIM flavor DELETE %s", url
)
774 vim_response
= requests
.delete(url
, headers
=self
.headers_req
)
775 self
._check
_http
_request
_response
(vim_response
)
776 # self.logger.debug(vim_response.text)
777 # print json.dumps(vim_response.json(), indent=4)
779 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
780 self
._format
_request
_exception
(e
)
782 def get_image(self
, image_id
):
783 """Obtain image details from the VIM"""
785 self
._get
_my
_tenant
()
786 url
= self
.url
+ "/" + self
.tenant
+ "/images/" + image_id
787 self
.logger
.info("Getting image GET %s", url
)
788 vim_response
= requests
.get(url
, headers
=self
.headers_req
)
789 self
._check
_http
_request
_response
(vim_response
)
790 self
.logger
.debug(vim_response
.text
)
791 # print json.dumps(vim_response.json(), indent=4)
792 response
= vim_response
.json()
793 js_v(response
, get_image_response_schema
)
794 r
= self
._remove
_extra
_items
(response
, get_image_response_schema
)
796 self
.logger
.warn("Warning: remove extra items %s", str(r
))
797 return response
["image"]
798 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
799 self
._format
_request
_exception
(e
)
801 def new_image(self
, image_dict
):
802 """Adds a tenant image to VIM, returns image_id"""
804 self
._get
_my
_tenant
()
805 new_image_dict
= {"name": image_dict
["name"][:64]}
806 if image_dict
.get("description"):
807 new_image_dict
["description"] = image_dict
["description"]
808 if image_dict
.get("metadata"):
809 new_image_dict
["metadata"] = yaml
.load(
810 image_dict
["metadata"], Loader
=yaml
.SafeLoader
812 if image_dict
.get("location"):
813 new_image_dict
["path"] = image_dict
["location"]
814 payload_req
= json
.dumps({"image": new_image_dict
})
815 url
= self
.url
+ "/" + self
.tenant
+ "/images"
816 self
.logger
.info("Adding a new VIM image POST %s", url
)
817 vim_response
= requests
.post(
818 url
, headers
=self
.headers_req
, data
=payload_req
820 self
._check
_http
_request
_response
(vim_response
)
821 self
.logger
.debug(vim_response
.text
)
822 # print json.dumps(vim_response.json(), indent=4)
823 response
= vim_response
.json()
824 js_v(response
, new_image_response_schema
)
825 r
= self
._remove
_extra
_items
(response
, new_image_response_schema
)
827 self
.logger
.warn("Warning: remove extra items %s", str(r
))
828 image_id
= response
["image"]["id"]
830 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
831 self
._format
_request
_exception
(e
)
833 def delete_image(self
, image_id
):
834 """Deletes a tenant image from VIM"""
835 """Returns the deleted image_id"""
837 self
._get
_my
_tenant
()
838 url
= self
.url
+ "/" + self
.tenant
+ "/images/" + image_id
839 self
.logger
.info("Deleting VIM image DELETE %s", url
)
840 vim_response
= requests
.delete(url
, headers
=self
.headers_req
)
841 self
._check
_http
_request
_response
(vim_response
)
842 # self.logger.debug(vim_response.text)
843 # print json.dumps(vim_response.json(), indent=4)
845 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
846 self
._format
_request
_exception
(e
)
848 def get_image_id_from_path(self
, path
):
849 """Get the image id from image path in the VIM database. Returns the image_id"""
851 self
._get
_my
_tenant
()
852 url
= self
.url
+ "/" + self
.tenant
+ "/images?path=" + quote(path
)
853 self
.logger
.info("Getting images GET %s", url
)
854 vim_response
= requests
.get(url
)
855 self
._check
_http
_request
_response
(vim_response
)
856 self
.logger
.debug(vim_response
.text
)
857 # print json.dumps(vim_response.json(), indent=4)
858 response
= vim_response
.json()
859 js_v(response
, get_images_response_schema
)
860 # r = self._remove_extra_items(response, get_images_response_schema)
862 # self.logger.warn("Warning: remove extra items %s", str(r))
863 if len(response
["images"]) == 0:
864 raise vimconn
.VimConnNotFoundException(
865 "Image not found at VIM with path '{}'".format(path
)
867 elif len(response
["images"]) > 1:
868 raise vimconn
.VimConnConflictException(
869 "More than one image found at VIM with path '{}'".format(path
)
871 return response
["images"][0]["id"]
872 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
873 self
._format
_request
_exception
(e
)
875 def get_image_list(self
, filter_dict
={}):
876 """Obtain tenant images from VIM
880 checksum: image checksum
882 Returns the image list of dictionaries:
883 [{<the fields at Filter_dict plus some VIM specific>}, ...]
887 self
._get
_my
_tenant
()
889 filterquery_text
= ""
890 for k
, v
in filter_dict
.items():
891 filterquery
.append(str(k
) + "=" + str(v
))
892 if len(filterquery
) > 0:
893 filterquery_text
= "?" + "&".join(filterquery
)
894 url
= self
.url
+ "/" + self
.tenant
+ "/images" + filterquery_text
895 self
.logger
.info("Getting image list GET %s", url
)
896 vim_response
= requests
.get(url
, headers
=self
.headers_req
)
897 self
._check
_http
_request
_response
(vim_response
)
898 self
.logger
.debug(vim_response
.text
)
899 # print json.dumps(vim_response.json(), indent=4)
900 response
= vim_response
.json()
901 return response
["images"]
902 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
903 self
._format
_request
_exception
(e
)
905 def new_vminstancefromJSON(self
, vm_data
):
906 """Adds a VM instance to VIM"""
907 """Returns the instance identifier"""
909 self
._get
_my
_tenant
()
910 except Exception as e
:
911 return -vimconn
.HTTP_Not_Found
, str(e
)
912 print("VIMConnector: Adding a new VM instance from JSON to VIM")
913 payload_req
= vm_data
915 vim_response
= requests
.post(
916 self
.url
+ "/" + self
.tenant
+ "/servers",
917 headers
=self
.headers_req
,
920 except requests
.exceptions
.RequestException
as e
:
921 print("new_vminstancefromJSON Exception: ", e
.args
)
922 return -vimconn
.HTTP_Not_Found
, str(e
.args
[0])
924 # print vim_response.status_code
925 if vim_response
.status_code
== 200:
926 # print vim_response.json()
927 # print json.dumps(vim_response.json(), indent=4)
928 res
, http_content
= self
._format
_in
(vim_response
, new_image_response_schema
)
931 r
= self
._remove
_extra
_items
(http_content
, new_image_response_schema
)
933 print("Warning: remove extra items ", r
)
935 vminstance_id
= http_content
["server"]["id"]
936 print("Tenant image id: ", vminstance_id
)
937 return vim_response
.status_code
, vminstance_id
939 return -vimconn
.HTTP_Bad_Request
, http_content
941 # print vim_response.text
942 jsonerror
= self
._format
_jsonerror
(vim_response
)
943 text
= 'Error in VIM "{}": not possible to add new vm instance. HTTP Response: {}. Error: {}'.format(
944 self
.url
, vim_response
.status_code
, jsonerror
947 return -vim_response
.status_code
, text
960 availability_zone_index
=None,
961 availability_zone_list
=None,
963 """Adds a VM instance to VIM
965 start: indicates if VM must start or boot in pause mode. Ignored
966 image_id,flavor_id: image and flavor uuid
967 net_list: list of interfaces, each one is a dictionary with:
969 net_id: network uuid to connect
970 vpci: virtual vcpi to assign
971 model: interface model, virtio, e1000, ...
973 use: 'data', 'bridge', 'mgmt'
974 type: 'virtual', 'PCI-PASSTHROUGH'('PF'), 'SR-IOV'('VF'), 'VFnotShared'
975 vim_id: filled/added by this function
976 #TODO ip, security groups
977 Returns a tuple with the instance identifier and created_items or raises an exception on error
978 created_items can be None or a dictionary where this method can include key-values that will be passed to
979 the method delete_vminstance and action_vminstance. Can be used to store created ports, volumes, etc.
980 Format is vimconnector dependent, but do not use nested dictionaries and a value of None should be the same
984 "new_vminstance input: image='%s' flavor='%s' nics='%s'",
990 self
._get
_my
_tenant
()
992 # for k,v in net_dict.items():
994 # net_list.append('{"name":"' + k + '", "uuid":"' + v + '"}')
995 # net_list_string = ', '.join(net_list)
998 if not net
.get("net_id"):
1000 net_dict
= {"uuid": net
["net_id"]}
1002 if net
["type"] == "SR-IOV":
1003 net_dict
["type"] = "VF"
1004 elif net
["type"] == "PCI-PASSTHROUGH":
1005 net_dict
["type"] = "PF"
1007 net_dict
["type"] = net
["type"]
1009 net_dict
["name"] = net
["name"]
1011 net_dict
["vpci"] = net
["vpci"]
1012 if net
.get("model"):
1013 if net
["model"] == "VIRTIO" or net
["model"] == "paravirt":
1014 net_dict
["model"] = "virtio"
1016 net_dict
["model"] = net
["model"]
1017 if net
.get("mac_address"):
1018 net_dict
["mac_address"] = net
["mac_address"]
1019 if net
.get("ip_address"):
1020 net_dict
["ip_address"] = net
["ip_address"]
1021 virtio_net_list
.append(net_dict
)
1024 "description": description
,
1025 "imageRef": image_id
,
1026 "flavorRef": flavor_id
,
1027 "networks": virtio_net_list
,
1029 if start
is not None:
1030 payload_dict
["start"] = start
1031 payload_req
= json
.dumps({"server": payload_dict
})
1032 url
= self
.url
+ "/" + self
.tenant
+ "/servers"
1033 self
.logger
.info("Adding a new vm POST %s DATA %s", url
, payload_req
)
1034 vim_response
= requests
.post(
1035 url
, headers
=self
.headers_req
, data
=payload_req
1037 self
._check
_http
_request
_response
(vim_response
)
1038 self
.logger
.debug(vim_response
.text
)
1039 # print json.dumps(vim_response.json(), indent=4)
1040 response
= vim_response
.json()
1041 js_v(response
, new_vminstance_response_schema
)
1042 # r = self._remove_extra_items(response, new_vminstance_response_schema)
1044 # self.logger.warn("Warning: remove extra items %s", str(r))
1045 vminstance_id
= response
["server"]["id"]
1047 # connect data plane interfaces to network
1048 for net
in net_list
:
1049 if net
["type"] == "virtual":
1050 if not net
.get("net_id"):
1052 for iface
in response
["server"]["networks"]:
1054 if net
["name"] == iface
["name"]:
1055 net
["vim_id"] = iface
["iface_id"]
1057 elif "net_id" in net
:
1058 if net
["net_id"] == iface
["net_id"]:
1059 net
["vim_id"] = iface
["iface_id"]
1062 for numa
in response
["server"].get("extended", {}).get("numas", ()):
1063 for iface
in numa
.get("interfaces", ()):
1064 if net
["name"] == iface
["name"]:
1065 net
["vim_id"] = iface
["iface_id"]
1066 # Code bellow is not needed, current openvim connect dataplane interfaces
1067 # if net.get("net_id"):
1068 # connect dataplane interface
1069 # result, port_id = self.connect_port_network(iface['iface_id'], net["net_id"])
1071 # error_text = "Error attaching port %s to network %s: %s." % (iface['iface_id']
1072 # , net["net_id"], port_id)
1073 # print "new_vminstance: " + error_text
1074 # self.delete_vminstance(vminstance_id)
1075 # return result, error_text
1078 return vminstance_id
, None
1079 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
1080 self
._format
_request
_exception
(e
)
1082 def get_vminstance(self
, vm_id
):
1083 """Returns the VM instance information from VIM"""
1085 self
._get
_my
_tenant
()
1086 url
= self
.url
+ "/" + self
.tenant
+ "/servers/" + vm_id
1087 self
.logger
.info("Getting vm GET %s", url
)
1088 vim_response
= requests
.get(url
, headers
=self
.headers_req
)
1089 vim_response
= requests
.get(url
, headers
=self
.headers_req
)
1090 self
._check
_http
_request
_response
(vim_response
)
1091 self
.logger
.debug(vim_response
.text
)
1092 # print json.dumps(vim_response.json(), indent=4)
1093 response
= vim_response
.json()
1094 js_v(response
, new_vminstance_response_schema
)
1095 # r = self._remove_extra_items(response, new_vminstance_response_schema)
1097 # self.logger.warn("Warning: remove extra items %s", str(r))
1098 return response
["server"]
1099 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
1100 self
._format
_request
_exception
(e
)
1102 def delete_vminstance(self
, vm_id
, created_items
=None, volumes_to_hold
=None):
1103 """Removes a VM instance from VIM, returns the deleted vm_id"""
1105 self
._get
_my
_tenant
()
1106 url
= self
.url
+ "/" + self
.tenant
+ "/servers/" + vm_id
1107 self
.logger
.info("Deleting VIM vm DELETE %s", url
)
1108 vim_response
= requests
.delete(url
, headers
=self
.headers_req
)
1109 self
._check
_http
_request
_response
(vim_response
)
1110 # self.logger.debug(vim_response.text)
1111 # print json.dumps(vim_response.json(), indent=4)
1113 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
1114 self
._format
_request
_exception
(e
)
1116 def refresh_vms_status(self
, vm_list
):
1117 """Refreshes the status of the virtual machines"""
1119 self
._get
_my
_tenant
()
1120 except requests
.exceptions
.RequestException
as e
:
1121 self
._format
_request
_exception
(e
)
1123 for vm_id
in vm_list
:
1125 # print "VIMConnector refresh_tenant_vms and nets: Getting tenant VM instance information from VIM"
1127 url
= self
.url
+ "/" + self
.tenant
+ "/servers/" + vm_id
1128 self
.logger
.info("Getting vm GET %s", url
)
1129 vim_response
= requests
.get(url
, headers
=self
.headers_req
)
1130 self
._check
_http
_request
_response
(vim_response
)
1131 response
= vim_response
.json()
1132 js_v(response
, new_vminstance_response_schema
)
1133 if response
["server"]["status"] in vmStatus2manoFormat
:
1134 vm
["status"] = vmStatus2manoFormat
[response
["server"]["status"]]
1136 vm
["status"] = "OTHER"
1138 "VIM status reported " + response
["server"]["status"]
1140 if response
["server"].get("last_error"):
1141 vm
["error_msg"] = response
["server"]["last_error"]
1142 vm
["vim_info"] = yaml
.safe_dump(response
["server"])
1143 # get interfaces info
1145 management_ip
= False
1146 url2
= self
.url
+ "/ports?device_id=" + quote(vm_id
)
1147 self
.logger
.info("Getting PORTS GET %s", url2
)
1148 vim_response2
= requests
.get(url2
, headers
=self
.headers_req
)
1149 self
._check
_http
_request
_response
(vim_response2
)
1150 client_data
= vim_response2
.json()
1151 if isinstance(client_data
.get("ports"), list):
1152 vm
["interfaces"] = []
1153 for port
in client_data
.get("ports"):
1155 interface
["vim_info"] = yaml
.safe_dump(port
)
1156 interface
["mac_address"] = port
.get("mac_address")
1157 interface
["vim_net_id"] = port
.get("network_id")
1158 interface
["vim_interface_id"] = port
["id"]
1159 interface
["ip_address"] = port
.get("ip_address")
1160 if interface
["ip_address"]:
1161 management_ip
= True
1162 if interface
["ip_address"] == "0.0.0.0":
1163 interface
["ip_address"] = None
1164 vm
["interfaces"].append(interface
)
1166 except Exception as e
:
1168 "refresh_vms_and_nets. Port get %s: %s",
1173 if vm
["status"] == "ACTIVE" and not management_ip
:
1174 vm
["status"] = "ACTIVE:NoMgmtIP"
1176 except vimconn
.VimConnNotFoundException
as e
:
1177 self
.logger
.error("Exception getting vm status: %s", str(e
))
1178 vm
["status"] = "DELETED"
1179 vm
["error_msg"] = str(e
)
1181 requests
.exceptions
.RequestException
,
1182 js_e
.ValidationError
,
1183 vimconn
.VimConnException
,
1185 self
.logger
.error("Exception getting vm status: %s", str(e
))
1186 vm
["status"] = "VIM_ERROR"
1187 vm
["error_msg"] = str(e
)
1191 def refresh_nets_status(self
, net_list
):
1192 """Get the status of the networks
1193 Params: the list of network identifiers
1194 Returns a dictionary with:
1195 net_id: #VIM id of this network
1196 status: #Mandatory. Text with one of:
1197 # DELETED (not found at vim)
1198 # VIM_ERROR (Cannot connect to VIM, VIM response error, ...)
1199 # OTHER (Vim reported other status not understood)
1200 # ERROR (VIM indicates an ERROR status)
1201 # ACTIVE, INACTIVE, DOWN (admin down),
1202 # BUILD (on building process)
1204 error_msg: #Text with VIM error message, if any. Or the VIM connection ERROR
1205 vim_info: #Text with plain information obtained from vim (yaml.safe_dump)
1209 self
._get
_my
_tenant
()
1210 except requests
.exceptions
.RequestException
as e
:
1211 self
._format
_request
_exception
(e
)
1214 for net_id
in net_list
:
1216 # print "VIMConnector refresh_tenant_vms_and_nets:
1217 # Getting tenant network from VIM (tenant: " + str(self.tenant) + "): "
1219 net_vim
= self
.get_network(net_id
)
1220 if net_vim
["status"] in netStatus2manoFormat
:
1221 net
["status"] = netStatus2manoFormat
[net_vim
["status"]]
1223 net
["status"] = "OTHER"
1224 net
["error_msg"] = "VIM status reported " + net_vim
["status"]
1226 if net
["status"] == "ACTIVE" and not net_vim
["admin_state_up"]:
1227 net
["status"] = "DOWN"
1228 if net_vim
.get("last_error"):
1229 net
["error_msg"] = net_vim
["last_error"]
1230 net
["vim_info"] = yaml
.safe_dump(net_vim
)
1231 except vimconn
.VimConnNotFoundException
as e
:
1232 self
.logger
.error("Exception getting net status: %s", str(e
))
1233 net
["status"] = "DELETED"
1234 net
["error_msg"] = str(e
)
1236 requests
.exceptions
.RequestException
,
1237 js_e
.ValidationError
,
1238 vimconn
.VimConnException
,
1240 self
.logger
.error("Exception getting net status: %s", str(e
))
1241 net
["status"] = "VIM_ERROR"
1242 net
["error_msg"] = str(e
)
1243 net_dict
[net_id
] = net
1246 def action_vminstance(self
, vm_id
, action_dict
, created_items
={}):
1247 """Send and action over a VM instance from VIM"""
1248 """Returns the status"""
1250 self
._get
_my
_tenant
()
1251 if "console" in action_dict
:
1252 raise vimconn
.VimConnException(
1253 "getting console is not available at openvim",
1254 http_code
=vimconn
.HTTP_Service_Unavailable
,
1256 url
= self
.url
+ "/" + self
.tenant
+ "/servers/" + vm_id
+ "/action"
1257 self
.logger
.info("Action over VM instance POST %s", url
)
1258 vim_response
= requests
.post(
1259 url
, headers
=self
.headers_req
, data
=json
.dumps(action_dict
)
1261 self
._check
_http
_request
_response
(vim_response
)
1263 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
1264 self
._format
_request
_exception
(e
)
1266 # NOT USED METHODS in current version
1268 def host_vim2gui(self
, host
, server_dict
):
1269 """Transform host dictionary from VIM format to GUI format,
1270 and append to the server_dict
1272 if type(server_dict
) is not dict:
1274 "vimconnector.host_vim2gui() ERROR, param server_dict must be a dictionary"
1279 for numa
in host
["host"]["numas"]:
1281 occupation_item
= {}
1283 RAD_item
["memory"] = {
1284 "size": str(numa
["memory"]) + "GB",
1285 "eligible": str(numa
["hugepages"]) + "GB",
1287 occupation_item
["memory"] = str(numa
["hugepages_consumed"]) + "GB"
1289 RAD_item
["cpus"] = {}
1290 RAD_item
["cpus"]["cores"] = []
1291 RAD_item
["cpus"]["eligible_cores"] = []
1292 occupation_item
["cores"] = []
1293 for _
in range(0, len(numa
["cores"]) // 2):
1294 RAD_item
["cpus"]["cores"].append([])
1295 for core
in numa
["cores"]:
1296 RAD_item
["cpus"]["cores"][core
["core_id"]].append(core
["thread_id"])
1297 if "status" not in core
:
1298 RAD_item
["cpus"]["eligible_cores"].append(core
["thread_id"])
1299 if "instance_id" in core
:
1300 occupation_item
["cores"].append(core
["thread_id"])
1302 RAD_item
["ports"] = {}
1303 occupation_item
["ports"] = {}
1304 for iface
in numa
["interfaces"]:
1305 RAD_item
["ports"][iface
["pci"]] = "speed:" + str(iface
["Mbps"]) + "M"
1306 occupation_item
["ports"][iface
["pci"]] = {
1307 "occupied": str(100 * iface
["Mbps_consumed"] // iface
["Mbps"]) + "%"
1310 RAD
[numa
["numa_socket"]] = RAD_item
1311 occupation
[numa
["numa_socket"]] = occupation_item
1312 server_dict
[host
["host"]["name"]] = {"RAD": RAD
, "occupation": occupation
}
1314 def get_hosts_info(self
):
1315 """Get the information of deployed hosts
1316 Returns the hosts content"""
1318 url
= self
.url
+ "/hosts"
1320 vim_response
= requests
.get(url
)
1321 except requests
.exceptions
.RequestException
as e
:
1322 print("get_hosts_info Exception: ", e
.args
)
1323 return -vimconn
.HTTP_Not_Found
, str(e
.args
[0])
1325 "vim get", url
, "response:", vim_response
.status_code
, vim_response
.json()
1327 # print vim_response.status_code
1328 # print json.dumps(vim_response.json(), indent=4)
1329 if vim_response
.status_code
!= 200:
1332 "vimconnector.get_hosts_info error getting host list {} {}".format(
1333 vim_response
.status_code
, vim_response
.json()
1336 return -vim_response
.status_code
, "Error getting host list"
1338 res
, hosts
= self
._format
_in
(vim_response
, get_hosts_response_schema
)
1342 "vimconnector.get_hosts_info error parsing GET HOSTS vim response",
1345 return vimconn
.HTTP_Internal_Server_Error
, hosts
1346 # obtain hosts details
1348 for host
in hosts
["hosts"]:
1349 url
= self
.url
+ "/hosts/" + host
["id"]
1351 vim_response
= requests
.get(url
)
1352 except requests
.exceptions
.RequestException
as e
:
1353 print("get_hosts_info Exception: ", e
.args
)
1354 return -vimconn
.HTTP_Not_Found
, str(e
.args
[0])
1359 vim_response
.status_code
,
1360 vim_response
.json(),
1362 if vim_response
.status_code
!= 200:
1364 "vimconnector.get_hosts_info error getting detailed host {} {}".format(
1365 vim_response
.status_code
, vim_response
.json()
1369 res
, host_detail
= self
._format
_in
(
1370 vim_response
, get_host_detail_response_schema
1374 "vimconnector.get_hosts_info error parsing GET HOSTS/{} vim response {}".format(
1375 host
["id"], host_detail
1379 # print 'host id '+host['id'], json.dumps(host_detail, indent=4)
1380 self
.host_vim2gui(host_detail
, hosts_dict
)
1381 return 200, hosts_dict
1383 def get_hosts(self
, vim_tenant
):
1384 """Get the hosts and deployed instances
1385 Returns the hosts content"""
1387 url
= self
.url
+ "/hosts"
1389 vim_response
= requests
.get(url
)
1390 except requests
.exceptions
.RequestException
as e
:
1391 print("get_hosts Exception: ", e
.args
)
1392 return -vimconn
.HTTP_Not_Found
, str(e
.args
[0])
1394 "vim get", url
, "response:", vim_response
.status_code
, vim_response
.json()
1396 # print vim_response.status_code
1397 # print json.dumps(vim_response.json(), indent=4)
1398 if vim_response
.status_code
!= 200:
1401 "vimconnector.get_hosts error getting host list {} {}".format(
1402 vim_response
.status_code
, vim_response
.json()
1405 return -vim_response
.status_code
, "Error getting host list"
1407 res
, hosts
= self
._format
_in
(vim_response
, get_hosts_response_schema
)
1410 print("vimconnector.get_host error parsing GET HOSTS vim response", hosts
)
1411 return vimconn
.HTTP_Internal_Server_Error
, hosts
1412 # obtain instances from hosts
1413 for host
in hosts
["hosts"]:
1414 url
= self
.url
+ "/" + vim_tenant
+ "/servers?hostId=" + host
["id"]
1416 vim_response
= requests
.get(url
)
1417 except requests
.exceptions
.RequestException
as e
:
1418 print("get_hosts Exception: ", e
.args
)
1419 return -vimconn
.HTTP_Not_Found
, str(e
.args
[0])
1424 vim_response
.status_code
,
1425 vim_response
.json(),
1427 if vim_response
.status_code
!= 200:
1429 "vimconnector.get_hosts error getting instances at host {} {}".format(
1430 vim_response
.status_code
, vim_response
.json()
1434 res
, servers
= self
._format
_in
(vim_response
, get_server_response_schema
)
1437 "vimconnector.get_host error parsing GET SERVERS/{} vim response {}".format(
1442 # print 'host id '+host['id'], json.dumps(host_detail, indent=4)
1443 host
["instances"] = servers
["servers"]
1444 return 200, hosts
["hosts"]
1446 def get_processor_rankings(self
):
1447 """Get the processor rankings in the VIM database"""
1448 url
= self
.url
+ "/processor_ranking"
1450 vim_response
= requests
.get(url
)
1451 except requests
.exceptions
.RequestException
as e
:
1452 print("get_processor_rankings Exception: ", e
.args
)
1453 return -vimconn
.HTTP_Not_Found
, str(e
.args
[0])
1455 "vim get", url
, "response:", vim_response
.status_code
, vim_response
.json()
1457 # print vim_response.status_code
1458 # print json.dumps(vim_response.json(), indent=4)
1459 if vim_response
.status_code
!= 200:
1462 "vimconnector.get_processor_rankings error getting processor rankings {} {}".format(
1463 vim_response
.status_code
, vim_response
.json()
1466 return -vim_response
.status_code
, "Error getting processor rankings"
1468 res
, rankings
= self
._format
_in
(
1469 vim_response
, get_processor_rankings_response_schema
1471 return res
, rankings
["rankings"]
1473 def new_host(self
, host_data
):
1474 """Adds a new host to VIM"""
1475 """Returns status code of the VIM response"""
1476 payload_req
= host_data
1478 url
= self
.url_admin
+ "/hosts"
1479 self
.logger
.info("Adding a new host POST %s", url
)
1480 vim_response
= requests
.post(
1481 url
, headers
=self
.headers_req
, data
=payload_req
1483 self
._check
_http
_request
_response
(vim_response
)
1484 self
.logger
.debug(vim_response
.text
)
1485 # print json.dumps(vim_response.json(), indent=4)
1486 response
= vim_response
.json()
1487 js_v(response
, new_host_response_schema
)
1488 r
= self
._remove
_extra
_items
(response
, new_host_response_schema
)
1490 self
.logger
.warn("Warning: remove extra items %s", str(r
))
1491 host_id
= response
["host"]["id"]
1493 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
1494 self
._format
_request
_exception
(e
)
1496 def new_external_port(self
, port_data
):
1497 """Adds a external port to VIM"""
1498 """Returns the port identifier"""
1499 # TODO change to logging exception code policies
1500 print("VIMConnector: Adding a new external port")
1501 payload_req
= port_data
1503 vim_response
= requests
.post(
1504 self
.url_admin
+ "/ports", headers
=self
.headers_req
, data
=payload_req
1506 except requests
.exceptions
.RequestException
as e
:
1507 self
.logger
.error("new_external_port Exception: ", str(e
))
1508 return -vimconn
.HTTP_Not_Found
, str(e
.args
[0])
1510 # print vim_response.status_code
1511 if vim_response
.status_code
== 200:
1512 # print vim_response.json()
1513 # print json.dumps(vim_response.json(), indent=4)
1514 res
, http_content
= self
._format
_in
(vim_response
, new_port_response_schema
)
1515 # print http_content
1517 r
= self
._remove
_extra
_items
(http_content
, new_port_response_schema
)
1519 print("Warning: remove extra items ", r
)
1520 # print http_content
1521 port_id
= http_content
["port"]["id"]
1522 print("Port id: ", port_id
)
1523 return vim_response
.status_code
, port_id
1525 return -vimconn
.HTTP_Bad_Request
, http_content
1527 # print vim_response.text
1528 jsonerror
= self
._format
_jsonerror
(vim_response
)
1529 text
= 'Error in VIM "{}": not possible to add new external port. HTTP Response: {}. Error: {}'.format(
1530 self
.url_admin
, vim_response
.status_code
, jsonerror
1533 return -vim_response
.status_code
, text
1535 def new_external_network(self
, net_name
, net_type
):
1536 """Adds a external network to VIM (shared)"""
1537 """Returns the network identifier"""
1538 # TODO change to logging exception code policies
1540 "VIMConnector: Adding external shared network to VIM (type "
1547 '{"network":{"name": "'
1549 + '","shared":true,"type": "'
1554 vim_response
= requests
.post(
1555 self
.url
+ "/networks", headers
=self
.headers_req
, data
=payload_req
1557 except requests
.exceptions
.RequestException
as e
:
1558 self
.logger
.error("new_external_network Exception: ", e
.args
)
1559 return -vimconn
.HTTP_Not_Found
, str(e
.args
[0])
1561 # print vim_response.status_code
1562 if vim_response
.status_code
== 200:
1563 # print vim_response.json()
1564 # print json.dumps(vim_response.json(), indent=4)
1565 res
, http_content
= self
._format
_in
(
1566 vim_response
, new_network_response_schema
1568 # print http_content
1570 r
= self
._remove
_extra
_items
(http_content
, new_network_response_schema
)
1572 print("Warning: remove extra items ", r
)
1573 # print http_content
1574 network_id
= http_content
["network"]["id"]
1575 print("Network id: ", network_id
)
1576 return vim_response
.status_code
, network_id
1578 return -vimconn
.HTTP_Bad_Request
, http_content
1580 # print vim_response.text
1581 jsonerror
= self
._format
_jsonerror
(vim_response
)
1582 text
= 'Error in VIM "{}": not possible to add new external network. HTTP Response: {}. Error: {}'.format(
1583 self
.url
, vim_response
.status_code
, jsonerror
1586 return -vim_response
.status_code
, text
1588 def connect_port_network(self
, port_id
, network_id
, admin
=False):
1589 """Connects a external port to a network"""
1590 """Returns status code of the VIM response"""
1591 # TODO change to logging exception code policies
1592 print("VIMConnector: Connecting external port to network")
1594 payload_req
= '{"port":{"network_id":"' + network_id
+ '"}}'
1596 if self
.url_admin
is None:
1598 -vimconn
.HTTP_Unauthorized
,
1599 "datacenter cannot contain admin URL",
1601 url
= self
.url_admin
1605 vim_response
= requests
.put(
1606 url
+ "/ports/" + port_id
, headers
=self
.headers_req
, data
=payload_req
1608 except requests
.exceptions
.RequestException
as e
:
1609 print("connect_port_network Exception: ", e
.args
)
1610 return -vimconn
.HTTP_Not_Found
, str(e
.args
[0])
1612 # print vim_response.status_code
1613 if vim_response
.status_code
== 200:
1614 # print vim_response.json()
1615 # print json.dumps(vim_response.json(), indent=4)
1616 res
, http_content
= self
._format
_in
(vim_response
, new_port_response_schema
)
1617 # print http_content
1619 r
= self
._remove
_extra
_items
(http_content
, new_port_response_schema
)
1621 print("Warning: remove extra items ", r
)
1622 # print http_content
1623 port_id
= http_content
["port"]["id"]
1624 print("Port id: ", port_id
)
1625 return vim_response
.status_code
, port_id
1627 return -vimconn
.HTTP_Bad_Request
, http_content
1629 print(vim_response
.text
)
1630 jsonerror
= self
._format
_jsonerror
(vim_response
)
1632 'Error in VIM "{}": not possible to connect external port to network. HTTP Response: {}.'
1633 " Error: {}".format(self
.url_admin
, vim_response
.status_code
, jsonerror
)
1636 return -vim_response
.status_code
, text
1638 def migrate_instance(self
, vm_id
, compute_host
=None):
1642 vm_id: ID of an instance
1643 compute_host: Host to migrate the vdu to
1645 # TODO: Add support for migration
1646 raise vimconn
.VimConnNotImplemented("Not implemented")
1648 def resize_instance(self
, vm_id
, flavor_id
=None):
1652 vm_id: ID of an instance
1653 flavor_id: flavor_id to resize the vdu to
1655 # TODO: Add support for resize
1656 raise vimconn
.VimConnNotImplemented("Not implemented")