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$"
30 from osm_ro_plugin
import vimconn
36 from osm_ro
.openmano_schemas
import (
44 from jsonschema
import validate
as js_v
, exceptions
as js_e
45 from urllib
.parse
import quote
47 """contain the openvim virtual machine status to openmano status"""
48 vmStatus2manoFormat
= {
51 "SUSPENDED": "SUSPENDED",
52 "INACTIVE": "INACTIVE",
57 netStatus2manoFormat
= {
59 "INACTIVE": "INACTIVE",
81 "required": ["id", "name"],
89 "required": ["id", "name"],
91 new_host_response_schema
= {
92 "title": "host response information schema",
93 "$schema": "http://json-schema.org/draft-04/schema#",
95 "properties": {"host": host_schema
},
97 "additionalProperties": False,
100 get_images_response_schema
= {
101 "title": "openvim images response information schema",
102 "$schema": "http://json-schema.org/draft-04/schema#",
107 "items": image_schema
,
110 "required": ["images"],
111 "additionalProperties": False,
114 get_hosts_response_schema
= {
115 "title": "openvim hosts response information schema",
116 "$schema": "http://json-schema.org/draft-04/schema#",
121 "items": host_schema
,
124 "required": ["hosts"],
125 "additionalProperties": False,
128 get_host_detail_response_schema
= (
129 new_host_response_schema
# TODO: Content is not parsed yet
132 get_server_response_schema
= {
133 "title": "openvim server response information schema",
134 "$schema": "http://json-schema.org/draft-04/schema#",
139 "items": server_schema
,
142 "required": ["servers"],
143 "additionalProperties": False,
146 new_tenant_response_schema
= {
147 "title": "tenant response information schema",
148 "$schema": "http://json-schema.org/draft-04/schema#",
155 "name": nameshort_schema
,
156 "description": description_schema
,
157 "enabled": {"type": "boolean"},
162 "required": ["tenant"],
163 "additionalProperties": False,
166 new_network_response_schema
= {
167 "title": "network response information schema",
168 "$schema": "http://json-schema.org/draft-04/schema#",
178 "enum": ["bridge_man", "bridge_data", "data", "ptp"],
180 "shared": {"type": "boolean"},
181 "tenant_id": id_schema
,
182 "admin_state_up": {"type": "boolean"},
183 "vlan": vlan1000_schema
,
188 "required": ["network"],
189 "additionalProperties": False,
193 # get_network_response_schema = {
194 # "title":"get network response information schema",
195 # "$schema": "http://json-schema.org/draft-04/schema#",
202 # "name":name_schema,
203 # "type":{"type":"string", "enum":["bridge_man","bridge_data","data", "ptp"]},
204 # "shared":{"type":"boolean"},
205 # "tenant_id":id_schema,
206 # "admin_state_up":{"type":"boolean"},
207 # "vlan":vlan1000_schema
212 # "required": ["network"],
213 # "additionalProperties": False
217 new_port_response_schema
= {
218 "title": "port response information schema",
219 "$schema": "http://json-schema.org/draft-04/schema#",
230 "required": ["port"],
231 "additionalProperties": False,
234 get_flavor_response_schema
= {
235 "title": "openvim flavors response information schema",
236 "$schema": "http://json-schema.org/draft-04/schema#",
244 "extended": {"type": "object"},
246 "required": ["id", "name"],
249 "required": ["flavor"],
250 "additionalProperties": False,
253 new_flavor_response_schema
= {
254 "title": "flavor response information schema",
255 "$schema": "http://json-schema.org/draft-04/schema#",
266 "required": ["flavor"],
267 "additionalProperties": False,
270 get_image_response_schema
= {
271 "title": "openvim images response information schema",
272 "$schema": "http://json-schema.org/draft-04/schema#",
281 "required": ["id", "name"],
284 "required": ["flavor"],
285 "additionalProperties": False,
287 new_image_response_schema
= {
288 "title": "image response information schema",
289 "$schema": "http://json-schema.org/draft-04/schema#",
300 "required": ["image"],
301 "additionalProperties": False,
304 new_vminstance_response_schema
= {
305 "title": "server response information schema",
306 "$schema": "http://json-schema.org/draft-04/schema#",
317 "required": ["server"],
318 "additionalProperties": False,
321 get_processor_rankings_response_schema
= {
322 "title": "processor rankings information schema",
323 "$schema": "http://json-schema.org/draft-04/schema#",
330 "properties": {"model": description_schema
, "value": integer0_schema
},
331 "additionalProperties": False,
332 "required": ["model", "value"],
335 "additionalProperties": False,
336 "required": ["rankings"],
341 class vimconnector(vimconn
.VimConnector
):
356 vimconn
.VimConnector
.__init
__(
370 self
.headers_req
= {"content-type": "application/json"}
371 self
.logger
= logging
.getLogger("ro.vim.openvim")
372 self
.persistent_info
= persistent_info
374 self
.tenant
= tenant_id
376 def __setitem__(self
, index
, value
):
377 """Set individuals parameters
378 Throw TypeError, KeyError
380 if index
== "tenant_id":
382 elif index
== "tenant_name":
384 vimconn
.VimConnector
.__setitem
__(self
, index
, value
)
386 def _get_my_tenant(self
):
387 """Obtain uuid of my tenant from name"""
391 url
= self
.url
+ "/tenants?name=" + quote(self
.tenant_name
)
392 self
.logger
.info("Getting VIM tenant_id GET %s", url
)
393 vim_response
= requests
.get(url
, headers
=self
.headers_req
)
394 self
._check
_http
_request
_response
(vim_response
)
396 tenant_list
= vim_response
.json()["tenants"]
397 if len(tenant_list
) == 0:
398 raise vimconn
.VimConnNotFoundException(
399 "No tenant found for name '{}'".format(self
.tenant_name
)
401 elif len(tenant_list
) > 1:
402 raise vimconn
.VimConnConflictException(
403 "More that one tenant found for name '{}'".format(self
.tenant_name
)
405 self
.tenant
= tenant_list
[0]["id"]
407 except Exception as e
:
408 raise vimconn
.VimConnUnexpectedResponse(
409 "Get VIM tenant {} '{}'".format(type(e
).__name
__, str(e
))
412 def _format_jsonerror(self
, http_response
):
413 # DEPRECATED, to delete in the future
415 data
= http_response
.json()
416 return data
["error"]["description"]
418 return http_response
.text
420 def _format_in(self
, http_response
, schema
):
421 # DEPRECATED, to delete in the future
423 client_data
= http_response
.json()
424 js_v(client_data
, schema
)
425 # print "Input data: ", str(client_data)
426 return True, client_data
427 except js_e
.ValidationError
as exc
:
429 "validate_in error, jsonschema exception ", exc
.message
, "at", exc
.path
432 "validate_in error, jsonschema exception ",
438 def _remove_extra_items(self
, data
, schema
):
440 if type(data
) is tuple or type(data
) is list:
442 a
= self
._remove
_extra
_items
(d
, schema
["items"])
445 elif type(data
) is dict:
447 for k
in data
.keys():
448 if "properties" not in schema
or k
not in schema
["properties"].keys():
452 a
= self
._remove
_extra
_items
(data
[k
], schema
["properties"][k
])
454 deleted
.append({k
: a
})
457 if len(deleted
) == 0:
459 elif len(deleted
) == 1:
464 def _format_request_exception(self
, request_exception
):
465 """Transform a request exception into a vimconn exception"""
466 if isinstance(request_exception
, js_e
.ValidationError
):
467 raise vimconn
.VimConnUnexpectedResponse(
468 "jsonschema exception '{}' at '{}'".format(
469 request_exception
.message
, request_exception
.path
472 elif isinstance(request_exception
, requests
.exceptions
.HTTPError
):
473 raise vimconn
.VimConnUnexpectedResponse(
474 type(request_exception
).__name
__ + ": " + str(request_exception
)
477 raise vimconn
.VimConnConnectionException(
478 type(request_exception
).__name
__ + ": " + str(request_exception
)
481 def _check_http_request_response(self
, request_response
):
482 """Raise a vimconn exception if the response is not Ok"""
483 if request_response
.status_code
>= 200 and request_response
.status_code
< 300:
485 if request_response
.status_code
== vimconn
.HTTP_Unauthorized
:
486 raise vimconn
.VimConnAuthException(request_response
.text
)
487 elif request_response
.status_code
== vimconn
.HTTP_Not_Found
:
488 raise vimconn
.VimConnNotFoundException(request_response
.text
)
489 elif request_response
.status_code
== vimconn
.HTTP_Conflict
:
490 raise vimconn
.VimConnConflictException(request_response
.text
)
492 raise vimconn
.VimConnUnexpectedResponse(
493 "VIM HTTP_response {}, {}".format(
494 request_response
.status_code
, str(request_response
.text
)
498 def new_tenant(self
, tenant_name
, tenant_description
):
499 """Adds a new tenant to VIM with this name and description, returns the tenant identifier"""
500 # print "VIMConnector: Adding a new tenant to VIM"
504 "description": tenant_description
,
508 payload_req
= json
.dumps(payload_dict
)
510 url
= self
.url_admin
+ "/tenants"
511 self
.logger
.info("Adding a new tenant %s", url
)
512 vim_response
= requests
.post(
513 url
, headers
=self
.headers_req
, data
=payload_req
515 self
._check
_http
_request
_response
(vim_response
)
516 self
.logger
.debug(vim_response
.text
)
517 # print json.dumps(vim_response.json(), indent=4)
518 response
= vim_response
.json()
519 js_v(response
, new_tenant_response_schema
)
520 # r = self._remove_extra_items(response, new_tenant_response_schema)
522 # self.logger.warn("Warning: remove extra items %s", str(r))
523 tenant_id
= response
["tenant"]["id"]
525 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
526 self
._format
_request
_exception
(e
)
528 def delete_tenant(self
, tenant_id
):
529 """Delete a tenant from VIM. Returns the old tenant identifier"""
531 url
= self
.url_admin
+ "/tenants/" + tenant_id
532 self
.logger
.info("Delete a tenant DELETE %s", url
)
533 vim_response
= requests
.delete(url
, headers
=self
.headers_req
)
534 self
._check
_http
_request
_response
(vim_response
)
535 self
.logger
.debug(vim_response
.text
)
536 # print json.dumps(vim_response.json(), indent=4)
538 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
539 self
._format
_request
_exception
(e
)
541 def get_tenant_list(self
, filter_dict
={}):
542 """Obtain tenants of VIM
543 filter_dict can contain the following keys:
544 name: filter by tenant name
545 id: filter by tenant uuid/id
547 Returns the tenant list of dictionaries: [{'name':'<name>, 'id':'<id>, ...}, ...]
550 filterquery_text
= ""
551 for k
, v
in filter_dict
.items():
552 filterquery
.append(str(k
) + "=" + str(v
))
553 if len(filterquery
) > 0:
554 filterquery_text
= "?" + "&".join(filterquery
)
556 url
= self
.url
+ "/tenants" + filterquery_text
557 self
.logger
.info("get_tenant_list GET %s", url
)
558 vim_response
= requests
.get(url
, headers
=self
.headers_req
)
559 self
._check
_http
_request
_response
(vim_response
)
560 self
.logger
.debug(vim_response
.text
)
561 # print json.dumps(vim_response.json(), indent=4)
562 return vim_response
.json()["tenants"]
563 except requests
.exceptions
.RequestException
as e
:
564 self
._format
_request
_exception
(e
)
572 provider_network_profile
=None,
573 ): # , **vim_specific):
574 """Adds a tenant network to VIM
576 'net_name': name of the network
578 'bridge': overlay isolated network
579 'data': underlay E-LAN network for Passthrough and SRIOV interfaces
580 'ptp': underlay E-LINE network for Passthrough and SRIOV interfaces.
581 'ip_profile': is a dict containing the IP parameters of the network
582 'ip_version': can be "IPv4" or "IPv6" (Currently only IPv4 is implemented)
583 'subnet_address': ip_prefix_schema, that is X.X.X.X/Y
584 'gateway_address': (Optional) ip_schema, that is X.X.X.X
585 'dns_address': (Optional) comma separated list of ip_schema, e.g. X.X.X.X[,X,X,X,X]
586 'dhcp_enabled': True or False
587 'dhcp_start_address': ip_schema, first IP to grant
588 'dhcp_count': number of IPs to grant.
589 'shared': if this network can be seen/use by other tenants/organization
590 'provider_network_profile': (optional) contains {segmentation-id: vlan, provider-network: vim_netowrk}
591 Returns a tuple with the network identifier and created_items, or raises an exception on error
592 created_items can be None or a dictionary where this method can include key-values that will be passed to
593 the method delete_network. Can be used to store created segments, created l2gw connections, etc.
594 Format is vimconnector dependent, but do not use nested dictionaries and a value of None should be the same
599 if provider_network_profile
:
600 vlan
= provider_network_profile
.get("segmentation-id")
602 self
._get
_my
_tenant
()
603 if net_type
== "bridge":
604 net_type
= "bridge_data"
608 "tenant_id": self
.tenant
,
612 payload_req
["provider:vlan"] = vlan
613 # payload_req.update(vim_specific)
614 url
= self
.url
+ "/networks"
616 "Adding a new network POST: %s DATA: %s", url
, str(payload_req
)
618 vim_response
= requests
.post(
619 url
, headers
=self
.headers_req
, data
=json
.dumps({"network": payload_req
})
621 self
._check
_http
_request
_response
(vim_response
)
622 self
.logger
.debug(vim_response
.text
)
623 # print json.dumps(vim_response.json(), indent=4)
624 response
= vim_response
.json()
625 js_v(response
, new_network_response_schema
)
626 # r = self._remove_extra_items(response, new_network_response_schema)
628 # self.logger.warn("Warning: remove extra items %s", str(r))
629 network_id
= response
["network"]["id"]
630 return network_id
, created_items
631 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
632 self
._format
_request
_exception
(e
)
634 def get_network_list(self
, filter_dict
={}):
635 """Obtain tenant networks of VIM
641 admin_state_up: boolean
643 Returns the network list of dictionaries
646 if "tenant_id" not in filter_dict
:
647 filter_dict
["tenant_id"] = self
._get
_my
_tenant
()
648 elif not filter_dict
["tenant_id"]:
649 del filter_dict
["tenant_id"]
651 filterquery_text
= ""
652 for k
, v
in filter_dict
.items():
653 filterquery
.append(str(k
) + "=" + str(v
))
654 if len(filterquery
) > 0:
655 filterquery_text
= "?" + "&".join(filterquery
)
656 url
= self
.url
+ "/networks" + filterquery_text
657 self
.logger
.info("Getting network list GET %s", url
)
658 vim_response
= requests
.get(url
, headers
=self
.headers_req
)
659 self
._check
_http
_request
_response
(vim_response
)
660 self
.logger
.debug(vim_response
.text
)
661 # print json.dumps(vim_response.json(), indent=4)
662 response
= vim_response
.json()
663 return response
["networks"]
664 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
665 self
._format
_request
_exception
(e
)
667 def get_network(self
, net_id
):
668 """Obtain network details of network id"""
670 url
= self
.url
+ "/networks/" + net_id
671 self
.logger
.info("Getting network GET %s", url
)
672 vim_response
= requests
.get(url
, headers
=self
.headers_req
)
673 self
._check
_http
_request
_response
(vim_response
)
674 self
.logger
.debug(vim_response
.text
)
675 # print json.dumps(vim_response.json(), indent=4)
676 response
= vim_response
.json()
677 return response
["network"]
678 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
679 self
._format
_request
_exception
(e
)
681 def delete_network(self
, net_id
, created_items
=None):
683 Removes a tenant network from VIM and its associated elements
684 :param net_id: VIM identifier of the network, provided by method new_network
685 :param created_items: dictionary with extra items to be deleted. provided by method new_network
686 Returns the network identifier or raises an exception upon error or when network is not found
689 self
._get
_my
_tenant
()
690 url
= self
.url
+ "/networks/" + net_id
691 self
.logger
.info("Deleting VIM network DELETE %s", url
)
692 vim_response
= requests
.delete(url
, headers
=self
.headers_req
)
693 self
._check
_http
_request
_response
(vim_response
)
694 # self.logger.debug(vim_response.text)
695 # print json.dumps(vim_response.json(), indent=4)
697 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
698 self
._format
_request
_exception
(e
)
700 def get_flavor(self
, flavor_id
):
701 """Obtain flavor details from the VIM"""
703 self
._get
_my
_tenant
()
704 url
= self
.url
+ "/" + self
.tenant
+ "/flavors/" + flavor_id
705 self
.logger
.info("Getting flavor GET %s", url
)
706 vim_response
= requests
.get(url
, headers
=self
.headers_req
)
707 self
._check
_http
_request
_response
(vim_response
)
708 self
.logger
.debug(vim_response
.text
)
709 # print json.dumps(vim_response.json(), indent=4)
710 response
= vim_response
.json()
711 js_v(response
, get_flavor_response_schema
)
712 r
= self
._remove
_extra
_items
(response
, get_flavor_response_schema
)
714 self
.logger
.warn("Warning: remove extra items %s", str(r
))
715 return response
["flavor"]
716 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
717 self
._format
_request
_exception
(e
)
719 def new_flavor(self
, flavor_data
):
720 """Adds a tenant flavor to VIM"""
721 """Returns the flavor identifier"""
723 new_flavor_dict
= flavor_data
.copy()
724 for device
in new_flavor_dict
.get("extended", {}).get("devices", ()):
725 if "image name" in device
:
726 del device
["image name"]
729 numas
= new_flavor_dict
.get("extended", {}).get("numas")
732 # translate memory, cpus to EPA
735 and "threads" not in numa
736 and "paired-threads" not in numa
738 numa
["paired-threads"] = new_flavor_dict
["vcpus"]
739 if "memory" not in numa
:
740 numa
["memory"] = int(math
.ceil(new_flavor_dict
["ram"] / 1024.0))
741 for iface
in numa
.get("interfaces", ()):
742 if not iface
.get("bandwidth"):
743 iface
["bandwidth"] = "1 Mbps"
745 new_flavor_dict
["name"] = flavor_data
["name"][:64]
746 self
._get
_my
_tenant
()
747 payload_req
= json
.dumps({"flavor": new_flavor_dict
})
748 url
= self
.url
+ "/" + self
.tenant
+ "/flavors"
749 self
.logger
.info("Adding a new VIM flavor POST %s", url
)
750 vim_response
= requests
.post(
751 url
, headers
=self
.headers_req
, data
=payload_req
753 self
._check
_http
_request
_response
(vim_response
)
754 self
.logger
.debug(vim_response
.text
)
755 # print json.dumps(vim_response.json(), indent=4)
756 response
= vim_response
.json()
757 js_v(response
, new_flavor_response_schema
)
758 r
= self
._remove
_extra
_items
(response
, new_flavor_response_schema
)
760 self
.logger
.warn("Warning: remove extra items %s", str(r
))
761 flavor_id
= response
["flavor"]["id"]
763 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
764 self
._format
_request
_exception
(e
)
766 def delete_flavor(self
, flavor_id
):
767 """Deletes a tenant flavor from VIM"""
768 """Returns the old flavor_id"""
770 self
._get
_my
_tenant
()
771 url
= self
.url
+ "/" + self
.tenant
+ "/flavors/" + flavor_id
772 self
.logger
.info("Deleting VIM flavor DELETE %s", url
)
773 vim_response
= requests
.delete(url
, headers
=self
.headers_req
)
774 self
._check
_http
_request
_response
(vim_response
)
775 # self.logger.debug(vim_response.text)
776 # print json.dumps(vim_response.json(), indent=4)
778 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
779 self
._format
_request
_exception
(e
)
781 def get_image(self
, image_id
):
782 """Obtain image details from the VIM"""
784 self
._get
_my
_tenant
()
785 url
= self
.url
+ "/" + self
.tenant
+ "/images/" + image_id
786 self
.logger
.info("Getting image GET %s", url
)
787 vim_response
= requests
.get(url
, headers
=self
.headers_req
)
788 self
._check
_http
_request
_response
(vim_response
)
789 self
.logger
.debug(vim_response
.text
)
790 # print json.dumps(vim_response.json(), indent=4)
791 response
= vim_response
.json()
792 js_v(response
, get_image_response_schema
)
793 r
= self
._remove
_extra
_items
(response
, get_image_response_schema
)
795 self
.logger
.warn("Warning: remove extra items %s", str(r
))
796 return response
["image"]
797 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
798 self
._format
_request
_exception
(e
)
800 def new_image(self
, image_dict
):
801 """Adds a tenant image to VIM, returns image_id"""
803 self
._get
_my
_tenant
()
804 new_image_dict
= {"name": image_dict
["name"][:64]}
805 if image_dict
.get("description"):
806 new_image_dict
["description"] = image_dict
["description"]
807 if image_dict
.get("metadata"):
808 new_image_dict
["metadata"] = yaml
.load(
809 image_dict
["metadata"], Loader
=yaml
.SafeLoader
811 if image_dict
.get("location"):
812 new_image_dict
["path"] = image_dict
["location"]
813 payload_req
= json
.dumps({"image": new_image_dict
})
814 url
= self
.url
+ "/" + self
.tenant
+ "/images"
815 self
.logger
.info("Adding a new VIM image POST %s", url
)
816 vim_response
= requests
.post(
817 url
, headers
=self
.headers_req
, data
=payload_req
819 self
._check
_http
_request
_response
(vim_response
)
820 self
.logger
.debug(vim_response
.text
)
821 # print json.dumps(vim_response.json(), indent=4)
822 response
= vim_response
.json()
823 js_v(response
, new_image_response_schema
)
824 r
= self
._remove
_extra
_items
(response
, new_image_response_schema
)
826 self
.logger
.warn("Warning: remove extra items %s", str(r
))
827 image_id
= response
["image"]["id"]
829 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
830 self
._format
_request
_exception
(e
)
832 def delete_image(self
, image_id
):
833 """Deletes a tenant image from VIM"""
834 """Returns the deleted image_id"""
836 self
._get
_my
_tenant
()
837 url
= self
.url
+ "/" + self
.tenant
+ "/images/" + image_id
838 self
.logger
.info("Deleting VIM image DELETE %s", url
)
839 vim_response
= requests
.delete(url
, headers
=self
.headers_req
)
840 self
._check
_http
_request
_response
(vim_response
)
841 # self.logger.debug(vim_response.text)
842 # print json.dumps(vim_response.json(), indent=4)
844 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
845 self
._format
_request
_exception
(e
)
847 def get_image_id_from_path(self
, path
):
848 """Get the image id from image path in the VIM database. Returns the image_id"""
850 self
._get
_my
_tenant
()
851 url
= self
.url
+ "/" + self
.tenant
+ "/images?path=" + quote(path
)
852 self
.logger
.info("Getting images GET %s", url
)
853 vim_response
= requests
.get(url
)
854 self
._check
_http
_request
_response
(vim_response
)
855 self
.logger
.debug(vim_response
.text
)
856 # print json.dumps(vim_response.json(), indent=4)
857 response
= vim_response
.json()
858 js_v(response
, get_images_response_schema
)
859 # r = self._remove_extra_items(response, get_images_response_schema)
861 # self.logger.warn("Warning: remove extra items %s", str(r))
862 if len(response
["images"]) == 0:
863 raise vimconn
.VimConnNotFoundException(
864 "Image not found at VIM with path '{}'".format(path
)
866 elif len(response
["images"]) > 1:
867 raise vimconn
.VimConnConflictException(
868 "More than one image found at VIM with path '{}'".format(path
)
870 return response
["images"][0]["id"]
871 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
872 self
._format
_request
_exception
(e
)
874 def get_image_list(self
, filter_dict
={}):
875 """Obtain tenant images from VIM
879 checksum: image checksum
881 Returns the image list of dictionaries:
882 [{<the fields at Filter_dict plus some VIM specific>}, ...]
886 self
._get
_my
_tenant
()
888 filterquery_text
= ""
889 for k
, v
in filter_dict
.items():
890 filterquery
.append(str(k
) + "=" + str(v
))
891 if len(filterquery
) > 0:
892 filterquery_text
= "?" + "&".join(filterquery
)
893 url
= self
.url
+ "/" + self
.tenant
+ "/images" + filterquery_text
894 self
.logger
.info("Getting image list GET %s", url
)
895 vim_response
= requests
.get(url
, headers
=self
.headers_req
)
896 self
._check
_http
_request
_response
(vim_response
)
897 self
.logger
.debug(vim_response
.text
)
898 # print json.dumps(vim_response.json(), indent=4)
899 response
= vim_response
.json()
900 return response
["images"]
901 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
902 self
._format
_request
_exception
(e
)
904 def new_vminstancefromJSON(self
, vm_data
):
905 """Adds a VM instance to VIM"""
906 """Returns the instance identifier"""
908 self
._get
_my
_tenant
()
909 except Exception as e
:
910 return -vimconn
.HTTP_Not_Found
, str(e
)
911 print("VIMConnector: Adding a new VM instance from JSON to VIM")
912 payload_req
= vm_data
914 vim_response
= requests
.post(
915 self
.url
+ "/" + self
.tenant
+ "/servers",
916 headers
=self
.headers_req
,
919 except requests
.exceptions
.RequestException
as e
:
920 print("new_vminstancefromJSON Exception: ", e
.args
)
921 return -vimconn
.HTTP_Not_Found
, str(e
.args
[0])
923 # print vim_response.status_code
924 if vim_response
.status_code
== 200:
925 # print vim_response.json()
926 # print json.dumps(vim_response.json(), indent=4)
927 res
, http_content
= self
._format
_in
(vim_response
, new_image_response_schema
)
930 r
= self
._remove
_extra
_items
(http_content
, new_image_response_schema
)
932 print("Warning: remove extra items ", r
)
934 vminstance_id
= http_content
["server"]["id"]
935 print("Tenant image id: ", vminstance_id
)
936 return vim_response
.status_code
, vminstance_id
938 return -vimconn
.HTTP_Bad_Request
, http_content
940 # print vim_response.text
941 jsonerror
= self
._format
_jsonerror
(vim_response
)
942 text
= 'Error in VIM "{}": not possible to add new vm instance. HTTP Response: {}. Error: {}'.format(
943 self
.url
, vim_response
.status_code
, jsonerror
946 return -vim_response
.status_code
, text
958 availability_zone_index
=None,
959 availability_zone_list
=None,
961 """Adds a VM instance to VIM
963 start: indicates if VM must start or boot in pause mode. Ignored
964 image_id,flavor_id: image and flavor uuid
965 net_list: list of interfaces, each one is a dictionary with:
967 net_id: network uuid to connect
968 vpci: virtual vcpi to assign
969 model: interface model, virtio, e1000, ...
971 use: 'data', 'bridge', 'mgmt'
972 type: 'virtual', 'PCI-PASSTHROUGH'('PF'), 'SR-IOV'('VF'), 'VFnotShared'
973 vim_id: filled/added by this function
974 #TODO ip, security groups
975 Returns a tuple with the instance identifier and created_items or raises an exception on error
976 created_items can be None or a dictionary where this method can include key-values that will be passed to
977 the method delete_vminstance and action_vminstance. Can be used to store created ports, volumes, etc.
978 Format is vimconnector dependent, but do not use nested dictionaries and a value of None should be the same
982 "new_vminstance input: image='%s' flavor='%s' nics='%s'",
988 self
._get
_my
_tenant
()
990 # for k,v in net_dict.items():
992 # net_list.append('{"name":"' + k + '", "uuid":"' + v + '"}')
993 # net_list_string = ', '.join(net_list)
996 if not net
.get("net_id"):
998 net_dict
= {"uuid": net
["net_id"]}
1000 if net
["type"] == "SR-IOV":
1001 net_dict
["type"] = "VF"
1002 elif net
["type"] == "PCI-PASSTHROUGH":
1003 net_dict
["type"] = "PF"
1005 net_dict
["type"] = net
["type"]
1007 net_dict
["name"] = net
["name"]
1009 net_dict
["vpci"] = net
["vpci"]
1010 if net
.get("model"):
1011 if net
["model"] == "VIRTIO" or net
["model"] == "paravirt":
1012 net_dict
["model"] = "virtio"
1014 net_dict
["model"] = net
["model"]
1015 if net
.get("mac_address"):
1016 net_dict
["mac_address"] = net
["mac_address"]
1017 if net
.get("ip_address"):
1018 net_dict
["ip_address"] = net
["ip_address"]
1019 virtio_net_list
.append(net_dict
)
1022 "description": description
,
1023 "imageRef": image_id
,
1024 "flavorRef": flavor_id
,
1025 "networks": virtio_net_list
,
1027 if start
is not None:
1028 payload_dict
["start"] = start
1029 payload_req
= json
.dumps({"server": payload_dict
})
1030 url
= self
.url
+ "/" + self
.tenant
+ "/servers"
1031 self
.logger
.info("Adding a new vm POST %s DATA %s", url
, payload_req
)
1032 vim_response
= requests
.post(
1033 url
, headers
=self
.headers_req
, data
=payload_req
1035 self
._check
_http
_request
_response
(vim_response
)
1036 self
.logger
.debug(vim_response
.text
)
1037 # print json.dumps(vim_response.json(), indent=4)
1038 response
= vim_response
.json()
1039 js_v(response
, new_vminstance_response_schema
)
1040 # r = self._remove_extra_items(response, new_vminstance_response_schema)
1042 # self.logger.warn("Warning: remove extra items %s", str(r))
1043 vminstance_id
= response
["server"]["id"]
1045 # connect data plane interfaces to network
1046 for net
in net_list
:
1047 if net
["type"] == "virtual":
1048 if not net
.get("net_id"):
1050 for iface
in response
["server"]["networks"]:
1052 if net
["name"] == iface
["name"]:
1053 net
["vim_id"] = iface
["iface_id"]
1055 elif "net_id" in net
:
1056 if net
["net_id"] == iface
["net_id"]:
1057 net
["vim_id"] = iface
["iface_id"]
1060 for numa
in response
["server"].get("extended", {}).get("numas", ()):
1061 for iface
in numa
.get("interfaces", ()):
1062 if net
["name"] == iface
["name"]:
1063 net
["vim_id"] = iface
["iface_id"]
1064 # Code bellow is not needed, current openvim connect dataplane interfaces
1065 # if net.get("net_id"):
1066 # connect dataplane interface
1067 # result, port_id = self.connect_port_network(iface['iface_id'], net["net_id"])
1069 # error_text = "Error attaching port %s to network %s: %s." % (iface['iface_id']
1070 # , net["net_id"], port_id)
1071 # print "new_vminstance: " + error_text
1072 # self.delete_vminstance(vminstance_id)
1073 # return result, error_text
1076 return vminstance_id
, None
1077 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
1078 self
._format
_request
_exception
(e
)
1080 def get_vminstance(self
, vm_id
):
1081 """Returns the VM instance information from VIM"""
1083 self
._get
_my
_tenant
()
1084 url
= self
.url
+ "/" + self
.tenant
+ "/servers/" + vm_id
1085 self
.logger
.info("Getting vm GET %s", url
)
1086 vim_response
= requests
.get(url
, headers
=self
.headers_req
)
1087 vim_response
= requests
.get(url
, headers
=self
.headers_req
)
1088 self
._check
_http
_request
_response
(vim_response
)
1089 self
.logger
.debug(vim_response
.text
)
1090 # print json.dumps(vim_response.json(), indent=4)
1091 response
= vim_response
.json()
1092 js_v(response
, new_vminstance_response_schema
)
1093 # r = self._remove_extra_items(response, new_vminstance_response_schema)
1095 # self.logger.warn("Warning: remove extra items %s", str(r))
1096 return response
["server"]
1097 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
1098 self
._format
_request
_exception
(e
)
1100 def delete_vminstance(self
, vm_id
, created_items
=None):
1101 """Removes a VM instance from VIM, returns the deleted vm_id"""
1103 self
._get
_my
_tenant
()
1104 url
= self
.url
+ "/" + self
.tenant
+ "/servers/" + vm_id
1105 self
.logger
.info("Deleting VIM vm DELETE %s", url
)
1106 vim_response
= requests
.delete(url
, headers
=self
.headers_req
)
1107 self
._check
_http
_request
_response
(vim_response
)
1108 # self.logger.debug(vim_response.text)
1109 # print json.dumps(vim_response.json(), indent=4)
1111 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
1112 self
._format
_request
_exception
(e
)
1114 def refresh_vms_status(self
, vm_list
):
1115 """Refreshes the status of the virtual machines"""
1117 self
._get
_my
_tenant
()
1118 except requests
.exceptions
.RequestException
as e
:
1119 self
._format
_request
_exception
(e
)
1121 for vm_id
in vm_list
:
1123 # print "VIMConnector refresh_tenant_vms and nets: Getting tenant VM instance information from VIM"
1125 url
= self
.url
+ "/" + self
.tenant
+ "/servers/" + vm_id
1126 self
.logger
.info("Getting vm GET %s", url
)
1127 vim_response
= requests
.get(url
, headers
=self
.headers_req
)
1128 self
._check
_http
_request
_response
(vim_response
)
1129 response
= vim_response
.json()
1130 js_v(response
, new_vminstance_response_schema
)
1131 if response
["server"]["status"] in vmStatus2manoFormat
:
1132 vm
["status"] = vmStatus2manoFormat
[response
["server"]["status"]]
1134 vm
["status"] = "OTHER"
1136 "VIM status reported " + response
["server"]["status"]
1138 if response
["server"].get("last_error"):
1139 vm
["error_msg"] = response
["server"]["last_error"]
1140 vm
["vim_info"] = yaml
.safe_dump(response
["server"])
1141 # get interfaces info
1143 management_ip
= False
1144 url2
= self
.url
+ "/ports?device_id=" + quote(vm_id
)
1145 self
.logger
.info("Getting PORTS GET %s", url2
)
1146 vim_response2
= requests
.get(url2
, headers
=self
.headers_req
)
1147 self
._check
_http
_request
_response
(vim_response2
)
1148 client_data
= vim_response2
.json()
1149 if isinstance(client_data
.get("ports"), list):
1150 vm
["interfaces"] = []
1151 for port
in client_data
.get("ports"):
1153 interface
["vim_info"] = yaml
.safe_dump(port
)
1154 interface
["mac_address"] = port
.get("mac_address")
1155 interface
["vim_net_id"] = port
.get("network_id")
1156 interface
["vim_interface_id"] = port
["id"]
1157 interface
["ip_address"] = port
.get("ip_address")
1158 if interface
["ip_address"]:
1159 management_ip
= True
1160 if interface
["ip_address"] == "0.0.0.0":
1161 interface
["ip_address"] = None
1162 vm
["interfaces"].append(interface
)
1164 except Exception as e
:
1166 "refresh_vms_and_nets. Port get %s: %s",
1171 if vm
["status"] == "ACTIVE" and not management_ip
:
1172 vm
["status"] = "ACTIVE:NoMgmtIP"
1174 except vimconn
.VimConnNotFoundException
as e
:
1175 self
.logger
.error("Exception getting vm status: %s", str(e
))
1176 vm
["status"] = "DELETED"
1177 vm
["error_msg"] = str(e
)
1179 requests
.exceptions
.RequestException
,
1180 js_e
.ValidationError
,
1181 vimconn
.VimConnException
,
1183 self
.logger
.error("Exception getting vm status: %s", str(e
))
1184 vm
["status"] = "VIM_ERROR"
1185 vm
["error_msg"] = str(e
)
1189 def refresh_nets_status(self
, net_list
):
1190 """Get the status of the networks
1191 Params: the list of network identifiers
1192 Returns a dictionary with:
1193 net_id: #VIM id of this network
1194 status: #Mandatory. Text with one of:
1195 # DELETED (not found at vim)
1196 # VIM_ERROR (Cannot connect to VIM, VIM response error, ...)
1197 # OTHER (Vim reported other status not understood)
1198 # ERROR (VIM indicates an ERROR status)
1199 # ACTIVE, INACTIVE, DOWN (admin down),
1200 # BUILD (on building process)
1202 error_msg: #Text with VIM error message, if any. Or the VIM connection ERROR
1203 vim_info: #Text with plain information obtained from vim (yaml.safe_dump)
1207 self
._get
_my
_tenant
()
1208 except requests
.exceptions
.RequestException
as e
:
1209 self
._format
_request
_exception
(e
)
1212 for net_id
in net_list
:
1214 # print "VIMConnector refresh_tenant_vms_and_nets:
1215 # Getting tenant network from VIM (tenant: " + str(self.tenant) + "): "
1217 net_vim
= self
.get_network(net_id
)
1218 if net_vim
["status"] in netStatus2manoFormat
:
1219 net
["status"] = netStatus2manoFormat
[net_vim
["status"]]
1221 net
["status"] = "OTHER"
1222 net
["error_msg"] = "VIM status reported " + net_vim
["status"]
1224 if net
["status"] == "ACTIVE" and not net_vim
["admin_state_up"]:
1225 net
["status"] = "DOWN"
1226 if net_vim
.get("last_error"):
1227 net
["error_msg"] = net_vim
["last_error"]
1228 net
["vim_info"] = yaml
.safe_dump(net_vim
)
1229 except vimconn
.VimConnNotFoundException
as e
:
1230 self
.logger
.error("Exception getting net status: %s", str(e
))
1231 net
["status"] = "DELETED"
1232 net
["error_msg"] = str(e
)
1234 requests
.exceptions
.RequestException
,
1235 js_e
.ValidationError
,
1236 vimconn
.VimConnException
,
1238 self
.logger
.error("Exception getting net status: %s", str(e
))
1239 net
["status"] = "VIM_ERROR"
1240 net
["error_msg"] = str(e
)
1241 net_dict
[net_id
] = net
1244 def action_vminstance(self
, vm_id
, action_dict
, created_items
={}):
1245 """Send and action over a VM instance from VIM"""
1246 """Returns the status"""
1248 self
._get
_my
_tenant
()
1249 if "console" in action_dict
:
1250 raise vimconn
.VimConnException(
1251 "getting console is not available at openvim",
1252 http_code
=vimconn
.HTTP_Service_Unavailable
,
1254 url
= self
.url
+ "/" + self
.tenant
+ "/servers/" + vm_id
+ "/action"
1255 self
.logger
.info("Action over VM instance POST %s", url
)
1256 vim_response
= requests
.post(
1257 url
, headers
=self
.headers_req
, data
=json
.dumps(action_dict
)
1259 self
._check
_http
_request
_response
(vim_response
)
1261 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
1262 self
._format
_request
_exception
(e
)
1264 # NOT USED METHODS in current version
1266 def host_vim2gui(self
, host
, server_dict
):
1267 """Transform host dictionary from VIM format to GUI format,
1268 and append to the server_dict
1270 if type(server_dict
) is not dict:
1272 "vimconnector.host_vim2gui() ERROR, param server_dict must be a dictionary"
1277 for numa
in host
["host"]["numas"]:
1279 occupation_item
= {}
1281 RAD_item
["memory"] = {
1282 "size": str(numa
["memory"]) + "GB",
1283 "eligible": str(numa
["hugepages"]) + "GB",
1285 occupation_item
["memory"] = str(numa
["hugepages_consumed"]) + "GB"
1287 RAD_item
["cpus"] = {}
1288 RAD_item
["cpus"]["cores"] = []
1289 RAD_item
["cpus"]["eligible_cores"] = []
1290 occupation_item
["cores"] = []
1291 for _
in range(0, len(numa
["cores"]) // 2):
1292 RAD_item
["cpus"]["cores"].append([])
1293 for core
in numa
["cores"]:
1294 RAD_item
["cpus"]["cores"][core
["core_id"]].append(core
["thread_id"])
1295 if "status" not in core
:
1296 RAD_item
["cpus"]["eligible_cores"].append(core
["thread_id"])
1297 if "instance_id" in core
:
1298 occupation_item
["cores"].append(core
["thread_id"])
1300 RAD_item
["ports"] = {}
1301 occupation_item
["ports"] = {}
1302 for iface
in numa
["interfaces"]:
1303 RAD_item
["ports"][iface
["pci"]] = "speed:" + str(iface
["Mbps"]) + "M"
1304 occupation_item
["ports"][iface
["pci"]] = {
1305 "occupied": str(100 * iface
["Mbps_consumed"] // iface
["Mbps"]) + "%"
1308 RAD
[numa
["numa_socket"]] = RAD_item
1309 occupation
[numa
["numa_socket"]] = occupation_item
1310 server_dict
[host
["host"]["name"]] = {"RAD": RAD
, "occupation": occupation
}
1312 def get_hosts_info(self
):
1313 """Get the information of deployed hosts
1314 Returns the hosts content"""
1316 url
= self
.url
+ "/hosts"
1318 vim_response
= requests
.get(url
)
1319 except requests
.exceptions
.RequestException
as e
:
1320 print("get_hosts_info Exception: ", e
.args
)
1321 return -vimconn
.HTTP_Not_Found
, str(e
.args
[0])
1323 "vim get", url
, "response:", vim_response
.status_code
, vim_response
.json()
1325 # print vim_response.status_code
1326 # print json.dumps(vim_response.json(), indent=4)
1327 if vim_response
.status_code
!= 200:
1330 "vimconnector.get_hosts_info error getting host list {} {}".format(
1331 vim_response
.status_code
, vim_response
.json()
1334 return -vim_response
.status_code
, "Error getting host list"
1336 res
, hosts
= self
._format
_in
(vim_response
, get_hosts_response_schema
)
1340 "vimconnector.get_hosts_info error parsing GET HOSTS vim response",
1343 return vimconn
.HTTP_Internal_Server_Error
, hosts
1344 # obtain hosts details
1346 for host
in hosts
["hosts"]:
1347 url
= self
.url
+ "/hosts/" + host
["id"]
1349 vim_response
= requests
.get(url
)
1350 except requests
.exceptions
.RequestException
as e
:
1351 print("get_hosts_info Exception: ", e
.args
)
1352 return -vimconn
.HTTP_Not_Found
, str(e
.args
[0])
1357 vim_response
.status_code
,
1358 vim_response
.json(),
1360 if vim_response
.status_code
!= 200:
1362 "vimconnector.get_hosts_info error getting detailed host {} {}".format(
1363 vim_response
.status_code
, vim_response
.json()
1367 res
, host_detail
= self
._format
_in
(
1368 vim_response
, get_host_detail_response_schema
1372 "vimconnector.get_hosts_info error parsing GET HOSTS/{} vim response {}".format(
1373 host
["id"], host_detail
1377 # print 'host id '+host['id'], json.dumps(host_detail, indent=4)
1378 self
.host_vim2gui(host_detail
, hosts_dict
)
1379 return 200, hosts_dict
1381 def get_hosts(self
, vim_tenant
):
1382 """Get the hosts and deployed instances
1383 Returns the hosts content"""
1385 url
= self
.url
+ "/hosts"
1387 vim_response
= requests
.get(url
)
1388 except requests
.exceptions
.RequestException
as e
:
1389 print("get_hosts Exception: ", e
.args
)
1390 return -vimconn
.HTTP_Not_Found
, str(e
.args
[0])
1392 "vim get", url
, "response:", vim_response
.status_code
, vim_response
.json()
1394 # print vim_response.status_code
1395 # print json.dumps(vim_response.json(), indent=4)
1396 if vim_response
.status_code
!= 200:
1399 "vimconnector.get_hosts error getting host list {} {}".format(
1400 vim_response
.status_code
, vim_response
.json()
1403 return -vim_response
.status_code
, "Error getting host list"
1405 res
, hosts
= self
._format
_in
(vim_response
, get_hosts_response_schema
)
1408 print("vimconnector.get_host error parsing GET HOSTS vim response", hosts
)
1409 return vimconn
.HTTP_Internal_Server_Error
, hosts
1410 # obtain instances from hosts
1411 for host
in hosts
["hosts"]:
1412 url
= self
.url
+ "/" + vim_tenant
+ "/servers?hostId=" + host
["id"]
1414 vim_response
= requests
.get(url
)
1415 except requests
.exceptions
.RequestException
as e
:
1416 print("get_hosts Exception: ", e
.args
)
1417 return -vimconn
.HTTP_Not_Found
, str(e
.args
[0])
1422 vim_response
.status_code
,
1423 vim_response
.json(),
1425 if vim_response
.status_code
!= 200:
1427 "vimconnector.get_hosts error getting instances at host {} {}".format(
1428 vim_response
.status_code
, vim_response
.json()
1432 res
, servers
= self
._format
_in
(vim_response
, get_server_response_schema
)
1435 "vimconnector.get_host error parsing GET SERVERS/{} vim response {}".format(
1440 # print 'host id '+host['id'], json.dumps(host_detail, indent=4)
1441 host
["instances"] = servers
["servers"]
1442 return 200, hosts
["hosts"]
1444 def get_processor_rankings(self
):
1445 """Get the processor rankings in the VIM database"""
1446 url
= self
.url
+ "/processor_ranking"
1448 vim_response
= requests
.get(url
)
1449 except requests
.exceptions
.RequestException
as e
:
1450 print("get_processor_rankings Exception: ", e
.args
)
1451 return -vimconn
.HTTP_Not_Found
, str(e
.args
[0])
1453 "vim get", url
, "response:", vim_response
.status_code
, vim_response
.json()
1455 # print vim_response.status_code
1456 # print json.dumps(vim_response.json(), indent=4)
1457 if vim_response
.status_code
!= 200:
1460 "vimconnector.get_processor_rankings error getting processor rankings {} {}".format(
1461 vim_response
.status_code
, vim_response
.json()
1464 return -vim_response
.status_code
, "Error getting processor rankings"
1466 res
, rankings
= self
._format
_in
(
1467 vim_response
, get_processor_rankings_response_schema
1469 return res
, rankings
["rankings"]
1471 def new_host(self
, host_data
):
1472 """Adds a new host to VIM"""
1473 """Returns status code of the VIM response"""
1474 payload_req
= host_data
1476 url
= self
.url_admin
+ "/hosts"
1477 self
.logger
.info("Adding a new host POST %s", url
)
1478 vim_response
= requests
.post(
1479 url
, headers
=self
.headers_req
, data
=payload_req
1481 self
._check
_http
_request
_response
(vim_response
)
1482 self
.logger
.debug(vim_response
.text
)
1483 # print json.dumps(vim_response.json(), indent=4)
1484 response
= vim_response
.json()
1485 js_v(response
, new_host_response_schema
)
1486 r
= self
._remove
_extra
_items
(response
, new_host_response_schema
)
1488 self
.logger
.warn("Warning: remove extra items %s", str(r
))
1489 host_id
= response
["host"]["id"]
1491 except (requests
.exceptions
.RequestException
, js_e
.ValidationError
) as e
:
1492 self
._format
_request
_exception
(e
)
1494 def new_external_port(self
, port_data
):
1495 """Adds a external port to VIM"""
1496 """Returns the port identifier"""
1497 # TODO change to logging exception code policies
1498 print("VIMConnector: Adding a new external port")
1499 payload_req
= port_data
1501 vim_response
= requests
.post(
1502 self
.url_admin
+ "/ports", headers
=self
.headers_req
, data
=payload_req
1504 except requests
.exceptions
.RequestException
as e
:
1505 self
.logger
.error("new_external_port Exception: ", str(e
))
1506 return -vimconn
.HTTP_Not_Found
, str(e
.args
[0])
1508 # print vim_response.status_code
1509 if vim_response
.status_code
== 200:
1510 # print vim_response.json()
1511 # print json.dumps(vim_response.json(), indent=4)
1512 res
, http_content
= self
._format
_in
(vim_response
, new_port_response_schema
)
1513 # print http_content
1515 r
= self
._remove
_extra
_items
(http_content
, new_port_response_schema
)
1517 print("Warning: remove extra items ", r
)
1518 # print http_content
1519 port_id
= http_content
["port"]["id"]
1520 print("Port id: ", port_id
)
1521 return vim_response
.status_code
, port_id
1523 return -vimconn
.HTTP_Bad_Request
, http_content
1525 # print vim_response.text
1526 jsonerror
= self
._format
_jsonerror
(vim_response
)
1527 text
= 'Error in VIM "{}": not possible to add new external port. HTTP Response: {}. Error: {}'.format(
1528 self
.url_admin
, vim_response
.status_code
, jsonerror
1531 return -vim_response
.status_code
, text
1533 def new_external_network(self
, net_name
, net_type
):
1534 """Adds a external network to VIM (shared)"""
1535 """Returns the network identifier"""
1536 # TODO change to logging exception code policies
1538 "VIMConnector: Adding external shared network to VIM (type "
1545 '{"network":{"name": "'
1547 + '","shared":true,"type": "'
1552 vim_response
= requests
.post(
1553 self
.url
+ "/networks", headers
=self
.headers_req
, data
=payload_req
1555 except requests
.exceptions
.RequestException
as e
:
1556 self
.logger
.error("new_external_network Exception: ", e
.args
)
1557 return -vimconn
.HTTP_Not_Found
, str(e
.args
[0])
1559 # print vim_response.status_code
1560 if vim_response
.status_code
== 200:
1561 # print vim_response.json()
1562 # print json.dumps(vim_response.json(), indent=4)
1563 res
, http_content
= self
._format
_in
(
1564 vim_response
, new_network_response_schema
1566 # print http_content
1568 r
= self
._remove
_extra
_items
(http_content
, new_network_response_schema
)
1570 print("Warning: remove extra items ", r
)
1571 # print http_content
1572 network_id
= http_content
["network"]["id"]
1573 print("Network id: ", network_id
)
1574 return vim_response
.status_code
, network_id
1576 return -vimconn
.HTTP_Bad_Request
, http_content
1578 # print vim_response.text
1579 jsonerror
= self
._format
_jsonerror
(vim_response
)
1580 text
= 'Error in VIM "{}": not possible to add new external network. HTTP Response: {}. Error: {}'.format(
1581 self
.url
, vim_response
.status_code
, jsonerror
1584 return -vim_response
.status_code
, text
1586 def connect_port_network(self
, port_id
, network_id
, admin
=False):
1587 """Connects a external port to a network"""
1588 """Returns status code of the VIM response"""
1589 # TODO change to logging exception code policies
1590 print("VIMConnector: Connecting external port to network")
1592 payload_req
= '{"port":{"network_id":"' + network_id
+ '"}}'
1594 if self
.url_admin
is None:
1596 -vimconn
.HTTP_Unauthorized
,
1597 "datacenter cannot contain admin URL",
1599 url
= self
.url_admin
1603 vim_response
= requests
.put(
1604 url
+ "/ports/" + port_id
, headers
=self
.headers_req
, data
=payload_req
1606 except requests
.exceptions
.RequestException
as e
:
1607 print("connect_port_network Exception: ", e
.args
)
1608 return -vimconn
.HTTP_Not_Found
, str(e
.args
[0])
1610 # print vim_response.status_code
1611 if vim_response
.status_code
== 200:
1612 # print vim_response.json()
1613 # print json.dumps(vim_response.json(), indent=4)
1614 res
, http_content
= self
._format
_in
(vim_response
, new_port_response_schema
)
1615 # print http_content
1617 r
= self
._remove
_extra
_items
(http_content
, new_port_response_schema
)
1619 print("Warning: remove extra items ", r
)
1620 # print http_content
1621 port_id
= http_content
["port"]["id"]
1622 print("Port id: ", port_id
)
1623 return vim_response
.status_code
, port_id
1625 return -vimconn
.HTTP_Bad_Request
, http_content
1627 print(vim_response
.text
)
1628 jsonerror
= self
._format
_jsonerror
(vim_response
)
1630 'Error in VIM "{}": not possible to connect external port to network. HTTP Response: {}.'
1631 " Error: {}".format(self
.url_admin
, vim_response
.status_code
, jsonerror
)
1634 return -vim_response
.status_code
, text