From edca7b3cd61081d0d84de9acc4dec39daaa07419 Mon Sep 17 00:00:00 2001 From: garciadeblas Date: Thu, 29 Sep 2016 14:01:52 +0000 Subject: [PATCH 01/16] v0.4.60: fixed bug when using ip profiles in openstack, improved logs in case od unexpected exception in REST API, dos2unix vnf examples Signed-off-by: garciadeblas --- .gitignore-common | 31 +- httpserver.py | 178 +++++---- nfvo.py | 5 +- openmanod.py | 2 +- vimconn_openstack.py | 7 +- vnfs/examples/dataplaneVNF1.yaml | 162 ++++---- vnfs/examples/dataplaneVNF2.yaml | 158 ++++---- vnfs/examples/dataplaneVNF3.yaml | 130 +++---- vnfs/examples/dataplaneVNF_2VMs.yaml | 200 +++++----- vnfs/examples/dataplaneVNF_2VMs_v02.yaml | 226 +++++------ .../dataplaneVNF_2VMs_v02_withimagename.yaml | 226 +++++------ vnfs/examples/linux.yaml | 86 ++-- vnfs/examples/linux_2VMs_v02.yaml | 208 +++++----- vnfs/vnf-template-2vm.yaml | 368 +++++++++--------- vnfs/vnf-template.yaml | 214 +++++----- 15 files changed, 1127 insertions(+), 1074 deletions(-) diff --git a/.gitignore-common b/.gitignore-common index 233cf38a..c71eced3 100644 --- a/.gitignore-common +++ b/.gitignore-common @@ -1,6 +1,26 @@ -# Created by .ignore support plugin (hsz.mobi) -#this is a template with common files to be igonored, after clone make a copy to .gitignore -#cp .gitignore-common .gitignore +## +# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. +# This file is part of openmano +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# For those usages not covered by the Apache License, Version 2.0 please +# contact with: nfvlabs@tid.es +## + +# This is a template with common files to be igonored, after clone make a copy to .gitignore +# cp .gitignore-common .gitignore *.pyc @@ -10,10 +30,10 @@ #logs of openmano logs -#pycham +#pycharm .idea -#eclpise +#eclipse .project .pydevproject .settings @@ -33,3 +53,4 @@ scenarios/local instance-scenarios/local database_utils/local scripts/local + diff --git a/httpserver.py b/httpserver.py index 43f57242..cd40882f 100644 --- a/httpserver.py +++ b/httpserver.py @@ -322,8 +322,8 @@ def http_get_tenants(): logger.error("http_get_tenants error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) @bottle.route(url_base + '/tenants/', method='GET') @@ -341,8 +341,8 @@ def http_get_tenant_id(tenant_id): logger.error("http_get_tenant_id error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) @bottle.route(url_base + '/tenants', method='POST') @@ -361,8 +361,8 @@ def http_post_tenants(): logger.error("http_post_tenants error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) @bottle.route(url_base + '/tenants/', method='PUT') @@ -387,8 +387,8 @@ def http_edit_tenant_id(tenant_id): logger.error("http_edit_tenant_id error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) @bottle.route(url_base + '/tenants/', method='DELETE') @@ -402,8 +402,8 @@ def http_delete_tenant_id(tenant_id): logger.error("http_delete_tenant_id error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) @bottle.route(url_base + '//datacenters', method='GET') @@ -434,8 +434,8 @@ def http_get_datacenters(tenant_id): logger.error("http_get_datacenters error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) @bottle.route(url_base + '//datacenters/', method='GET') @@ -491,8 +491,9 @@ def http_get_datacenter_id(tenant_id, datacenter_id): logger.error("http_get_datacenter_id error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + @bottle.route(url_base + '/datacenters', method='POST') def http_post_datacenters(): @@ -510,8 +511,9 @@ def http_post_datacenters(): logger.error("http_post_datacenters error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + @bottle.route(url_base + '/datacenters/', method='PUT') def http_edit_datacenter_id(datacenter_id_name): @@ -530,8 +532,9 @@ def http_edit_datacenter_id(datacenter_id_name): logger.error("http_edit_datacenter_id error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + @bottle.route(url_base + '//datacenters//networks', method='GET') #deprecated @bottle.route(url_base + '//datacenters//netmaps', method='GET') @@ -565,8 +568,9 @@ def http_getnetmap_datacenter_id(tenant_id, datacenter_id, netmap_id=None): logger.error("http_getnetwork_datacenter_id error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + @bottle.route(url_base + '//datacenters//netmaps', method='DELETE') @bottle.route(url_base + '//datacenters//netmaps/', method='DELETE') @@ -594,8 +598,8 @@ def http_delnetmap_datacenter_id(tenant_id, datacenter_id, netmap_id=None): logger.error("http_delnetmap_datacenter_id error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) @bottle.route(url_base + '//datacenters//netmaps/upload', method='POST') @@ -611,8 +615,9 @@ def http_uploadnetmap_datacenter_id(tenant_id, datacenter_id): logger.error("http_uploadnetmap_datacenter_id error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + @bottle.route(url_base + '//datacenters//netmaps', method='POST') def http_postnetmap_datacenter_id(tenant_id, datacenter_id): @@ -634,8 +639,9 @@ def http_postnetmap_datacenter_id(tenant_id, datacenter_id): logger.error("http_postnetmap_datacenter_id error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + @bottle.route(url_base + '//datacenters//netmaps/', method='PUT') def http_putnettmap_datacenter_id(tenant_id, datacenter_id, netmap_id): @@ -655,8 +661,8 @@ def http_putnettmap_datacenter_id(tenant_id, datacenter_id, netmap_id): logger.error("http_putnettmap_datacenter_id error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) @bottle.route(url_base + '//datacenters//action', method='POST') @@ -679,8 +685,8 @@ def http_action_datacenter_id(tenant_id, datacenter_id): logger.error("http_action_datacenter_id error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) @bottle.route(url_base + '/datacenters/', method='DELETE') @@ -695,8 +701,9 @@ def http_delete_datacenter_id( datacenter_id): logger.error("http_delete_datacenter_id error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + @bottle.route(url_base + '//datacenters/', method='POST') def http_associate_datacenters(tenant_id, datacenter_id): @@ -719,8 +726,9 @@ def http_associate_datacenters(tenant_id, datacenter_id): logger.error("http_associate_datacenters error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + @bottle.route(url_base + '//datacenters/', method='DELETE') def http_deassociate_datacenters(tenant_id, datacenter_id): @@ -733,8 +741,9 @@ def http_deassociate_datacenters(tenant_id, datacenter_id): logger.error("http_deassociate_datacenters error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + @bottle.route(url_base + '//vim//', method='GET') @bottle.route(url_base + '//vim///', method='GET') @@ -747,8 +756,9 @@ def http_get_vim_items(tenant_id, datacenter_id, item, name=None): logger.error("http_get_vim_items error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + @bottle.route(url_base + '//vim///', method='DELETE') def http_del_vim_items(tenant_id, datacenter_id, item, name): @@ -760,8 +770,9 @@ def http_del_vim_items(tenant_id, datacenter_id, item, name): logger.error("http_del_vim_items error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + @bottle.route(url_base + '//vim//', method='POST') def http_post_vim_items(tenant_id, datacenter_id, item): @@ -774,8 +785,9 @@ def http_post_vim_items(tenant_id, datacenter_id, item): logger.error("http_post_vim_items error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + @bottle.route(url_base + '//vnfs', method='GET') def http_get_vnfs(tenant_id): @@ -800,8 +812,9 @@ def http_get_vnfs(tenant_id): logger.error("http_get_vnfs error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + @bottle.route(url_base + '//vnfs/', method='GET') def http_get_vnf_id(tenant_id,vnf_id): @@ -816,8 +829,9 @@ def http_get_vnf_id(tenant_id,vnf_id): logger.error("http_get_vnf_id error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + @bottle.route(url_base + '//vnfs', method='POST') def http_post_vnfs(tenant_id): @@ -842,8 +856,9 @@ def http_post_vnfs(tenant_id): logger.error("http_post_vnfs error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + @bottle.route(url_base + '//vnfs/', method='DELETE') def http_delete_vnf_id(tenant_id,vnf_id): @@ -858,8 +873,9 @@ def http_delete_vnf_id(tenant_id,vnf_id): logger.error("http_delete_vnf_id error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + #@bottle.route(url_base + '//hosts/topology', method='GET') #@bottle.route(url_base + '//physicalview/Madrid-Alcantara', method='GET') @@ -886,8 +902,8 @@ def http_get_hosts(tenant_id, datacenter): logger.error("http_get_hosts error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) @bottle.route(url_base + '/', method='OPTIONS') @@ -921,8 +937,9 @@ def http_post_deploy(tenant_id): logger.error("http_post_deploy error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + @bottle.route(url_base + '//topology/verify', method='POST') def http_post_verify(tenant_id): @@ -961,8 +978,9 @@ def http_post_scenarios(tenant_id): logger.error("http_post_scenarios error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + @bottle.route(url_base + '//scenarios//action', method='POST') def http_post_scenario_action(tenant_id, scenario_id): @@ -1002,8 +1020,9 @@ def http_post_scenario_action(tenant_id, scenario_id): logger.error("http_post_scenario_action error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + @bottle.route(url_base + '//scenarios', method='GET') def http_get_scenarios(tenant_id): @@ -1029,8 +1048,9 @@ def http_get_scenarios(tenant_id): logger.error("http_get_scenarios error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + @bottle.route(url_base + '//scenarios/', method='GET') def http_get_scenario_id(tenant_id, scenario_id): @@ -1049,8 +1069,9 @@ def http_get_scenario_id(tenant_id, scenario_id): logger.error("http_get_scenarios error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + @bottle.route(url_base + '//scenarios/', method='DELETE') def http_delete_scenario_id(tenant_id, scenario_id): @@ -1067,8 +1088,8 @@ def http_delete_scenario_id(tenant_id, scenario_id): logger.error("http_delete_scenario_id error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) @bottle.route(url_base + '//scenarios/', method='PUT') @@ -1088,12 +1109,12 @@ def http_put_scenario_id(tenant_id, scenario_id): logger.error("http_put_scenario_id error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) @bottle.route(url_base + '//instances', method='POST') def http_post_instances(tenant_id): - '''take an action over a scenario''' + '''create an instance-scenario''' logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url) try: #check valid tenant_id @@ -1110,8 +1131,8 @@ def http_post_instances(tenant_id): logger.error("http_post_instances error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) # # INSTANCES @@ -1136,8 +1157,9 @@ def http_get_instances(tenant_id): logger.error("http_get_instances error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + @bottle.route(url_base + '//instances/', method='GET') def http_get_instance_id(tenant_id, instance_id): @@ -1164,8 +1186,9 @@ def http_get_instance_id(tenant_id, instance_id): logger.error("http_get_instance_id error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + @bottle.route(url_base + '//instances/', method='DELETE') def http_delete_instance_id(tenant_id, instance_id): @@ -1184,8 +1207,9 @@ def http_delete_instance_id(tenant_id, instance_id): logger.error("http_delete_instance_id error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) + @bottle.route(url_base + '//instances//action', method='POST') def http_post_instance_scenario_action(tenant_id, instance_id): @@ -1212,8 +1236,8 @@ def http_post_instance_scenario_action(tenant_id, instance_id): logger.error("http_post_instance_scenario_action error {}: {}".format(e.http_code, str(e))) bottle.abort(e.http_code, str(e)) except Exception as e: - logger.error("Unexpected exception %s", str(e)) - bottle.abort(HTTP_Internal_Server_Error, str(e)) + logger.error("Unexpected exception: ", exc_info=True) + bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e)) @bottle.error(400) diff --git a/nfvo.py b/nfvo.py index f681f5b7..b0936e27 100644 --- a/nfvo.py +++ b/nfvo.py @@ -1768,7 +1768,10 @@ def create_instance(mydb, tenant_id, instance_dict): ipprofile['dhcp_enabled'] = ipprofile['dhcp'].get('enabled',True) ipprofile['dhcp_count'] = ipprofile['dhcp'].get('count',None) del ipprofile['dhcp'] - update(scenario_net['ip_profile'],ipprofile) + if 'ip_profile' not in scenario_net: + scenario_net['ip_profile'] = ipprofile + else: + update(scenario_net['ip_profile'],ipprofile) for interface in net_instance_desc.get('interfaces', () ): if 'ip_address' in interface: for vnf in scenarioDict['vnfs']: diff --git a/openmanod.py b/openmanod.py index 59a566dc..a5a2a53f 100755 --- a/openmanod.py +++ b/openmanod.py @@ -33,7 +33,7 @@ It loads the configuration file and launches the http_server thread that will li ''' __author__="Alfonso Tierno, Gerardo Garcia, Pablo Montes" __date__ ="$26-aug-2014 11:09:29$" -__version__="0.4.59-r502" +__version__="0.4.60-r503" version_date="Sep 2016" database_version="0.15" #expected database schema version diff --git a/vimconn_openstack.py b/vimconn_openstack.py index 70f8c012..f44257d4 100644 --- a/vimconn_openstack.py +++ b/vimconn_openstack.py @@ -227,7 +227,9 @@ class vimconnector(vimconn.vimconnector): def new_network(self,net_name, net_type, ip_profile=None, shared=False, vlan=None): '''Adds a tenant network to VIM. Returns the network identifier''' self.logger.debug("Adding a new network to VIM name '%s', type '%s'", net_name, net_type) + #self.logger.debug(">>>>>>>>>>>>>>>>>> IP profile %s", str(ip_profile)) try: + new_net = None self._reload_connection() network_dict = {'name': net_name, 'admin_state_up': True} if net_type=="data" or net_type=="ptp": @@ -255,7 +257,7 @@ class vimconnector(vimconn.vimconnector): } if 'gateway_address' in ip_profile: subnet['gateway_ip'] = ip_profile['gateway_address'] - if 'dns_address' in ip_profile: + if ip_profile.get('dns_address'): #TODO: manage dns_address as a list of addresses separated by commas subnet['dns_nameservers'] = [] subnet['dns_nameservers'].append(ip_profile['dns_address']) @@ -272,9 +274,12 @@ class vimconnector(vimconn.vimconnector): ip_int += ip_profile['dhcp_count'] ip_str = str(netaddr.IPAddress(ip_int)) subnet['allocation_pools'][0]['end'] = ip_str + #self.logger.debug(">>>>>>>>>>>>>>>>>> Subnet: %s", str(subnet)) self.neutron.create_subnet({"subnet": subnet} ) return new_net["network"]["id"] except (neExceptions.ConnectionFailed, ksExceptions.ClientException, neExceptions.NeutronException, ConnectionError) as e: + if new_net: + self.neutron.delete_network(new_net['network']['id']) self._format_exception(e) def get_network_list(self, filter_dict={}): diff --git a/vnfs/examples/dataplaneVNF1.yaml b/vnfs/examples/dataplaneVNF1.yaml index 3d702309..74206049 100644 --- a/vnfs/examples/dataplaneVNF1.yaml +++ b/vnfs/examples/dataplaneVNF1.yaml @@ -1,81 +1,81 @@ -## -# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. -# This file is part of openmano -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# For those usages not covered by the Apache License, Version 2.0 please -# contact with: nfvlabs@tid.es -## ---- -vnf: - name: dataplaneVNF1 - description: "Example of a dataplane VNF consisting of a single VM for data plane workloads with high I/O performance requirements: 14 HW threads, 16 GB hugepages and 4 10G interfaces" - external-connections: - - name: mgmt - type: mgmt # "mgmt"(autoconnect to management net) - VNFC: dataplaneVNF1-VM - local_iface_name: eth0 - description: Management interface for general use - - name: xe0 - type: data - VNFC: dataplaneVNF1-VM - local_iface_name: xe0 - description: Dataplane interface 1 - - name: xe1 - type: data - VNFC: dataplaneVNF1-VM - local_iface_name: xe1 - description: Dataplane interface 2 - - name: xe2 - type: data - VNFC: dataplaneVNF1-VM - local_iface_name: xe2 - description: Dataplane interface 3 - - name: xe3 - type: data - VNFC: dataplaneVNF1-VM - local_iface_name: xe3 - description: Dataplane interface 4 - VNFC: - - name: dataplaneVNF1-VM - description: "Dataplane VM with high I/O performance requirements: 14 HW threads, 16 GB hugepages and 4 10G interfaces" - #Copy the image to a compute path and edit this path - VNFC image: /path/to/imagefolder/dataplaneVNF1.qcow2 - numas: - - paired-threads: 7 # "cores", "paired-threads", "threads" - paired-threads-id: [ [0,1], [2,3], [4,5], [6,7], [8,9], [10,11], [12, 13] ] - memory: 16 # GBytes - interfaces: - - name: xe0 - vpci: "0000:00:11.0" - dedicated: "yes" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) - bandwidth: 10 Gbps - - name: xe1 - vpci: "0000:00:12.0" - dedicated: "yes" - bandwidth: 10 Gbps - - name: xe2 - vpci: "0000:00:13.0" - dedicated: "yes" - bandwidth: 10 Gbps - - name: xe3 - vpci: "0000:00:14.0" - dedicated: "yes" - bandwidth: 10 Gbps - bridge-ifaces: - - name: eth0 - vpci: "0000:00:09.0" - bandwidth: 1 Mbps # Optional, informative only - +## +# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. +# This file is part of openmano +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# For those usages not covered by the Apache License, Version 2.0 please +# contact with: nfvlabs@tid.es +## +--- +vnf: + name: dataplaneVNF1 + description: "Example of a dataplane VNF consisting of a single VM for data plane workloads with high I/O performance requirements: 14 HW threads, 16 GB hugepages and 4 10G interfaces" + external-connections: + - name: mgmt + type: mgmt # "mgmt"(autoconnect to management net) + VNFC: dataplaneVNF1-VM + local_iface_name: eth0 + description: Management interface for general use + - name: xe0 + type: data + VNFC: dataplaneVNF1-VM + local_iface_name: xe0 + description: Dataplane interface 1 + - name: xe1 + type: data + VNFC: dataplaneVNF1-VM + local_iface_name: xe1 + description: Dataplane interface 2 + - name: xe2 + type: data + VNFC: dataplaneVNF1-VM + local_iface_name: xe2 + description: Dataplane interface 3 + - name: xe3 + type: data + VNFC: dataplaneVNF1-VM + local_iface_name: xe3 + description: Dataplane interface 4 + VNFC: + - name: dataplaneVNF1-VM + description: "Dataplane VM with high I/O performance requirements: 14 HW threads, 16 GB hugepages and 4 10G interfaces" + #Copy the image to a compute path and edit this path + VNFC image: /path/to/imagefolder/dataplaneVNF1.qcow2 + numas: + - paired-threads: 7 # "cores", "paired-threads", "threads" + paired-threads-id: [ [0,1], [2,3], [4,5], [6,7], [8,9], [10,11], [12, 13] ] + memory: 16 # GBytes + interfaces: + - name: xe0 + vpci: "0000:00:11.0" + dedicated: "yes" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) + bandwidth: 10 Gbps + - name: xe1 + vpci: "0000:00:12.0" + dedicated: "yes" + bandwidth: 10 Gbps + - name: xe2 + vpci: "0000:00:13.0" + dedicated: "yes" + bandwidth: 10 Gbps + - name: xe3 + vpci: "0000:00:14.0" + dedicated: "yes" + bandwidth: 10 Gbps + bridge-ifaces: + - name: eth0 + vpci: "0000:00:09.0" + bandwidth: 1 Mbps # Optional, informative only + diff --git a/vnfs/examples/dataplaneVNF2.yaml b/vnfs/examples/dataplaneVNF2.yaml index 6760ed7f..f03c2080 100644 --- a/vnfs/examples/dataplaneVNF2.yaml +++ b/vnfs/examples/dataplaneVNF2.yaml @@ -1,79 +1,79 @@ -## -# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. -# This file is part of openmano -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# For those usages not covered by the Apache License, Version 2.0 please -# contact with: nfvlabs@tid.es -## ---- -vnf: - name: dataplaneVNF2 - description: "Example of a dataplane VNF consisting of a single VM for data plane workloads with high I/O performance requirements: 3 cores, 8 GB hugepages, 2 10G interfaces and 1 SR-IOV interface" - external-connections: - - name: mgmt - type: mgmt # "mgmt"(autoconnect to management net) - VNFC: dataplaneVNF2-VM - local_iface_name: eth0 - description: Management interface for general use - - name: control - type: bridge - VNFC: dataplaneVNF2-VM - local_iface_name: eth1 - description: Bridge interface - - name: xe0 - type: data - VNFC: dataplaneVNF2-VM - local_iface_name: xe0 - description: Dataplane interface 1 - - name: xe1 - type: data - VNFC: dataplaneVNF2-VM - local_iface_name: xe1 - description: Dataplane interface 2 - - name: xe2 - type: data - VNFC: dataplaneVNF2-VM - local_iface_name: xe2 - description: Dataplane interface 3 (SR-IOV) - VNFC: - - name: dataplaneVNF2-VM - description: "Dataplane VM with high I/O performance requirements: 3 cores (no hyperthreading), 8 GB hugepages, 2 10G interfaces and 1 SR-IOV interface" - #Copy the image to a compute path and edit this path - VNFC image: /path/to/imagefolder/dataplaneVNF2.qcow2 - numas: - - cores: 3 # "cores", "paired-threads", "threads" - memory: 8 # GBytes - interfaces: - - name: xe0 - vpci: "0000:00:11.0" - dedicated: "yes" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) - bandwidth: 10 Gbps - - name: xe1 - vpci: "0000:00:12.0" - dedicated: "yes" - bandwidth: 10 Gbps - - name: xe2 - vpci: "0000:00:13.0" - dedicated: "no" - bandwidth: 1 Gbps - bridge-ifaces: - - name: eth0 - vpci: "0000:00:09.0" - bandwidth: 1 Mbps # Optional, informative only - - name: eth1 - vpci: "0000:00:10.0" - bandwidth: 1 Mbps # Optional, informative only - +## +# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. +# This file is part of openmano +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# For those usages not covered by the Apache License, Version 2.0 please +# contact with: nfvlabs@tid.es +## +--- +vnf: + name: dataplaneVNF2 + description: "Example of a dataplane VNF consisting of a single VM for data plane workloads with high I/O performance requirements: 3 cores, 8 GB hugepages, 2 10G interfaces and 1 SR-IOV interface" + external-connections: + - name: mgmt + type: mgmt # "mgmt"(autoconnect to management net) + VNFC: dataplaneVNF2-VM + local_iface_name: eth0 + description: Management interface for general use + - name: control + type: bridge + VNFC: dataplaneVNF2-VM + local_iface_name: eth1 + description: Bridge interface + - name: xe0 + type: data + VNFC: dataplaneVNF2-VM + local_iface_name: xe0 + description: Dataplane interface 1 + - name: xe1 + type: data + VNFC: dataplaneVNF2-VM + local_iface_name: xe1 + description: Dataplane interface 2 + - name: xe2 + type: data + VNFC: dataplaneVNF2-VM + local_iface_name: xe2 + description: Dataplane interface 3 (SR-IOV) + VNFC: + - name: dataplaneVNF2-VM + description: "Dataplane VM with high I/O performance requirements: 3 cores (no hyperthreading), 8 GB hugepages, 2 10G interfaces and 1 SR-IOV interface" + #Copy the image to a compute path and edit this path + VNFC image: /path/to/imagefolder/dataplaneVNF2.qcow2 + numas: + - cores: 3 # "cores", "paired-threads", "threads" + memory: 8 # GBytes + interfaces: + - name: xe0 + vpci: "0000:00:11.0" + dedicated: "yes" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) + bandwidth: 10 Gbps + - name: xe1 + vpci: "0000:00:12.0" + dedicated: "yes" + bandwidth: 10 Gbps + - name: xe2 + vpci: "0000:00:13.0" + dedicated: "no" + bandwidth: 1 Gbps + bridge-ifaces: + - name: eth0 + vpci: "0000:00:09.0" + bandwidth: 1 Mbps # Optional, informative only + - name: eth1 + vpci: "0000:00:10.0" + bandwidth: 1 Mbps # Optional, informative only + diff --git a/vnfs/examples/dataplaneVNF3.yaml b/vnfs/examples/dataplaneVNF3.yaml index 73d2cf9f..87e90e17 100644 --- a/vnfs/examples/dataplaneVNF3.yaml +++ b/vnfs/examples/dataplaneVNF3.yaml @@ -1,65 +1,65 @@ -## -# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. -# This file is part of openmano -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# For those usages not covered by the Apache License, Version 2.0 please -# contact with: nfvlabs@tid.es -## ---- -vnf: - name: dataplaneVNF3 - description: "Example of a dataplane VNF consisting of one VM with two SR-IOV" - # class: parent # Optional. Used to organize VNFs - external-connections: - - name: mgmt - type: mgmt - VNFC: dataplaneVNF3-VM - local_iface_name: eth0 - description: control interface VM1 - - name: data0 - type: data - VNFC: dataplaneVNF3-VM - local_iface_name: xe0 - description: Dataplane interface - - name: data1 - type: data - VNFC: dataplaneVNF3-VM - local_iface_name: xe1 - description: Dataplane interface - VNFC: - - name: dataplaneVNF3-VM - description: "Dataplane VM with 2 threads, 2 GB hugepages, 2 SR-IOV interface" - #Copy the image to a compute path and edit this path - VNFC image: /path/to/imagefolder/dataplaneVNF3.qcow2 - disk: 10 - numas: - - threads: 2 # "cores", "paired-threads", "threads" - memory: 2 # GBytes - interfaces: - - name: xe0 - vpci: "0000:00:11.0" - dedicated: "no" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) - bandwidth: 1 Gbps - - name: xe1 - vpci: "0000:00:12.0" - dedicated: "no" - bandwidth: 1 Gbps - bridge-ifaces: - - name: eth0 - vpci: "0000:00:09.0" - bandwidth: 1 Mbps # Optional, informative only - - +## +# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. +# This file is part of openmano +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# For those usages not covered by the Apache License, Version 2.0 please +# contact with: nfvlabs@tid.es +## +--- +vnf: + name: dataplaneVNF3 + description: "Example of a dataplane VNF consisting of one VM with two SR-IOV" + # class: parent # Optional. Used to organize VNFs + external-connections: + - name: mgmt + type: mgmt + VNFC: dataplaneVNF3-VM + local_iface_name: eth0 + description: control interface VM1 + - name: data0 + type: data + VNFC: dataplaneVNF3-VM + local_iface_name: xe0 + description: Dataplane interface + - name: data1 + type: data + VNFC: dataplaneVNF3-VM + local_iface_name: xe1 + description: Dataplane interface + VNFC: + - name: dataplaneVNF3-VM + description: "Dataplane VM with 2 threads, 2 GB hugepages, 2 SR-IOV interface" + #Copy the image to a compute path and edit this path + VNFC image: /path/to/imagefolder/dataplaneVNF3.qcow2 + disk: 10 + numas: + - threads: 2 # "cores", "paired-threads", "threads" + memory: 2 # GBytes + interfaces: + - name: xe0 + vpci: "0000:00:11.0" + dedicated: "no" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) + bandwidth: 1 Gbps + - name: xe1 + vpci: "0000:00:12.0" + dedicated: "no" + bandwidth: 1 Gbps + bridge-ifaces: + - name: eth0 + vpci: "0000:00:09.0" + bandwidth: 1 Mbps # Optional, informative only + + diff --git a/vnfs/examples/dataplaneVNF_2VMs.yaml b/vnfs/examples/dataplaneVNF_2VMs.yaml index 1e468feb..8871270c 100644 --- a/vnfs/examples/dataplaneVNF_2VMs.yaml +++ b/vnfs/examples/dataplaneVNF_2VMs.yaml @@ -1,100 +1,100 @@ -## -# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. -# This file is part of openmano -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# For those usages not covered by the Apache License, Version 2.0 please -# contact with: nfvlabs@tid.es -## ---- -vnf: - name: dataplaneVNF_2VMs - description: "Example of a dataplane VNF consisting of two VMs for data plane workloads with one internal network" - # class: parent # Optional. Used to organize VNFs - internal-connections: - - name: datanet - description: datanet - type: data - elements: - - VNFC: VNF_2VMs-VM1 - local_iface_name: xe0 - - VNFC: VNF_2VMs-VM2 - local_iface_name: xe0 - external-connections: - - name: control0 - type: mgmt - VNFC: VNF_2VMs-VM1 - local_iface_name: eth0 - description: control interface VM1 - - name: control1 - type: mgmt - VNFC: VNF_2VMs-VM2 - local_iface_name: eth0 - description: control interface VM2 - - name: in - type: data - VNFC: VNF_2VMs-VM1 - local_iface_name: xe1 - description: Dataplane interface input - - name: out - type: data - VNFC: VNF_2VMs-VM2 - local_iface_name: xe1 - description: Dataplane interface output - VNFC: - - name: VNF_2VMs-VM1 - description: "Dataplane VM1 with 4 threads, 2 GB hugepages, 2 SR-IOV interface" - #Copy the image to a compute path and edit this path - VNFC image: /path/to/imagefolder/dataplaneVNF_2VMs.qcow2 - disk: 10 - numas: - - paired-threads: 2 # "cores", "paired-threads", "threads" - memory: 2 # GBytes - interfaces: - - name: xe0 - vpci: "0000:00:11.0" - dedicated: "no" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) - bandwidth: 1 Gbps - - name: xe1 - vpci: "0000:00:12.0" - dedicated: "no" - bandwidth: 1 Gbps - bridge-ifaces: - - name: eth0 - vpci: "0000:00:09.0" - bandwidth: 1 Mbps # Optional, informative only - - - name: VNF_2VMs-VM2 - description: "Dataplane VM1 with 2 threads, 2 GB hugepages, 2 SR-IOV interface" - #Copy the image to a compute path and edit this path - VNFC image: /path/to/imagefolder/dataplaneVNF_2VMs.qcow2 - disk: 10 - numas: - - paired-threads: 1 # "cores", "paired-threads", "threads" - memory: 2 # GBytes - interfaces: - - name: xe0 - vpci: "0000:00:11.0" - dedicated: "no" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) - bandwidth: 1 Gbps - - name: xe1 - vpci: "0000:00:12.0" - dedicated: "no" - bandwidth: 1 Gbps - bridge-ifaces: - - name: eth0 - vpci: "0000:00:09.0" - bandwidth: 1 Mbps # Optional, informative only - +## +# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. +# This file is part of openmano +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# For those usages not covered by the Apache License, Version 2.0 please +# contact with: nfvlabs@tid.es +## +--- +vnf: + name: dataplaneVNF_2VMs + description: "Example of a dataplane VNF consisting of two VMs for data plane workloads with one internal network" + # class: parent # Optional. Used to organize VNFs + internal-connections: + - name: datanet + description: datanet + type: data + elements: + - VNFC: VNF_2VMs-VM1 + local_iface_name: xe0 + - VNFC: VNF_2VMs-VM2 + local_iface_name: xe0 + external-connections: + - name: control0 + type: mgmt + VNFC: VNF_2VMs-VM1 + local_iface_name: eth0 + description: control interface VM1 + - name: control1 + type: mgmt + VNFC: VNF_2VMs-VM2 + local_iface_name: eth0 + description: control interface VM2 + - name: in + type: data + VNFC: VNF_2VMs-VM1 + local_iface_name: xe1 + description: Dataplane interface input + - name: out + type: data + VNFC: VNF_2VMs-VM2 + local_iface_name: xe1 + description: Dataplane interface output + VNFC: + - name: VNF_2VMs-VM1 + description: "Dataplane VM1 with 4 threads, 2 GB hugepages, 2 SR-IOV interface" + #Copy the image to a compute path and edit this path + VNFC image: /path/to/imagefolder/dataplaneVNF_2VMs.qcow2 + disk: 10 + numas: + - paired-threads: 2 # "cores", "paired-threads", "threads" + memory: 2 # GBytes + interfaces: + - name: xe0 + vpci: "0000:00:11.0" + dedicated: "no" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) + bandwidth: 1 Gbps + - name: xe1 + vpci: "0000:00:12.0" + dedicated: "no" + bandwidth: 1 Gbps + bridge-ifaces: + - name: eth0 + vpci: "0000:00:09.0" + bandwidth: 1 Mbps # Optional, informative only + + - name: VNF_2VMs-VM2 + description: "Dataplane VM1 with 2 threads, 2 GB hugepages, 2 SR-IOV interface" + #Copy the image to a compute path and edit this path + VNFC image: /path/to/imagefolder/dataplaneVNF_2VMs.qcow2 + disk: 10 + numas: + - paired-threads: 1 # "cores", "paired-threads", "threads" + memory: 2 # GBytes + interfaces: + - name: xe0 + vpci: "0000:00:11.0" + dedicated: "no" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) + bandwidth: 1 Gbps + - name: xe1 + vpci: "0000:00:12.0" + dedicated: "no" + bandwidth: 1 Gbps + bridge-ifaces: + - name: eth0 + vpci: "0000:00:09.0" + bandwidth: 1 Mbps # Optional, informative only + diff --git a/vnfs/examples/dataplaneVNF_2VMs_v02.yaml b/vnfs/examples/dataplaneVNF_2VMs_v02.yaml index dbd5bd16..bd807617 100644 --- a/vnfs/examples/dataplaneVNF_2VMs_v02.yaml +++ b/vnfs/examples/dataplaneVNF_2VMs_v02.yaml @@ -1,113 +1,113 @@ -## -# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. -# This file is part of openmano -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# For those usages not covered by the Apache License, Version 2.0 please -# contact with: nfvlabs@tid.es -## ---- -schema_version: "0.2" -vnf: - name: dataplaneVNF_2VMs_v02 - description: "Example of a dataplane VNF consisting of two VMs for data plane workloads with one internal network" - # class: parent # Optional. Used to organize VNFs - internal-connections: - - name: datanet - description: datanet - type: e-lan - implementation: underlay - ip-profile: - ip-version: IPv4 - subnet-address: 192.168.1.0/24 - gateway-address: 192.168.1.1 - dns-address: 8.8.8.8 - dhcp: - enabled: true - start-address: 192.168.1.100 - count: 100 - elements: - - VNFC: VNF_2VMs-VM1 - local_iface_name: xe0 - ip_address: 192.168.1.2 - - VNFC: VNF_2VMs-VM2 - local_iface_name: xe0 - ip_address: 192.168.1.3 - external-connections: - - name: control0 - type: mgmt - VNFC: VNF_2VMs-VM1 - local_iface_name: eth0 - description: control interface VM1 - - name: control1 - type: mgmt - VNFC: VNF_2VMs-VM2 - local_iface_name: eth0 - description: control interface VM2 - - name: in - type: data - VNFC: VNF_2VMs-VM1 - local_iface_name: xe1 - description: Dataplane interface input - - name: out - type: data - VNFC: VNF_2VMs-VM2 - local_iface_name: xe1 - description: Dataplane interface output - VNFC: - - name: VNF_2VMs-VM1 - description: "Dataplane VM1 with 4 threads, 2 GB hugepages, 2 SR-IOV interface" - #Copy the image to a compute path and edit this path - VNFC image: /path/to/imagefolder/dataplaneVNF_2VMs.qcow2 - disk: 10 - numas: - - paired-threads: 2 # "cores", "paired-threads", "threads" - memory: 2 # GBytes - interfaces: - - name: xe0 - vpci: "0000:00:11.0" - dedicated: "no" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) - bandwidth: 1 Gbps - - name: xe1 - vpci: "0000:00:12.0" - dedicated: "no" - bandwidth: 1 Gbps - bridge-ifaces: - - name: eth0 - vpci: "0000:00:09.0" - bandwidth: 1 Mbps # Optional, informative only - - - name: VNF_2VMs-VM2 - description: "Dataplane VM1 with 2 threads, 2 GB hugepages, 2 SR-IOV interface" - #Copy the image to a compute path and edit this path - VNFC image: /path/to/imagefolder/dataplaneVNF_2VMs.qcow2 - disk: 10 - numas: - - paired-threads: 1 # "cores", "paired-threads", "threads" - memory: 2 # GBytes - interfaces: - - name: xe0 - vpci: "0000:00:11.0" - dedicated: "no" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) - bandwidth: 1 Gbps - - name: xe1 - vpci: "0000:00:12.0" - dedicated: "no" - bandwidth: 1 Gbps - bridge-ifaces: - - name: eth0 - vpci: "0000:00:09.0" - bandwidth: 1 Mbps # Optional, informative only - +## +# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. +# This file is part of openmano +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# For those usages not covered by the Apache License, Version 2.0 please +# contact with: nfvlabs@tid.es +## +--- +schema_version: "0.2" +vnf: + name: dataplaneVNF_2VMs_v02 + description: "Example of a dataplane VNF consisting of two VMs for data plane workloads with one internal network" + # class: parent # Optional. Used to organize VNFs + internal-connections: + - name: datanet + description: datanet + type: e-lan + implementation: underlay + ip-profile: + ip-version: IPv4 + subnet-address: 192.168.1.0/24 + gateway-address: 192.168.1.1 + dns-address: 8.8.8.8 + dhcp: + enabled: true + start-address: 192.168.1.100 + count: 100 + elements: + - VNFC: VNF_2VMs-VM1 + local_iface_name: xe0 + ip_address: 192.168.1.2 + - VNFC: VNF_2VMs-VM2 + local_iface_name: xe0 + ip_address: 192.168.1.3 + external-connections: + - name: control0 + type: mgmt + VNFC: VNF_2VMs-VM1 + local_iface_name: eth0 + description: control interface VM1 + - name: control1 + type: mgmt + VNFC: VNF_2VMs-VM2 + local_iface_name: eth0 + description: control interface VM2 + - name: in + type: data + VNFC: VNF_2VMs-VM1 + local_iface_name: xe1 + description: Dataplane interface input + - name: out + type: data + VNFC: VNF_2VMs-VM2 + local_iface_name: xe1 + description: Dataplane interface output + VNFC: + - name: VNF_2VMs-VM1 + description: "Dataplane VM1 with 4 threads, 2 GB hugepages, 2 SR-IOV interface" + #Copy the image to a compute path and edit this path + VNFC image: /path/to/imagefolder/dataplaneVNF_2VMs.qcow2 + disk: 10 + numas: + - paired-threads: 2 # "cores", "paired-threads", "threads" + memory: 2 # GBytes + interfaces: + - name: xe0 + vpci: "0000:00:11.0" + dedicated: "no" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) + bandwidth: 1 Gbps + - name: xe1 + vpci: "0000:00:12.0" + dedicated: "no" + bandwidth: 1 Gbps + bridge-ifaces: + - name: eth0 + vpci: "0000:00:09.0" + bandwidth: 1 Mbps # Optional, informative only + + - name: VNF_2VMs-VM2 + description: "Dataplane VM1 with 2 threads, 2 GB hugepages, 2 SR-IOV interface" + #Copy the image to a compute path and edit this path + VNFC image: /path/to/imagefolder/dataplaneVNF_2VMs.qcow2 + disk: 10 + numas: + - paired-threads: 1 # "cores", "paired-threads", "threads" + memory: 2 # GBytes + interfaces: + - name: xe0 + vpci: "0000:00:11.0" + dedicated: "no" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) + bandwidth: 1 Gbps + - name: xe1 + vpci: "0000:00:12.0" + dedicated: "no" + bandwidth: 1 Gbps + bridge-ifaces: + - name: eth0 + vpci: "0000:00:09.0" + bandwidth: 1 Mbps # Optional, informative only + diff --git a/vnfs/examples/dataplaneVNF_2VMs_v02_withimagename.yaml b/vnfs/examples/dataplaneVNF_2VMs_v02_withimagename.yaml index 0c546520..674f36cc 100644 --- a/vnfs/examples/dataplaneVNF_2VMs_v02_withimagename.yaml +++ b/vnfs/examples/dataplaneVNF_2VMs_v02_withimagename.yaml @@ -1,113 +1,113 @@ -## -# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. -# This file is part of openmano -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# For those usages not covered by the Apache License, Version 2.0 please -# contact with: nfvlabs@tid.es -## ---- -schema_version: "0.2" -vnf: - name: dataplaneVNF_2VMs_v02_withimagename - description: "Example of a dataplane VNF consisting of two VMs for data plane workloads with one internal network" - # class: parent # Optional. Used to organize VNFs - internal-connections: - - name: datanet - description: datanet - type: e-lan - implementation: underlay - ip-profile: - ip-version: IPv4 - subnet-address: 192.168.1.0/24 - gateway-address: 192.168.1.1 - dns-address: 8.8.8.8 - dhcp: - enabled: true - start-address: 192.168.1.100 - count: 100 - elements: - - VNFC: VNF_2VMs-VM1 - local_iface_name: xe0 - ip_address: 192.168.1.2 - - VNFC: VNF_2VMs-VM2 - local_iface_name: xe0 - ip_address: 192.168.1.3 - external-connections: - - name: control0 - type: mgmt - VNFC: VNF_2VMs-VM1 - local_iface_name: eth0 - description: control interface VM1 - - name: control1 - type: mgmt - VNFC: VNF_2VMs-VM2 - local_iface_name: eth0 - description: control interface VM2 - - name: in - type: data - VNFC: VNF_2VMs-VM1 - local_iface_name: xe1 - description: Dataplane interface input - - name: out - type: data - VNFC: VNF_2VMs-VM2 - local_iface_name: xe1 - description: Dataplane interface output - VNFC: - - name: VNF_2VMs-VM1 - description: "Dataplane VM1 with 4 threads, 2 GB hugepages, 2 SR-IOV interface" - #Copy the image to a compute path and edit this path - image name: dataplaneVNF_2VMs-image - disk: 10 - numas: - - paired-threads: 2 # "cores", "paired-threads", "threads" - memory: 2 # GBytes - interfaces: - - name: xe0 - vpci: "0000:00:11.0" - dedicated: "no" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) - bandwidth: 1 Gbps - - name: xe1 - vpci: "0000:00:12.0" - dedicated: "no" - bandwidth: 1 Gbps - bridge-ifaces: - - name: eth0 - vpci: "0000:00:09.0" - bandwidth: 1 Mbps # Optional, informative only - - - name: VNF_2VMs-VM2 - description: "Dataplane VM1 with 2 threads, 2 GB hugepages, 2 SR-IOV interface" - #Copy the image to a compute path and edit this path - image name: dataplaneVNF_2VMs-image - disk: 10 - numas: - - paired-threads: 1 # "cores", "paired-threads", "threads" - memory: 2 # GBytes - interfaces: - - name: xe0 - vpci: "0000:00:11.0" - dedicated: "no" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) - bandwidth: 1 Gbps - - name: xe1 - vpci: "0000:00:12.0" - dedicated: "no" - bandwidth: 1 Gbps - bridge-ifaces: - - name: eth0 - vpci: "0000:00:09.0" - bandwidth: 1 Mbps # Optional, informative only - +## +# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. +# This file is part of openmano +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# For those usages not covered by the Apache License, Version 2.0 please +# contact with: nfvlabs@tid.es +## +--- +schema_version: "0.2" +vnf: + name: dataplaneVNF_2VMs_v02_withimagename + description: "Example of a dataplane VNF consisting of two VMs for data plane workloads with one internal network" + # class: parent # Optional. Used to organize VNFs + internal-connections: + - name: datanet + description: datanet + type: e-lan + implementation: underlay + ip-profile: + ip-version: IPv4 + subnet-address: 192.168.1.0/24 + gateway-address: 192.168.1.1 + dns-address: 8.8.8.8 + dhcp: + enabled: true + start-address: 192.168.1.100 + count: 100 + elements: + - VNFC: VNF_2VMs-VM1 + local_iface_name: xe0 + ip_address: 192.168.1.2 + - VNFC: VNF_2VMs-VM2 + local_iface_name: xe0 + ip_address: 192.168.1.3 + external-connections: + - name: control0 + type: mgmt + VNFC: VNF_2VMs-VM1 + local_iface_name: eth0 + description: control interface VM1 + - name: control1 + type: mgmt + VNFC: VNF_2VMs-VM2 + local_iface_name: eth0 + description: control interface VM2 + - name: in + type: data + VNFC: VNF_2VMs-VM1 + local_iface_name: xe1 + description: Dataplane interface input + - name: out + type: data + VNFC: VNF_2VMs-VM2 + local_iface_name: xe1 + description: Dataplane interface output + VNFC: + - name: VNF_2VMs-VM1 + description: "Dataplane VM1 with 4 threads, 2 GB hugepages, 2 SR-IOV interface" + #Copy the image to a compute path and edit this path + image name: dataplaneVNF_2VMs-image + disk: 10 + numas: + - paired-threads: 2 # "cores", "paired-threads", "threads" + memory: 2 # GBytes + interfaces: + - name: xe0 + vpci: "0000:00:11.0" + dedicated: "no" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) + bandwidth: 1 Gbps + - name: xe1 + vpci: "0000:00:12.0" + dedicated: "no" + bandwidth: 1 Gbps + bridge-ifaces: + - name: eth0 + vpci: "0000:00:09.0" + bandwidth: 1 Mbps # Optional, informative only + + - name: VNF_2VMs-VM2 + description: "Dataplane VM1 with 2 threads, 2 GB hugepages, 2 SR-IOV interface" + #Copy the image to a compute path and edit this path + image name: dataplaneVNF_2VMs-image + disk: 10 + numas: + - paired-threads: 1 # "cores", "paired-threads", "threads" + memory: 2 # GBytes + interfaces: + - name: xe0 + vpci: "0000:00:11.0" + dedicated: "no" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) + bandwidth: 1 Gbps + - name: xe1 + vpci: "0000:00:12.0" + dedicated: "no" + bandwidth: 1 Gbps + bridge-ifaces: + - name: eth0 + vpci: "0000:00:09.0" + bandwidth: 1 Mbps # Optional, informative only + diff --git a/vnfs/examples/linux.yaml b/vnfs/examples/linux.yaml index 796873fe..a80b71a8 100644 --- a/vnfs/examples/linux.yaml +++ b/vnfs/examples/linux.yaml @@ -1,43 +1,43 @@ -## -# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. -# This file is part of openmano -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# For those usages not covered by the Apache License, Version 2.0 please -# contact with: nfvlabs@tid.es -## ---- -vnf: - name: linux - description: Single-VM VNF with a traditional cloud VM based on generic Linux OS - external-connections: - - name: eth0 - type: bridge - VNFC: linux-VM - local_iface_name: eth0 - description: General purpose interface - VNFC: - - name: linux-VM - description: Generic Linux Virtual Machine - #Copy the image to a compute path and edit this path - VNFC image: /path/to/imagefolder/linux.qcow2 - vcpus: 1 # Only for traditional cloud VMs. Number of virtual CPUs (oversubscription is allowed). - ram: 1024 # Only for traditional cloud VMs. Memory in MBytes (not from hugepages, oversubscription is allowed) - disk: 10 - bridge-ifaces: - - name: eth0 - vpci: "0000:00:11.0" - numas: [] - +## +# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. +# This file is part of openmano +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# For those usages not covered by the Apache License, Version 2.0 please +# contact with: nfvlabs@tid.es +## +--- +vnf: + name: linux + description: Single-VM VNF with a traditional cloud VM based on generic Linux OS + external-connections: + - name: eth0 + type: bridge + VNFC: linux-VM + local_iface_name: eth0 + description: General purpose interface + VNFC: + - name: linux-VM + description: Generic Linux Virtual Machine + #Copy the image to a compute path and edit this path + VNFC image: /path/to/imagefolder/linux.qcow2 + vcpus: 1 # Only for traditional cloud VMs. Number of virtual CPUs (oversubscription is allowed). + ram: 1024 # Only for traditional cloud VMs. Memory in MBytes (not from hugepages, oversubscription is allowed) + disk: 10 + bridge-ifaces: + - name: eth0 + vpci: "0000:00:11.0" + numas: [] + diff --git a/vnfs/examples/linux_2VMs_v02.yaml b/vnfs/examples/linux_2VMs_v02.yaml index 41b5982f..fa1874be 100644 --- a/vnfs/examples/linux_2VMs_v02.yaml +++ b/vnfs/examples/linux_2VMs_v02.yaml @@ -1,104 +1,104 @@ -## -# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. -# This file is part of openmano -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# For those usages not covered by the Apache License, Version 2.0 please -# contact with: nfvlabs@tid.es -## ---- -schema_version: "0.2" -vnf: - name: linux_2VMs_v02 - description: "Example of a linux VNF consisting of two VMs with one internal network" - # class: parent # Optional. Used to organize VNFs - internal-connections: - - name: internalnet - description: internalnet - type: e-lan - implementation: overlay - ip-profile: - ip-version: IPv4 - subnet-address: 192.168.1.0/24 - gateway-address: 192.168.1.1 - dns-address: 8.8.8.8 - dhcp: - enabled: true - start-address: 192.168.1.100 - count: 100 - elements: - - VNFC: linux_2VMs-VM1 - local_iface_name: xe0 - ip_address: 192.168.1.2 - - VNFC: linux_2VMs-VM2 - local_iface_name: xe0 - ip_address: 192.168.1.3 - external-connections: - - name: control0 - type: mgmt - VNFC: linux_2VMs-VM1 - local_iface_name: eth0 - description: control interface VM1 - - name: control1 - type: mgmt - VNFC: linux_2VMs-VM2 - local_iface_name: eth0 - description: control interface VM2 - - name: in - type: bridge - VNFC: linux_2VMs-VM1 - local_iface_name: xe1 - description: data interface input - - name: out - type: bridge - VNFC: linux_2VMs-VM2 - local_iface_name: xe1 - description: data interface output - VNFC: - - name: linux_2VMs-VM1 - description: "Linux VM1 with 4 CPUs, 2 GB RAM and 3 bridge interfaces" - #Copy the image to a compute path and edit this path - VNFC image: /path/to/imagefolder/linux_VNF_2VMs.qcow2 - disk: 10 - vcpus: 4 - ram: 2048 - bridge-ifaces: - - name: eth0 - vpci: "0000:00:09.0" - bandwidth: 1 Mbps # Optional, informative only - - name: xe0 - vpci: "0000:00:11.0" - bandwidth: 1 Mbps - - name: xe1 - vpci: "0000:00:12.0" - bandwidth: 1 Mbps - - name: linux_2VMs-VM2 - description: "Linux VM2 with 2 CPUs, 2 GB RAM and 3 bridge interfaces" - #Copy the image to a compute path and edit this path - VNFC image: /path/to/imagefolder/linux_VNF_2VMs.qcow2 - disk: 10 - vcpus: 2 - ram: 2048 - bridge-ifaces: - - name: eth0 - vpci: "0000:00:09.0" - bandwidth: 1 Mbps # Optional, informative only - - name: xe0 - vpci: "0000:00:11.0" - bandwidth: 1 Mbps - - name: xe1 - vpci: "0000:00:12.0" - bandwidth: 1 Mbps - +## +# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. +# This file is part of openmano +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# For those usages not covered by the Apache License, Version 2.0 please +# contact with: nfvlabs@tid.es +## +--- +schema_version: "0.2" +vnf: + name: linux_2VMs_v02 + description: "Example of a linux VNF consisting of two VMs with one internal network" + # class: parent # Optional. Used to organize VNFs + internal-connections: + - name: internalnet + description: internalnet + type: e-lan + implementation: overlay + ip-profile: + ip-version: IPv4 + subnet-address: 192.168.1.0/24 + gateway-address: 192.168.1.1 + dns-address: 8.8.8.8 + dhcp: + enabled: true + start-address: 192.168.1.100 + count: 100 + elements: + - VNFC: linux_2VMs-VM1 + local_iface_name: xe0 + ip_address: 192.168.1.2 + - VNFC: linux_2VMs-VM2 + local_iface_name: xe0 + ip_address: 192.168.1.3 + external-connections: + - name: control0 + type: mgmt + VNFC: linux_2VMs-VM1 + local_iface_name: eth0 + description: control interface VM1 + - name: control1 + type: mgmt + VNFC: linux_2VMs-VM2 + local_iface_name: eth0 + description: control interface VM2 + - name: in + type: bridge + VNFC: linux_2VMs-VM1 + local_iface_name: xe1 + description: data interface input + - name: out + type: bridge + VNFC: linux_2VMs-VM2 + local_iface_name: xe1 + description: data interface output + VNFC: + - name: linux_2VMs-VM1 + description: "Linux VM1 with 4 CPUs, 2 GB RAM and 3 bridge interfaces" + #Copy the image to a compute path and edit this path + VNFC image: /path/to/imagefolder/linux_VNF_2VMs.qcow2 + disk: 10 + vcpus: 4 + ram: 2048 + bridge-ifaces: + - name: eth0 + vpci: "0000:00:09.0" + bandwidth: 1 Mbps # Optional, informative only + - name: xe0 + vpci: "0000:00:11.0" + bandwidth: 1 Mbps + - name: xe1 + vpci: "0000:00:12.0" + bandwidth: 1 Mbps + - name: linux_2VMs-VM2 + description: "Linux VM2 with 2 CPUs, 2 GB RAM and 3 bridge interfaces" + #Copy the image to a compute path and edit this path + VNFC image: /path/to/imagefolder/linux_VNF_2VMs.qcow2 + disk: 10 + vcpus: 2 + ram: 2048 + bridge-ifaces: + - name: eth0 + vpci: "0000:00:09.0" + bandwidth: 1 Mbps # Optional, informative only + - name: xe0 + vpci: "0000:00:11.0" + bandwidth: 1 Mbps + - name: xe1 + vpci: "0000:00:12.0" + bandwidth: 1 Mbps + diff --git a/vnfs/vnf-template-2vm.yaml b/vnfs/vnf-template-2vm.yaml index b1615db3..2e0970ab 100644 --- a/vnfs/vnf-template-2vm.yaml +++ b/vnfs/vnf-template-2vm.yaml @@ -1,184 +1,184 @@ -## -# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. -# This file is part of openmano -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# For those usages not covered by the Apache License, Version 2.0 please -# contact with: nfvlabs@tid.es -## ---- -vnf: - name: TEMPLATE-2VM - description: This is a template to help in the creation of multi-VM VNFs - # class: parent # Optional. Used to organize VNFs - internal-connections: - - name: datanet - description: datanet - type: data - elements: - - VNFC: VirtualMachine-1 - local_iface_name: xe0 - - VNFC: VirtualMachine-2 - local_iface_name: xe0 - - name: controlnet - description: controlnet - type: bridge - elements: - - VNFC: VirtualMachine-1 - local_iface_name: ge0 - - VNFC: VirtualMachine-2 - local_iface_name: ge0 - external-connections: - - name: mgmt0 - type: mgmt # "mgmt" (autoconnect to management net), "bridge", "data" - VNFC: VirtualMachine-1 # Virtual Machine this interface belongs to - local_iface_name: mgmt0 # interface name inside this Virtual Machine (must be defined in the VNFC section) - description: Management interface 1 - - name: mgmt1 - type: mgmt # "mgmt" (autoconnect to management net), "bridge", "data" - VNFC: VirtualMachine-2 # Virtual Machine this interface belongs to - local_iface_name: mgmt0 # interface name inside this Virtual Machine (must be defined in the VNFC section) - description: Management interface 2 - - name: data0 - type: data # "mgmt" (autoconnect to management net), "bridge", "data" - VNFC: VirtualMachine-1 # Virtual Machine this interface belongs to - local_iface_name: xe1 # interface name inside this Virtual Machine (must be defined in the VNFC section) - description: Data interface 1 - - name: data1 - type: data # "mgmt" (autoconnect to management net), "bridge", "data" - VNFC: VirtualMachine-2 # Virtual Machine this interface belongs to - local_iface_name: xe1 # interface name inside this Virtual Machine (must be defined in the VNFC section) - description: Data interface 2 - VNFC: # Virtual machine array - # First Virtual Machine - - name: VirtualMachine-1 # name of Virtual Machine - description: VM 1 in the MultiVM template - VNFC image: /path/to/imagefolder/TEMPLATE-2VM-VM1.qcow2 - # image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } #Optional - # processor: #Optional - # model: Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz - # features: ["64b", "iommu", "lps", "tlbps", "hwsv", "dioc", "ht"] - # hypervisor: #Optional - # type: QEMU-kvm - # version: "10002|12001|2.6.32-358.el6.x86_64" - # vcpus: 1 # Only for traditional cloud VMs. Number of virtual CPUs (oversubscription is allowed). - # ram: 1024 # Only for traditional cloud VMs. Memory in MBytes (not from hugepages, oversubscription is allowed) - # disk: 10 # disk size in GiB, by default 1 - numas: - - paired-threads: 5 # "cores", "paired-threads", "threads" - paired-threads-id: [ [0,1], [2,3], [4,5], [6,7], [8,9] ] # By default follows incremental order - memory: 14 # GBytes - interfaces: - - name: xe0 - vpci: "0000:00:11.0" - dedicated: "yes" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) - bandwidth: 10 Gbps - #mac_address: '20:33:45:56:77:44' #avoid this option if possible - - name: xe1 - vpci: "0000:00:12.0" - dedicated: "yes" - bandwidth: 10 Gbps - #mac_address: '20:33:45:56:77:45' #avoid this option if possible - bridge-ifaces: - - name: mgmt0 - vpci: "0000:00:09.0" # Optional. Virtual PCI address - bandwidth: 1 Mbps # Optional. Informative only - # mac_address: '20:33:45:56:77:46' #avoid this option if possible - # model: 'virtio' # ("virtio","e1000","ne2k_pci","pcnet","rtl8139") By default, it is automatically filled by libvirt - - name: ge0 - vpci: "0000:00:10.0" - bandwidth: 1 Mbps - # mac_address: '20:33:45:56:77:47' # avoid this option if possible - # model: 'virtio' # ("virtio","e1000","ne2k_pci","pcnet","rtl8139") By default, it is automatically filled by libvirt - devices: # Optional, order determines device letter asignation (hda, hdb, ...) - - type: disk # "disk","cdrom","xml" - image: /path/to/imagefolder/SECOND-DISK.qcow2 - # image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } - # vpci: "0000:00:03.0" # Optional, not for disk or cdrom - - type: cdrom - image: /path/to/imagefolder/CDROM-IMAGE.qcow2 - # image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } - - type: xml - image: /path/to/imagefolder/ADDITIONAL-DISK.qcow2 # Optional, depending on the device type - image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } # Optional, depending on the device type - vpci: "0000:00:03.0" # Optional, depending on the device type (not needed for disk or cdrom) - xml: ' xml text for XML described devices. Do not use single quotes inside - The following words, if found, will be replaced: - __file__ by image path, (image must be provided) - __format__ by qcow2 or raw (image must be provided) - __dev__ by device letter (b, c, d ...) - __vpci__ by vpci (vpci must be provided) - ' - # Second Virtual Machine - - name: VirtualMachine-2 # name of Virtual Machine - description: VM 2 in the MultiVM template - VNFC image: /path/to/imagefolder/TEMPLATE-2VM-VM1.qcow2 # In this case, it is the same as VirtualMachine-1, but it could have been different - # image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } #Optional - # processor: #Optional - # model: Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz - # features: ["64b", "iommu", "lps", "tlbps", "hwsv", "dioc", "ht"] - # hypervisor: #Optional - # type: QEMU-kvm - # version: "10002|12001|2.6.32-358.el6.x86_64" - # vcpus: 1 # Only for traditional cloud VMs. Number of virtual CPUs (oversubscription is allowed). - # ram: 1024 # Only for traditional cloud VMs. Memory in MBytes (not from hugepages, oversubscription is allowed) - # disk: 10 # disk size in GiB, by default 1 - numas: - - paired-threads: 5 # "cores", "paired-threads", "threads" - paired-threads-id: [ [0,1], [2,3], [4,5], [6,7], [8,9] ] # By default follows incremental order - memory: 14 # GBytes - interfaces: - - name: xe0 - vpci: "0000:00:11.0" - dedicated: "yes" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) - bandwidth: 10 Gbps - #mac_address: '20:33:45:56:77:44' #avoid this option if possible - - name: xe1 - vpci: "0000:00:12.0" - dedicated: "yes" - bandwidth: 10 Gbps - #mac_address: '20:33:45:56:77:45' #avoid this option if possible - bridge-ifaces: - - name: mgmt0 - vpci: "0000:00:09.0" # Optional - bandwidth: 1 Mbps # Optional, informative only - # mac_address: '20:33:45:56:77:46' #avoid this option if possible - # model: 'virtio' # ("virtio","e1000","ne2k_pci","pcnet","rtl8139") By default, it is automatically filled by libvirt - - name: ge0 - vpci: "0000:00:10.0" - bandwidth: 1 Mbps - # mac_address: '20:33:45:56:77:47' #avoid this option if possible - # model: 'virtio' # ("virtio","e1000","ne2k_pci","pcnet","rtl8139") By default, it is automatically filled by libvirt - devices: # Optional, order determines device letter asignation (hda, hdb, ...) - - type: disk # "disk","cdrom","xml" - image: /path/to/imagefolder/SECOND-DISK.qcow2 - # image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } - # vpci: "0000:00:03.0" # Optional, not for disk or cdrom - - type: cdrom - image: /path/to/imagefolder/CDROM-IMAGE.qcow2 - #image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } - - type: xml - image: /path/to/imagefolder/ADDITIONAL-DISK.qcow2 # Optional, depending on the device type - image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } # Optional, depending on the device type - vpci: "0000:00:03.0" # Optional, depending on the device type (not needed for disk or cdrom) - xml: ' xml text for XML described devices. Do not use single quotes inside - The following words, if found, will be replaced: - __file__ by image path, (image must be provided) - __format__ by qcow2 or raw (image must be provided) - __dev__ by device letter (b, c, d ...) - __vpci__ by vpci (vpci must be provided) - ' - # Additional Virtual Machines can be included here - +## +# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. +# This file is part of openmano +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# For those usages not covered by the Apache License, Version 2.0 please +# contact with: nfvlabs@tid.es +## +--- +vnf: + name: TEMPLATE-2VM + description: This is a template to help in the creation of multi-VM VNFs + # class: parent # Optional. Used to organize VNFs + internal-connections: + - name: datanet + description: datanet + type: data + elements: + - VNFC: VirtualMachine-1 + local_iface_name: xe0 + - VNFC: VirtualMachine-2 + local_iface_name: xe0 + - name: controlnet + description: controlnet + type: bridge + elements: + - VNFC: VirtualMachine-1 + local_iface_name: ge0 + - VNFC: VirtualMachine-2 + local_iface_name: ge0 + external-connections: + - name: mgmt0 + type: mgmt # "mgmt" (autoconnect to management net), "bridge", "data" + VNFC: VirtualMachine-1 # Virtual Machine this interface belongs to + local_iface_name: mgmt0 # interface name inside this Virtual Machine (must be defined in the VNFC section) + description: Management interface 1 + - name: mgmt1 + type: mgmt # "mgmt" (autoconnect to management net), "bridge", "data" + VNFC: VirtualMachine-2 # Virtual Machine this interface belongs to + local_iface_name: mgmt0 # interface name inside this Virtual Machine (must be defined in the VNFC section) + description: Management interface 2 + - name: data0 + type: data # "mgmt" (autoconnect to management net), "bridge", "data" + VNFC: VirtualMachine-1 # Virtual Machine this interface belongs to + local_iface_name: xe1 # interface name inside this Virtual Machine (must be defined in the VNFC section) + description: Data interface 1 + - name: data1 + type: data # "mgmt" (autoconnect to management net), "bridge", "data" + VNFC: VirtualMachine-2 # Virtual Machine this interface belongs to + local_iface_name: xe1 # interface name inside this Virtual Machine (must be defined in the VNFC section) + description: Data interface 2 + VNFC: # Virtual machine array + # First Virtual Machine + - name: VirtualMachine-1 # name of Virtual Machine + description: VM 1 in the MultiVM template + VNFC image: /path/to/imagefolder/TEMPLATE-2VM-VM1.qcow2 + # image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } #Optional + # processor: #Optional + # model: Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz + # features: ["64b", "iommu", "lps", "tlbps", "hwsv", "dioc", "ht"] + # hypervisor: #Optional + # type: QEMU-kvm + # version: "10002|12001|2.6.32-358.el6.x86_64" + # vcpus: 1 # Only for traditional cloud VMs. Number of virtual CPUs (oversubscription is allowed). + # ram: 1024 # Only for traditional cloud VMs. Memory in MBytes (not from hugepages, oversubscription is allowed) + # disk: 10 # disk size in GiB, by default 1 + numas: + - paired-threads: 5 # "cores", "paired-threads", "threads" + paired-threads-id: [ [0,1], [2,3], [4,5], [6,7], [8,9] ] # By default follows incremental order + memory: 14 # GBytes + interfaces: + - name: xe0 + vpci: "0000:00:11.0" + dedicated: "yes" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) + bandwidth: 10 Gbps + #mac_address: '20:33:45:56:77:44' #avoid this option if possible + - name: xe1 + vpci: "0000:00:12.0" + dedicated: "yes" + bandwidth: 10 Gbps + #mac_address: '20:33:45:56:77:45' #avoid this option if possible + bridge-ifaces: + - name: mgmt0 + vpci: "0000:00:09.0" # Optional. Virtual PCI address + bandwidth: 1 Mbps # Optional. Informative only + # mac_address: '20:33:45:56:77:46' #avoid this option if possible + # model: 'virtio' # ("virtio","e1000","ne2k_pci","pcnet","rtl8139") By default, it is automatically filled by libvirt + - name: ge0 + vpci: "0000:00:10.0" + bandwidth: 1 Mbps + # mac_address: '20:33:45:56:77:47' # avoid this option if possible + # model: 'virtio' # ("virtio","e1000","ne2k_pci","pcnet","rtl8139") By default, it is automatically filled by libvirt + devices: # Optional, order determines device letter asignation (hda, hdb, ...) + - type: disk # "disk","cdrom","xml" + image: /path/to/imagefolder/SECOND-DISK.qcow2 + # image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } + # vpci: "0000:00:03.0" # Optional, not for disk or cdrom + - type: cdrom + image: /path/to/imagefolder/CDROM-IMAGE.qcow2 + # image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } + - type: xml + image: /path/to/imagefolder/ADDITIONAL-DISK.qcow2 # Optional, depending on the device type + image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } # Optional, depending on the device type + vpci: "0000:00:03.0" # Optional, depending on the device type (not needed for disk or cdrom) + xml: ' xml text for XML described devices. Do not use single quotes inside + The following words, if found, will be replaced: + __file__ by image path, (image must be provided) + __format__ by qcow2 or raw (image must be provided) + __dev__ by device letter (b, c, d ...) + __vpci__ by vpci (vpci must be provided) + ' + # Second Virtual Machine + - name: VirtualMachine-2 # name of Virtual Machine + description: VM 2 in the MultiVM template + VNFC image: /path/to/imagefolder/TEMPLATE-2VM-VM1.qcow2 # In this case, it is the same as VirtualMachine-1, but it could have been different + # image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } #Optional + # processor: #Optional + # model: Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz + # features: ["64b", "iommu", "lps", "tlbps", "hwsv", "dioc", "ht"] + # hypervisor: #Optional + # type: QEMU-kvm + # version: "10002|12001|2.6.32-358.el6.x86_64" + # vcpus: 1 # Only for traditional cloud VMs. Number of virtual CPUs (oversubscription is allowed). + # ram: 1024 # Only for traditional cloud VMs. Memory in MBytes (not from hugepages, oversubscription is allowed) + # disk: 10 # disk size in GiB, by default 1 + numas: + - paired-threads: 5 # "cores", "paired-threads", "threads" + paired-threads-id: [ [0,1], [2,3], [4,5], [6,7], [8,9] ] # By default follows incremental order + memory: 14 # GBytes + interfaces: + - name: xe0 + vpci: "0000:00:11.0" + dedicated: "yes" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) + bandwidth: 10 Gbps + #mac_address: '20:33:45:56:77:44' #avoid this option if possible + - name: xe1 + vpci: "0000:00:12.0" + dedicated: "yes" + bandwidth: 10 Gbps + #mac_address: '20:33:45:56:77:45' #avoid this option if possible + bridge-ifaces: + - name: mgmt0 + vpci: "0000:00:09.0" # Optional + bandwidth: 1 Mbps # Optional, informative only + # mac_address: '20:33:45:56:77:46' #avoid this option if possible + # model: 'virtio' # ("virtio","e1000","ne2k_pci","pcnet","rtl8139") By default, it is automatically filled by libvirt + - name: ge0 + vpci: "0000:00:10.0" + bandwidth: 1 Mbps + # mac_address: '20:33:45:56:77:47' #avoid this option if possible + # model: 'virtio' # ("virtio","e1000","ne2k_pci","pcnet","rtl8139") By default, it is automatically filled by libvirt + devices: # Optional, order determines device letter asignation (hda, hdb, ...) + - type: disk # "disk","cdrom","xml" + image: /path/to/imagefolder/SECOND-DISK.qcow2 + # image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } + # vpci: "0000:00:03.0" # Optional, not for disk or cdrom + - type: cdrom + image: /path/to/imagefolder/CDROM-IMAGE.qcow2 + #image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } + - type: xml + image: /path/to/imagefolder/ADDITIONAL-DISK.qcow2 # Optional, depending on the device type + image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } # Optional, depending on the device type + vpci: "0000:00:03.0" # Optional, depending on the device type (not needed for disk or cdrom) + xml: ' xml text for XML described devices. Do not use single quotes inside + The following words, if found, will be replaced: + __file__ by image path, (image must be provided) + __format__ by qcow2 or raw (image must be provided) + __dev__ by device letter (b, c, d ...) + __vpci__ by vpci (vpci must be provided) + ' + # Additional Virtual Machines can be included here + diff --git a/vnfs/vnf-template.yaml b/vnfs/vnf-template.yaml index 5b33512d..121c5abb 100644 --- a/vnfs/vnf-template.yaml +++ b/vnfs/vnf-template.yaml @@ -1,107 +1,107 @@ -## -# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. -# This file is part of openmano -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# For those usages not covered by the Apache License, Version 2.0 please -# contact with: nfvlabs@tid.es -## ---- -vnf: - name: TEMPLATE - description: This is a template to help in the creation of your own VNFs - # class: parent # Optional. Used to organize VNFs - external-connections: - - name: mgmt0 - type: mgmt # "mgmt" (autoconnect to management net), "bridge", "data" - VNFC: TEMPLATE-VM # Virtual Machine this interface belongs to - local_iface_name: mgmt0 # interface name inside this Virtual Machine (must be defined in the VNFC section) - description: Management interface - - name: xe0 - type: data - VNFC: TEMPLATE-VM - local_iface_name: xe0 - description: Data interface 1 - - name: xe1 - type: data - VNFC: TEMPLATE-VM - local_iface_name: xe1 - description: Data interface 2 - - name: ge0 - type: bridge - VNFC: TEMPLATE-VM - local_iface_name: ge0 - description: Bridge interface - VNFC: # Virtual machine array - - name: TEMPLATE-VM # name of Virtual Machine - description: TEMPLATE description - VNFC image: /path/to/imagefolder/TEMPLATE-VM.qcow2 - # image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } #Optional - # processor: #Optional - # model: Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz - # features: ["64b", "iommu", "lps", "tlbps", "hwsv", "dioc", "ht"] - # hypervisor: #Optional - # type: QEMU-kvm - # version: "10002|12001|2.6.32-358.el6.x86_64" - # vcpus: 1 # Only for traditional cloud VMs. Number of virtual CPUs (oversubscription is allowed). - # ram: 1024 # Only for traditional cloud VMs. Memory in MBytes (not from hugepages, oversubscription is allowed) - # disk: 10 # disk size in GiB, by default 1 - numas: - - paired-threads: 5 # "cores", "paired-threads", "threads" - paired-threads-id: [ [0,1], [2,3], [4,5], [6,7], [8,9] ] # By default follows incremental order - memory: 14 # GBytes - interfaces: - - name: xe0 - vpci: "0000:00:11.0" - dedicated: "yes" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) - bandwidth: 10 Gbps - # mac_address: '20:33:45:56:77:44' #avoid this option if possible - - name: xe1 - vpci: "0000:00:12.0" - dedicated: "yes" - bandwidth: 10 Gbps - # mac_address: '20:33:45:56:77:45' #avoid this option if possible - bridge-ifaces: - - name: mgmt0 - vpci: "0000:00:09.0" # Optional. Virtual PCI address - bandwidth: 1 Mbps # Optional. Informative only - # mac_address: '20:33:45:56:77:46' #avoid this option if possible - # model: 'virtio' # ("virtio","e1000","ne2k_pci","pcnet","rtl8139") By default, it is automatically filled by libvirt - - name: ge0 - vpci: "0000:00:10.0" - bandwidth: 1 Mbps - # mac_address: '20:33:45:56:77:47' #avoid this option if possible - # model: 'virtio' # ("virtio","e1000","ne2k_pci","pcnet","rtl8139") By default, it is automatically filled by libvirt - devices: # Optional, order determines device letter asignation (hda, hdb, ...) - - type: disk # "disk","cdrom","xml" - image: /path/to/imagefolder/SECOND-DISK.qcow2 - # image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } - # vpci: "0000:00:03.0" # Optional, not for disk or cdrom - - type: cdrom - image: /path/to/imagefolder/CDROM-IMAGE.qcow2 - # image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } - - type: xml - image: /path/to/imagefolder/ADDITIONAL-DISK.qcow2 # Optional, depending on the device type - image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } # Optional, depending on the device type - vpci: "0000:00:03.0" # Optional, depending on the device type (not needed for disk or cdrom) - xml: ' xml text for XML described devices. Do not use single quotes inside - The following words, if found, will be replaced: - __file__ by image path, (image must be provided) - __format__ by qcow2 or raw (image must be provided) - __dev__ by device letter (b, c, d ...) - __vpci__ by vpci (vpci must be provided) - ' - # Additional Virtual Machines would be included here - +## +# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. +# This file is part of openmano +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# For those usages not covered by the Apache License, Version 2.0 please +# contact with: nfvlabs@tid.es +## +--- +vnf: + name: TEMPLATE + description: This is a template to help in the creation of your own VNFs + # class: parent # Optional. Used to organize VNFs + external-connections: + - name: mgmt0 + type: mgmt # "mgmt" (autoconnect to management net), "bridge", "data" + VNFC: TEMPLATE-VM # Virtual Machine this interface belongs to + local_iface_name: mgmt0 # interface name inside this Virtual Machine (must be defined in the VNFC section) + description: Management interface + - name: xe0 + type: data + VNFC: TEMPLATE-VM + local_iface_name: xe0 + description: Data interface 1 + - name: xe1 + type: data + VNFC: TEMPLATE-VM + local_iface_name: xe1 + description: Data interface 2 + - name: ge0 + type: bridge + VNFC: TEMPLATE-VM + local_iface_name: ge0 + description: Bridge interface + VNFC: # Virtual machine array + - name: TEMPLATE-VM # name of Virtual Machine + description: TEMPLATE description + VNFC image: /path/to/imagefolder/TEMPLATE-VM.qcow2 + # image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } #Optional + # processor: #Optional + # model: Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz + # features: ["64b", "iommu", "lps", "tlbps", "hwsv", "dioc", "ht"] + # hypervisor: #Optional + # type: QEMU-kvm + # version: "10002|12001|2.6.32-358.el6.x86_64" + # vcpus: 1 # Only for traditional cloud VMs. Number of virtual CPUs (oversubscription is allowed). + # ram: 1024 # Only for traditional cloud VMs. Memory in MBytes (not from hugepages, oversubscription is allowed) + # disk: 10 # disk size in GiB, by default 1 + numas: + - paired-threads: 5 # "cores", "paired-threads", "threads" + paired-threads-id: [ [0,1], [2,3], [4,5], [6,7], [8,9] ] # By default follows incremental order + memory: 14 # GBytes + interfaces: + - name: xe0 + vpci: "0000:00:11.0" + dedicated: "yes" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) + bandwidth: 10 Gbps + # mac_address: '20:33:45:56:77:44' #avoid this option if possible + - name: xe1 + vpci: "0000:00:12.0" + dedicated: "yes" + bandwidth: 10 Gbps + # mac_address: '20:33:45:56:77:45' #avoid this option if possible + bridge-ifaces: + - name: mgmt0 + vpci: "0000:00:09.0" # Optional. Virtual PCI address + bandwidth: 1 Mbps # Optional. Informative only + # mac_address: '20:33:45:56:77:46' #avoid this option if possible + # model: 'virtio' # ("virtio","e1000","ne2k_pci","pcnet","rtl8139") By default, it is automatically filled by libvirt + - name: ge0 + vpci: "0000:00:10.0" + bandwidth: 1 Mbps + # mac_address: '20:33:45:56:77:47' #avoid this option if possible + # model: 'virtio' # ("virtio","e1000","ne2k_pci","pcnet","rtl8139") By default, it is automatically filled by libvirt + devices: # Optional, order determines device letter asignation (hda, hdb, ...) + - type: disk # "disk","cdrom","xml" + image: /path/to/imagefolder/SECOND-DISK.qcow2 + # image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } + # vpci: "0000:00:03.0" # Optional, not for disk or cdrom + - type: cdrom + image: /path/to/imagefolder/CDROM-IMAGE.qcow2 + # image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } + - type: xml + image: /path/to/imagefolder/ADDITIONAL-DISK.qcow2 # Optional, depending on the device type + image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } # Optional, depending on the device type + vpci: "0000:00:03.0" # Optional, depending on the device type (not needed for disk or cdrom) + xml: ' xml text for XML described devices. Do not use single quotes inside + The following words, if found, will be replaced: + __file__ by image path, (image must be provided) + __format__ by qcow2 or raw (image must be provided) + __dev__ by device letter (b, c, d ...) + __vpci__ by vpci (vpci must be provided) + ' + # Additional Virtual Machines would be included here + -- 2.25.1 From fe78990bf0944f559acb02c69452124db66fe8a4 Mon Sep 17 00:00:00 2001 From: tierno Date: Thu, 29 Sep 2016 14:20:44 +0000 Subject: [PATCH 02/16] fixing logs at vimconn Signed-off-by: tierno --- vimconn.py | 5 +++-- vimconn_openstack.py | 4 +++- vimconn_vmware.py | 6 +++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/vimconn.py b/vimconn.py index 7d68ac45..cd529de8 100644 --- a/vimconn.py +++ b/vimconn.py @@ -82,7 +82,7 @@ class vimconnector(): These plugins must implement a vimconnector class derived from this and all these methods ''' - def __init__(self, uuid, name, tenant_id, tenant_name, url, url_admin=None, user=None, passwd=None, log_level="ERROR", config={}): + def __init__(self, uuid, name, tenant_id, tenant_name, url, url_admin=None, user=None, passwd=None, log_level=None, config={}): self.id = uuid self.name = name self.url = url @@ -93,7 +93,8 @@ class vimconnector(): self.passwd = passwd self.config = config self.logger = logging.getLogger('openmano.vim') - self.logger.setLevel( getattr(logging, log_level) ) + if log_level: + self.logger.setLevel( getattr(logging, log_level) ) if not self.url_admin: #try to use normal url self.url_admin = self.url diff --git a/vimconn_openstack.py b/vimconn_openstack.py index f44257d4..6396b77a 100644 --- a/vimconn_openstack.py +++ b/vimconn_openstack.py @@ -56,7 +56,7 @@ netStatus2manoFormat={'ACTIVE':'ACTIVE','PAUSED':'PAUSED','INACTIVE':'INACTIVE', } class vimconnector(vimconn.vimconnector): - def __init__(self, uuid, name, tenant_id, tenant_name, url, url_admin=None, user=None, passwd=None, log_level="DEBUG", config={}): + def __init__(self, uuid, name, tenant_id, tenant_name, url, url_admin=None, user=None, passwd=None, log_level=None, config={}): '''using common constructor parameters. In this case 'url' is the keystone authorization url, 'url_admin' is not use @@ -83,6 +83,8 @@ class vimconnector(vimconn.vimconnector): self.n_creds['api_key'] = passwd self.reload_client = True self.logger = logging.getLogger('openmano.vim.openstack') + if log_level: + self.logger.setLevel( getattr(logging, log_level) ) def __setitem__(self,index, value): '''Set individuals parameters diff --git a/vimconn_vmware.py b/vimconn_vmware.py index 64a1542e..069c0bc8 100644 --- a/vimconn_vmware.py +++ b/vimconn_vmware.py @@ -103,7 +103,7 @@ flavorlist = {} class vimconnector(vimconn.vimconnector): def __init__(self, uuid=None, name=None, tenant_id=None, tenant_name=None, - url=None, url_admin=None, user=None, passwd=None, log_level="ERROR", config={}): + url=None, url_admin=None, user=None, passwd=None, log_level=None, config={}): """ Constructor create vmware connector to vCloud director. @@ -151,7 +151,8 @@ class vimconnector(vimconn.vimconnector): self.admin_user = None self.logger = logging.getLogger('openmano.vim.vmware') - self.logger.setLevel(10) + if log_level: + self.logger.setLevel( getattr(logging, log_level) ) try: self.admin_user = config['admin_username'] @@ -159,7 +160,6 @@ class vimconnector(vimconn.vimconnector): except KeyError: raise vimconn.vimconnException(message="Error admin username or admin password is empty.") - self.logger = logging.getLogger('mano.vim.vmware') self.org_uuid = None self.vca = None -- 2.25.1 From 21d795b8a9eaac3b1887cec4fb6150f3536c1552 Mon Sep 17 00:00:00 2001 From: garciadeblas Date: Thu, 29 Sep 2016 17:31:46 +0200 Subject: [PATCH 03/16] Fix bug in vimconn_openstack related to dhcp_count Change-Id: Ib9ffc7034f413230ede334735380dea7cf93744a Signed-off-by: garciadeblas --- vimconn_openstack.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vimconn_openstack.py b/vimconn_openstack.py index 6396b77a..0fc5bbda 100644 --- a/vimconn_openstack.py +++ b/vimconn_openstack.py @@ -273,7 +273,7 @@ class vimconnector(vimconn.vimconnector): #parts = ip_profile['dhcp_start_address'].split('.') #ip_int = (int(parts[0]) << 24) + (int(parts[1]) << 16) + (int(parts[2]) << 8) + int(parts[3]) ip_int = int(netaddr.IPAddress(ip_profile['dhcp_start_address'])) - ip_int += ip_profile['dhcp_count'] + ip_int += ip_profile['dhcp_count'] - 1 ip_str = str(netaddr.IPAddress(ip_int)) subnet['allocation_pools'][0]['end'] = ip_str #self.logger.debug(">>>>>>>>>>>>>>>>>> Subnet: %s", str(subnet)) -- 2.25.1 From a9a7e620972e361c37440d66c717b9e2ff425d51 Mon Sep 17 00:00:00 2001 From: tierno Date: Fri, 30 Sep 2016 08:43:32 +0000 Subject: [PATCH 04/16] fix a bug getting log-socket-host option param Signed-off-by: tierno --- openmanod.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmanod.py b/openmanod.py index a5a2a53f..6df29d11 100755 --- a/openmanod.py +++ b/openmanod.py @@ -173,7 +173,7 @@ if __name__=="__main__": port_admin = a elif o == "--log-socket-port": log_socket_port = a - elif o == "--log-socket-port": + elif o == "--log-socket-host": log_socket_host = a elif o == "--log-file": log_file = a -- 2.25.1 From 9a241aa0b7825ce49e7d7822ce0d59b1a6cdc9eb Mon Sep 17 00:00:00 2001 From: garciadeblas Date: Fri, 30 Sep 2016 12:25:59 +0200 Subject: [PATCH 05/16] Tests updated to test deployment of VNFs using image name instead of path Change-Id: I84ea680fae05b900715504b6ebdcef55e8937d28 Signed-off-by: garciadeblas --- test/basictest.sh | 10 ++++++---- ..._2VMs_v02_withimagename.yaml => dataplaneVNF4.yaml} | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) rename vnfs/examples/{dataplaneVNF_2VMs_v02_withimagename.yaml => dataplaneVNF4.yaml} (97%) diff --git a/test/basictest.sh b/test/basictest.sh index 11162dd9..9c7b8885 100755 --- a/test/basictest.sh +++ b/test/basictest.sh @@ -135,16 +135,18 @@ then ${DIRmano}/openmano instance-scenario-delete -f complex2-instance || echo "fail" ${DIRmano}/openmano instance-scenario-delete -f complex3-instance || echo "fail" ${DIRmano}/openmano instance-scenario-delete -f complex4-instance || echo "fail" + ${DIRmano}/openmano instance-scenario-delete -f complex5-instance || echo "fail" ${DIRmano}/openmano scenario-delete -f simple || echo "fail" ${DIRmano}/openmano scenario-delete -f complex || echo "fail" ${DIRmano}/openmano scenario-delete -f complex2 || echo "fail" ${DIRmano}/openmano scenario-delete -f complex3 || echo "fail" ${DIRmano}/openmano scenario-delete -f complex4 || echo "fail" + ${DIRmano}/openmano scenario-delete -f complex5 || echo "fail" ${DIRmano}/openmano vnf-delete -f linux || echo "fail" ${DIRmano}/openmano vnf-delete -f linux_2VMs_v02 || echo "fail" ${DIRmano}/openmano vnf-delete -f dataplaneVNF_2VMs || echo "fail" ${DIRmano}/openmano vnf-delete -f dataplaneVNF_2VMs_v02 || echo "fail" - ${DIRmano}/openmano vnf-delete -f dataplaneVNF_2VMs_v02_withimagename || echo "fail" + ${DIRmano}/openmano vnf-delete -f dataplaneVNF4 || echo "fail" ${DIRmano}/openmano vnf-delete -f dataplaneVNF2 || echo "fail" ${DIRmano}/openmano vnf-delete -f dataplaneVNF3 || echo "fail" ${DIRmano}/openmano datacenter-detach TEST-dc || echo "fail" @@ -188,7 +190,7 @@ then [[ $? != 0 ]] && echo "FAIL" && echo " $result" && $_exit 1 echo OK - for VNF in linux dataplaneVNF1 dataplaneVNF2 dataplaneVNF_2VMs dataplaneVNF_2VMs_v02 dataplaneVNF3 linux_2VMs_v02 dataplaneVNF_2VMs_v02_withimagename + for VNF in linux dataplaneVNF1 dataplaneVNF2 dataplaneVNF_2VMs dataplaneVNF_2VMs_v02 dataplaneVNF3 linux_2VMs_v02 dataplaneVNF4 do printf "%-50s" "Creating VNF '${VNF}': " result=`$DIRmano/openmano vnf-create $DIRmano/vnfs/examples/${VNF}.yaml` @@ -197,7 +199,7 @@ then ! is_valid_uuid $vnf && echo FAIL && echo " $result" && $_exit 1 echo $vnf done - for NS in simple complex complex2 complex3 complex4 + for NS in simple complex complex2 complex3 complex4 complex5 do printf "%-50s" "Creating scenario '${NS}':" result=`$DIRmano/openmano scenario-create $DIRmano/scenarios/examples/${NS}.yaml` @@ -206,7 +208,7 @@ then echo $scenario done - for IS in simple complex complex2 complex3 + for IS in simple complex complex2 complex3 complex5 do printf "%-50s" "Creating instance-scenario '${IS}':" result=`$DIRmano/openmano instance-scenario-create --scenario ${IS} --name ${IS}-instance` diff --git a/vnfs/examples/dataplaneVNF_2VMs_v02_withimagename.yaml b/vnfs/examples/dataplaneVNF4.yaml similarity index 97% rename from vnfs/examples/dataplaneVNF_2VMs_v02_withimagename.yaml rename to vnfs/examples/dataplaneVNF4.yaml index 674f36cc..5b2132dd 100644 --- a/vnfs/examples/dataplaneVNF_2VMs_v02_withimagename.yaml +++ b/vnfs/examples/dataplaneVNF4.yaml @@ -21,8 +21,8 @@ --- schema_version: "0.2" vnf: - name: dataplaneVNF_2VMs_v02_withimagename - description: "Example of a dataplane VNF consisting of two VMs for data plane workloads with one internal network" + name: dataplaneVNF4 + description: "Example of a dataplane VNF consisting of two VMs for data plane workloads with one internal network. VMs use image name instead of the path" # class: parent # Optional. Used to organize VNFs internal-connections: - name: datanet -- 2.25.1 From bb6a1eddea58a499539b13859b0cff1964fd554e Mon Sep 17 00:00:00 2001 From: garciadeblas Date: Fri, 30 Sep 2016 14:02:09 +0000 Subject: [PATCH 06/16] Fixed issue when using VM image name instead of path in deployments on openstack Signed-off-by: garciadeblas --- nfvo.py | 11 ++++++----- vimconn_openstack.py | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/nfvo.py b/nfvo.py index b0936e27..e8032064 100644 --- a/nfvo.py +++ b/nfvo.py @@ -284,10 +284,11 @@ def create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vi filter_dict={} filter_dict['name']=image_dict['universal_name'] filter_dict['checksum']=image_dict['checksum'] + #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict)) vim_images = vim.get_image_list(filter_dict) if len(vim_images) > 1: raise NfvoException("More than one candidate VIM image found for filter: " + str(filter_dict), HTTP_Conflict) - elif len(vim_nets) == 0: + elif len(vim_images) == 0: raise NfvoException("Image not found at VIM with filter: '%s'", str(filter_dict)) else: image_vim_id = vim_images[0].id @@ -1688,9 +1689,9 @@ def create_instance(mydb, tenant_id, instance_dict): #print "Checking that the scenario exists and getting the scenario dictionary" scenarioDict = mydb.get_scenario(scenario, tenant_id, default_datacenter_id) - #logger.debug("Dictionaries before merging") - #logger.debug("InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256))) - #logger.debug("ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256))) + #logger.debug(">>>>>>> Dictionaries before merging") + #logger.debug(">>>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256))) + #logger.debug(">>>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256))) scenarioDict['datacenter_tenant_id'] = default_datacenter_tenant_id scenarioDict['datacenter_id'] = default_datacenter_id @@ -1780,7 +1781,7 @@ def create_instance(mydb, tenant_id, instance_dict): if interface['vnf_interface'] == vnf_interface['external_name']: vnf_interface['ip_address']=interface['ip_address'] - #logger.debug("Merged dictionary") + #logger.debug(">>>>>>>> Merged dictionary") logger.debug("Creating instance scenario-dict MERGED:\n%s", yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)) diff --git a/vimconn_openstack.py b/vimconn_openstack.py index 0fc5bbda..e0a3aa31 100644 --- a/vimconn_openstack.py +++ b/vimconn_openstack.py @@ -600,7 +600,7 @@ class vimconnector(vimconn.vimconnector): #Then we filter by the rest of filter fields: checksum filtered_list = [] for image in image_list: - image_dict=glance.images.get(image.id) + image_dict=self.glance.images.get(image.id) if image_dict['checksum']==filter_dict.get('checksum'): filtered_list.append(image) return filtered_list -- 2.25.1 From 1f3a67138592443a8bd68ab936e071cb5bccda55 Mon Sep 17 00:00:00 2001 From: garciadeblas Date: Fri, 30 Sep 2016 17:46:48 +0200 Subject: [PATCH 07/16] Fixed VNF descriptor for tests Change-Id: If19d1afd81eb178b8988f3249a3bf14c9ad48bd2 Signed-off-by: garciadeblas --- vnfs/examples/dataplaneVNF4.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/vnfs/examples/dataplaneVNF4.yaml b/vnfs/examples/dataplaneVNF4.yaml index 5b2132dd..294c4a0d 100644 --- a/vnfs/examples/dataplaneVNF4.yaml +++ b/vnfs/examples/dataplaneVNF4.yaml @@ -69,7 +69,6 @@ vnf: VNFC: - name: VNF_2VMs-VM1 description: "Dataplane VM1 with 4 threads, 2 GB hugepages, 2 SR-IOV interface" - #Copy the image to a compute path and edit this path image name: dataplaneVNF_2VMs-image disk: 10 numas: @@ -91,7 +90,6 @@ vnf: - name: VNF_2VMs-VM2 description: "Dataplane VM1 with 2 threads, 2 GB hugepages, 2 SR-IOV interface" - #Copy the image to a compute path and edit this path image name: dataplaneVNF_2VMs-image disk: 10 numas: -- 2.25.1 From a4bb7ac7db950c4e89ac3a2ca62ea9828fe56bbc Mon Sep 17 00:00:00 2001 From: garciadeblas Date: Mon, 3 Oct 2016 20:13:29 +0200 Subject: [PATCH 08/16] basictest changed to remove nsd complex5. It requires a pre-provisioned image at openvim. It will be added when that image is created as part of openvim Change-Id: Icc01d9b0247ec41d99a7752d036b661e35b1bae1 Signed-off-by: garciadeblas --- test/basictest.sh | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/basictest.sh b/test/basictest.sh index 9c7b8885..5fff3c5d 100755 --- a/test/basictest.sh +++ b/test/basictest.sh @@ -135,13 +135,11 @@ then ${DIRmano}/openmano instance-scenario-delete -f complex2-instance || echo "fail" ${DIRmano}/openmano instance-scenario-delete -f complex3-instance || echo "fail" ${DIRmano}/openmano instance-scenario-delete -f complex4-instance || echo "fail" - ${DIRmano}/openmano instance-scenario-delete -f complex5-instance || echo "fail" ${DIRmano}/openmano scenario-delete -f simple || echo "fail" ${DIRmano}/openmano scenario-delete -f complex || echo "fail" ${DIRmano}/openmano scenario-delete -f complex2 || echo "fail" ${DIRmano}/openmano scenario-delete -f complex3 || echo "fail" ${DIRmano}/openmano scenario-delete -f complex4 || echo "fail" - ${DIRmano}/openmano scenario-delete -f complex5 || echo "fail" ${DIRmano}/openmano vnf-delete -f linux || echo "fail" ${DIRmano}/openmano vnf-delete -f linux_2VMs_v02 || echo "fail" ${DIRmano}/openmano vnf-delete -f dataplaneVNF_2VMs || echo "fail" @@ -199,7 +197,7 @@ then ! is_valid_uuid $vnf && echo FAIL && echo " $result" && $_exit 1 echo $vnf done - for NS in simple complex complex2 complex3 complex4 complex5 + for NS in simple complex complex2 complex3 complex4 do printf "%-50s" "Creating scenario '${NS}':" result=`$DIRmano/openmano scenario-create $DIRmano/scenarios/examples/${NS}.yaml` @@ -208,7 +206,7 @@ then echo $scenario done - for IS in simple complex complex2 complex3 complex5 + for IS in simple complex complex2 complex3 do printf "%-50s" "Creating instance-scenario '${IS}':" result=`$DIRmano/openmano instance-scenario-create --scenario ${IS} --name ${IS}-instance` -- 2.25.1 From fe3f3c9af04a7250408d9a91c41de3e11684166c Mon Sep 17 00:00:00 2001 From: bayramov Date: Tue, 4 Oct 2016 07:53:41 +0400 Subject: [PATCH 09/16] Added required dependency to install script. Fixed licensing issue in the file. Merged changes from master to vmware_connector. vm_info now has more status. Add acuireConsole method return link to VMRC console. get_vapp_details_rest() parse entier vapp and vm consturct and return as dictionary Signed-off-by: bayramov --- scripts/install-openmano.sh | 10 +- vimconn_vmware.py | 439 ++++++++++++++++++++++++------------ vmwarerecli.py | 20 +- 3 files changed, 319 insertions(+), 150 deletions(-) diff --git a/scripts/install-openmano.sh b/scripts/install-openmano.sh index d46b22b2..9aaf028e 100755 --- a/scripts/install-openmano.sh +++ b/scripts/install-openmano.sh @@ -241,8 +241,14 @@ echo ' ################################################################# ##### INSTALL PYTHON PACKAGES ##### #################################################################' -[ "$_DISTRO" == "Ubuntu" ] && install_packages "python-yaml python-bottle python-mysqldb python-jsonschema python-paramiko python-argcomplete python-requests python-logutils" -[ "$_DISTRO" == "CentOS" -o "$_DISTRO" == "Red" ] && install_packages "PyYAML MySQL-python python-jsonschema python-paramiko python-argcomplete python-requests python-logutils" +[ "$_DISTRO" == "Ubuntu" ] && install_packages "python-yaml python-bottle python-mysqldb python-jsonschema python-paramiko python-argcomplete python-requests python-logutils libxml2-dev libxslt-dev python-dev python-pip" +[ "$_DISTRO" == "CentOS" -o "$_DISTRO" == "Red" ] && install_packages "PyYAML MySQL-python python-jsonschema python-paramiko python-argcomplete python-requests python-logutils libxslt-devel libxml2-devel python-devel python-pip" + +#required for vmware connector TODO move that to separete opt in install script +sudo pip install --upgrade pip +sudo pip install pyvcloud +sudo pip install progressbar +sudo pip install prettytable #The only way to install python-bottle on Centos7 is with easy_install or pip [ "$_DISTRO" == "CentOS" -o "$_DISTRO" == "Red" ] && easy_install -U bottle diff --git a/vimconn_vmware.py b/vimconn_vmware.py index 069c0bc8..e59b93c9 100644 --- a/vimconn_vmware.py +++ b/vimconn_vmware.py @@ -25,6 +25,7 @@ vimconn_vmware implementation an Abstract class in order to interact with VMware vCloud Director. mbayramov@vmware.com ''' +from progressbar import Percentage, Bar, ETA, FileTransferSpeed, ProgressBar import vimconn import os @@ -64,6 +65,7 @@ VCAVERSION = '5.9' __author__ = "Mustafa Bayramov" __date__ = "$26-Aug-2016 11:09:29$" +__version__ = '0.1' # -1: "Could not be created", # 0: "Unresolved", @@ -151,6 +153,8 @@ class vimconnector(vimconn.vimconnector): self.admin_user = None self.logger = logging.getLogger('openmano.vim.vmware') + self.logger.setLevel(10) + if log_level: self.logger.setLevel( getattr(logging, log_level) ) @@ -281,7 +285,8 @@ class vimconnector(vimconn.vimconnector): raise vimconn.vimconnConnectionException("Can't connect to a vCloud director as: {}".format(self.user)) result = vca.login(token=vca.token, org=self.name, org_url=vca.vcloud_session.org_url) if result is True: - self.logger.info("Successfully logged to a vcloud direct org: {} as user: {}".format(self.name, self.user)) + self.logger.info( + "Successfully logged to a vcloud direct org: {} as user: {}".format(self.name, self.user)) except: raise vimconn.vimconnConnectionException("Can't connect to a vCloud director as: {}".format(self.user)) @@ -534,7 +539,7 @@ class vimconnector(vimconn.vimconnector): return network_list def get_network(self, net_id): - """Method bbtain network details of net_id VIM network + """Method obtains network details of net_id VIM network Return a dict with the fields at filter_dict (see get_network_list) plus some VIM specific>}, ...]""" vca = self.connect() @@ -578,10 +583,12 @@ class vimconnector(vimconn.vimconnector): vca = self.connect() if not vca: - raise vimconn.vimconnConnectionException("self.connect() for tenant {} is failed".format(self.tenant_name)) + raise vimconn.vimconnConnectionException("self.connect() for tenant {} is failed.".format(self.tenant_name)) - if self.delete_network_action(net_id): - return net_id + vcd_network = self.get_vcd_network(network_uuid=net_id) + if vcd_network is not None and vcd_network: + if self.delete_network_action(network_uuid=net_id): + return net_id else: raise vimconn.vimconnNotFoundException("Network {} not found".format(net_id)) @@ -603,12 +610,6 @@ class vimconnector(vimconn.vimconnector): """ - # for net in net_list: - # net['status'] - # net['error_msg'] - # net['vim_info'] - - # vim vimcon failed == ERROR vca = self.connect() if not vca: raise vimconn.vimconnConnectionException("self.connect() is failed") @@ -616,19 +617,19 @@ class vimconnector(vimconn.vimconnector): dict_entry = {} try: for net in net_list: - status = '' errormsg = '' vcd_network = self.get_vcd_network(network_uuid=net) - if vcd_network is not None: + if vcd_network is not None and vcd_network: if vcd_network['status'] == 1: status = 'ACTIVE' else: status = 'DOWN' else: status = 'DELETED' - errormsg = 'network not found' - dict_entry['net'] = {'status': status, 'error_msg': errormsg, - 'vm_info': yaml.safe_dump(vcd_network)} + errormsg = 'Network not found.' + + dict_entry[net] = {'status': status, 'error_msg': errormsg, + 'vm_info': yaml.safe_dump(vcd_network)} except: self.logger.debug("Error in refresh_nets_status") self.logger.debug(traceback.format_exc()) @@ -639,6 +640,8 @@ class vimconnector(vimconn.vimconnector): """Obtain flavor details from the VIM Returns the flavor dict details {'id':<>, 'name':<>, other vim specific } #TODO to concrete """ + if not flavorlist.has_key(flavor_id): + raise vimconn.vimconnNotFoundException("Flavor not found.") return flavorlist[flavor_id] def new_flavor(self, flavor_data): @@ -673,11 +676,11 @@ class vimconnector(vimconn.vimconnector): def delete_flavor(self, flavor_id): """Deletes a tenant flavor from VIM identify by its id - Returns the used id or raise an exception + Returns the used id or raise an exception """ + if not flavorlist.has_key(flavor_id): + raise vimconn.vimconnNotFoundException("Flavor not found.") - # if key not present it will raise KeyError - # TODO check do I need raise any specific exception flavorlist.pop(flavor_id, None) return flavor_id @@ -692,19 +695,29 @@ class vimconnector(vimconn.vimconnector): return self.get_image_id_from_path(image_dict['location']) def delete_image(self, image_id): - '''Deletes a tenant image from VIM''' - '''Returns the HTTP response code and a message indicating details of the success or fail''' + """ + + :param image_id: + :return: + """ + self.vca; + raise vimconn.vimconnNotImplemented("Should have implemented this") def catalog_exists(self, catalog_name, catalogs): + """ + + :param catalog_name: + :param catalogs: + :return: + """ for catalog in catalogs: if catalog.name == catalog_name: return True return False def create_vimcatalog(self, vca=None, catalog_name=None): - """ Create new catalog entry in vcloud director. - + """ Create new catalog entry in vCloud director. Args vca: vCloud director. @@ -724,8 +737,8 @@ class vimconnector(vimconn.vimconnector): return False return self.catalog_exists(catalog_name, catalogs) - def upload_ovf(self, vca, catalog_name, item_name, media_file_name, description='', display_progress=False, - chunk_bytes=128 * 1024): + def upload_ovf(self, vca=None, catalog_name=None, image_name=None, media_file_name=None, + description='', progress=False, chunk_bytes=128 * 1024): """ Uploads a OVF file to a vCloud catalog @@ -750,7 +763,7 @@ class vimconnector(vimconn.vimconnector): assert len(link) == 1 data = """ %s vApp Template - """ % (escape(item_name), escape(description)) + """ % (escape(image_name), escape(description)) headers = vca.vcloud_session.get_vcloud_headers() headers['Content-Type'] = 'application/vnd.vmware.vcloud.uploadVAppTemplateParams+xml' response = Http.post(link[0].get_href(), headers=headers, data=data, verify=vca.verify, logger=self.logger) @@ -765,12 +778,13 @@ class vimconnector(vimconn.vimconnector): if response.status_code == requests.codes.ok: media = mediaType.parseString(response.content, True) - link = \ - filter(lambda link: link.get_rel() == 'upload:default', - media.get_Files().get_File()[0].get_Link())[0] + link = filter(lambda link: link.get_rel() == 'upload:default', + media.get_Files().get_File()[0].get_Link())[0] headers = vca.vcloud_session.get_vcloud_headers() headers['Content-Type'] = 'Content-Type text/xml' - response = Http.put(link.get_href(), data=open(media_file_name, 'rb'), headers=headers, + response = Http.put(link.get_href(), + data=open(media_file_name, 'rb'), + headers=headers, verify=vca.verify, logger=self.logger) if response.status_code != requests.codes.ok: self.logger.debug( @@ -785,52 +799,68 @@ class vimconnector(vimconn.vimconnector): format(catalog_name, media_file_name)) # uploading VMDK file - # check status of OVF upload - response = Http.get(template, headers=vca.vcloud_session.get_vcloud_headers(), verify=vca.verify, + # check status of OVF upload and upload remaining files. + response = Http.get(template, + headers=vca.vcloud_session.get_vcloud_headers(), + verify=vca.verify, logger=self.logger) + if response.status_code == requests.codes.ok: media = mediaType.parseString(response.content, True) - links_list = filter(lambda link: link.get_rel() == 'upload:default', - media.get_Files().get_File()[0].get_Link()) - - for link in links_list: - # The OVF file and VMDK must be in a same directory - head, tail = os.path.split(media_file_name) - media_file_name = link.get_href() - if 'ovf' in media_file_name: - print "skiping {}".format(media_file_name) - continue - file_vmdk = head + '/' + os.path.basename(link.get_href()) - os.path.isfile(file_vmdk) - statinfo = os.stat(file_vmdk) - - # in case first element is pointer to OVF. - hrefvmdk = link.get_href().replace("descriptor.ovf", media_file_name) - print("Uploading file {}".format(hrefvmdk)) - - f = open(file_vmdk, 'rb') - bytes_transferred = 0 - while bytes_transferred < statinfo.st_size: - my_bytes = f.read(chunk_bytes) - if len(my_bytes) <= chunk_bytes: - headers = vca.vcloud_session.get_vcloud_headers() - headers['Content-Range'] = 'bytes %s-%s/%s' % ( - bytes_transferred, len(my_bytes) - 1, statinfo.st_size) - headers['Content-Length'] = str(len(my_bytes)) - response = Http.put(hrefvmdk, - headers=headers, - data=my_bytes, - verify=vca.verify, - logger=None) - if response.status_code == requests.codes.ok: - bytes_transferred += len(my_bytes) - self.logger.debug('transferred %s of %s bytes' % (str(bytes_transferred), - str(statinfo.st_size))) - else: - self.logger.debug('file upload failed with error: [%s] %s' % (response.status_code, - response.content)) - return False - f.close() + number_of_files = len(media.get_Files().get_File()) + for index in xrange(0, number_of_files): + links_list = filter(lambda link: link.get_rel() == 'upload:default', + media.get_Files().get_File()[index].get_Link()) + for link in links_list: + # we skip ovf since it already uploaded. + if 'ovf' in link.get_href(): + continue + # The OVF file and VMDK must be in a same directory + head, tail = os.path.split(media_file_name) + file_vmdk = head + '/' + link.get_href().split("/")[-1] + if not os.path.isfile(file_vmdk): + return False + statinfo = os.stat(file_vmdk) + if statinfo.st_size == 0: + return False + hrefvmdk = link.get_href() + + if progress: + print("Uploading file: {}".format(file_vmdk)) + if progress: + widgets = ['Uploading file: ', Percentage(), ' ', Bar(), ' ', ETA(), ' ', + FileTransferSpeed()] + progress_bar = ProgressBar(widgets=widgets, maxval=statinfo.st_size).start() + + bytes_transferred = 0 + f = open(file_vmdk, 'rb') + while bytes_transferred < statinfo.st_size: + my_bytes = f.read(chunk_bytes) + if len(my_bytes) <= chunk_bytes: + headers = vca.vcloud_session.get_vcloud_headers() + headers['Content-Range'] = 'bytes %s-%s/%s' % ( + bytes_transferred, len(my_bytes) - 1, statinfo.st_size) + headers['Content-Length'] = str(len(my_bytes)) + response = Http.put(hrefvmdk, + headers=headers, + data=my_bytes, + verify=vca.verify, + logger=None) + + if response.status_code == requests.codes.ok: + bytes_transferred += len(my_bytes) + if progress: + progress_bar.update(bytes_transferred) + else: + self.logger.debug( + 'file upload failed with error: [%s] %s' % (response.status_code, + response.content)) + + f.close() + return False + f.close() + if progress: + progress_bar.finish() return True else: self.logger.debug("Failed retrieve vApp template for catalog name {} for OVF {}". @@ -840,10 +870,12 @@ class vimconnector(vimconn.vimconnector): self.logger.debug("Failed retrieve catalog name {} for OVF file {}".format(catalog_name, media_file_name)) return False - def upload_vimimage(self, vca, catalog_name, media_name, medial_file_name): + def upload_vimimage(self, vca=None, catalog_name=None, media_name=None, medial_file_name=None, progress=False): """Upload media file""" - # TODO add named parameters for readbility - return self.upload_ovf(vca, catalog_name, media_name.split(".")[0], medial_file_name, medial_file_name, True) + # TODO add named parameters for readability + + return self.upload_ovf(vca=vca, catalog_name=catalog_name, image_name=media_name.split(".")[0], + media_file_name=medial_file_name, description='medial_file_name', progress=progress) def validate_uuid4(self, uuid_string=None): """ Method validate correct format of UUID. @@ -891,7 +923,7 @@ class vimconnector(vimconn.vimconnector): return catalog.name return None - def get_image_id_from_path(self, path=None): + def get_image_id_from_path(self, path=None, progress=False): """ Method upload OVF image to vCloud director. Each OVF image represented as single catalog entry in vcloud director. @@ -902,33 +934,46 @@ class vimconnector(vimconn.vimconnector): If method can't create catalog entry or upload a file it will throw exception. + Method accept boolean flag progress that will output progress bar. It useful method + for standalone upload use case. In case to test large file upload. + Args - path: valid path to OVF file. + path: - valid path to OVF file. + progress - boolean progress bar show progress bar. Return: if image uploaded correct method will provide image catalog UUID. """ vca = self.connect() if not vca: - raise vimconn.vimconnConnectionException("self.connect() is failed") + raise vimconn.vimconnConnectionException("self.connect() is failed.") + + if path is None: + raise vimconn.vimconnException("Image path can't be None.") + + if not os.path.isfile(path): + raise vimconn.vimconnException("Can't read file. File not found.") - self.logger.debug("get_image_id_from_path path {}".format(path)) + if not os.access(path, os.R_OK): + raise vimconn.vimconnException("Can't read file. Check file permission to read.") + + self.logger.debug("get_image_id_from_path() client requesting {} ".format(path)) dirpath, filename = os.path.split(path) flname, file_extension = os.path.splitext(path) if file_extension != '.ovf': - self.logger.debug("Wrong file extension {}".format(file_extension)) + self.logger.debug("Wrong file extension {} connector support only OVF container.".format(file_extension)) raise vimconn.vimconnException("Wrong container. vCloud director supports only OVF.") catalog_name = os.path.splitext(filename)[0] self.logger.debug("File name {} Catalog Name {} file path {}".format(filename, catalog_name, path)) - self.logger.debug("Catalog name {}".format(catalog_name)) catalogs = vca.get_catalogs() if len(catalogs) == 0: - self.logger.info("Creating new catalog entry {} in vcloud director".format(catalog_name)) + self.logger.info("Creating a new catalog entry {} in vcloud director".format(catalog_name)) result = self.create_vimcatalog(vca, catalog_name) if not result: raise vimconn.vimconnException("Failed create new catalog {} ".format(catalog_name)) - result = self.upload_vimimage(vca, catalog_name, filename, path) + result = self.upload_vimimage(vca=vca, catalog_name=catalog_name, + media_name=filename, medial_file_name=path, progress=progress) if not result: raise vimconn.vimconnException("Failed create vApp template for catalog {} ".format(catalog_name)) return self.get_catalogid(catalog_name, vca.get_catalogs()) @@ -943,12 +988,14 @@ class vimconnector(vimconn.vimconnector): catalogs))) return self.get_catalogid(catalog_name, vca.get_catalogs()) - # if we didn't find existing catalog we create a new one. + # if we didn't find existing catalog we create a new one and upload image. self.logger.debug("Creating new catalog entry".format(catalog_name)) result = self.create_vimcatalog(vca, catalog_name) if not result: raise vimconn.vimconnException("Failed create new catalog {} ".format(catalog_name)) - result = self.upload_vimimage(vca, catalog_name, filename, path) + + result = self.upload_vimimage(vca=vca, catalog_name=catalog_name, + media_name=filename, medial_file_name=path, progress=progress) if not result: raise vimconn.vimconnException("Failed create vApp template for catalog {} ".format(catalog_name)) @@ -978,12 +1025,8 @@ class vimconnector(vimconn.vimconnector): return False return None - def check_vapp(self, vdc, vapp_id): - """ Take VDC object and vApp ID and return True if given ID in vCloud director - otherwise return False - """ - - """ Method Method returns vApp name from vCD and lookup done by vapp_id. + def check_vapp(self, vdc=None, vapp_uuid=None): + """ Method Method returns True or False if vapp deployed in vCloud director Args: vca: Connector to VCA @@ -991,7 +1034,7 @@ class vimconnector(vimconn.vimconnector): vappid: vappid is application identifier Returns: - The return vApp name otherwise None + The return True if vApp deployed """ try: refs = filter(lambda ref: @@ -1000,20 +1043,20 @@ class vimconnector(vimconn.vimconnector): for ref in refs: vappid = ref.href.split("vapp")[1][1:] # find vapp with respected vapp uuid - if vappid == vapp_id: + if vappid == vapp_uuid: return True except Exception as e: self.logger.exception(e) return False return False - def get_namebyvappid(self, vca, vdc, vapp_id): + def get_namebyvappid(self, vca=None, vdc=None, vapp_uuid=None): """Method returns vApp name from vCD and lookup done by vapp_id. Args: vca: Connector to VCA vdc: The VDC object. - vapp_id: vappid is application identifier + vapp_uuid: vappid is application identifier Returns: The return vApp name otherwise None @@ -1025,7 +1068,7 @@ class vimconnector(vimconn.vimconnector): for ref in refs: # we care only about UUID the rest doesn't matter vappid = ref.href.split("vapp")[1][1:] - if vappid == vapp_id: + if vappid == vapp_uuid: response = Http.get(ref.href, headers=vca.vcloud_session.get_vcloud_headers(), verify=vca.verify, logger=self.logger) tree = XmlElementTree.fromstring(response.content) @@ -1035,7 +1078,8 @@ class vimconnector(vimconn.vimconnector): return None return None - def new_vminstance(self, name=None, description="", start=False, image_id=None, flavor_id=None, net_list={}, cloud_config=None): + def new_vminstance(self, name=None, description="", start=False, image_id=None, flavor_id=None, net_list={}, + cloud_config=None): """Adds a VM instance to VIM Params: start: indicates if VM must start or boot in pause mode. Ignored @@ -1073,11 +1117,11 @@ class vimconnector(vimconn.vimconnector): # we check for presence of VDC, Catalog entry and Flavor. vdc = vca.get_vdc(self.tenant_name) if vdc is None: - raise vimconn.vimconnUnexpectedResponse( + raise vimconn.vimconnNotFoundException( "new_vminstance(): Failed create vApp {}: (Failed retrieve VDC information)".format(name)) catalogs = vca.get_catalogs() if catalogs is None: - raise vimconn.vimconnUnexpectedResponse( + raise vimconn.vimconnNotFoundException( "new_vminstance(): Failed create vApp {}: Failed create vApp {}: " "(Failed retrieve catalog information)".format(name)) @@ -1086,19 +1130,16 @@ class vimconnector(vimconn.vimconnector): if flavor_id is not None: flavor = flavorlist[flavor_id] if flavor is None: - raise vimconn.vimconnUnexpectedResponse( + raise vimconn.vimconnNotFoundException( "new_vminstance(): Failed create vApp {}: (Failed retrieve flavor information)".format(name)) else: try: - vm_cpus = flavor['vcpus'] - vm_memory= flavor['ram'] + vm_cpus = flavor['vcpus'] + vm_memory = flavor['ram'] except KeyError: raise vimconn.vimconnException("Corrupted flavor. {}".format(flavor_id)) # image upload creates template name as catalog name space Template. - - print image_id - templateName = self.get_catalogbyid(catalog_uuid=image_id, catalogs=catalogs) + ' Template' power_on = 'false' if start: @@ -1124,11 +1165,11 @@ class vimconnector(vimconn.vimconnector): # create vApp. Set vcpu and ram based on flavor id. vapptask = vca.create_vapp(self.tenant_name, name, templateName, self.get_catalogbyid(image_id, catalogs), - network_name=primary_net_name, # can be None if net_list None + network_name=primary_net_name, # can be None if net_list None network_mode='bridged', vm_name=name, - vm_cpus=vm_cpus, # can be None if flavor is None - vm_memory=vm_memory) # can be None if flavor is None + vm_cpus=vm_cpus, # can be None if flavor is None + vm_memory=vm_memory) # can be None if flavor is None if vapptask is None or vapptask is False: raise vimconn.vimconnUnexpectedResponse("new_vminstance(): failed deploy vApp {}".format(name)) @@ -1201,7 +1242,7 @@ class vimconnector(vimconn.vimconnector): # error_msg: # interfaces: … # - def get_vminstance(self, vim_vm_uuid): + def get_vminstance(self, vim_vm_uuid=None): '''Returns the VM instance information from VIM''' self.logger.debug("Client requesting vm instance {} ".format(vim_vm_uuid)) @@ -1211,43 +1252,35 @@ class vimconnector(vimconn.vimconnector): vdc = vca.get_vdc(self.tenant_name) if vdc is None: - return -1, "Failed to get a reference of VDC for a tenant {}".format(self.tenant_name) + raise vimconn.vimconnConnectionException( + "Failed to get a reference of VDC for a tenant {}".format(self.tenant_name)) - vm_name = self.get_namebyvappid(vca, vdc, vim_vm_uuid) - if vm_name is None: + vm_info_dict = self.get_vapp_details_rest(vapp_uuid=vim_vm_uuid) + if not vm_info_dict: self.logger.debug("get_vminstance(): Failed to get vApp name by UUID {}".format(vim_vm_uuid)) - return None, "Failed to get vApp name by UUID {}".format(vim_vm_uuid) + raise vimconn.vimconnNotFoundException("Failed to get vApp name by UUID {}".format(vim_vm_uuid)) - the_vapp = vca.get_vapp(vdc, vm_name) - vm_info = the_vapp.get_vms_details() - - vm_dict = {'description': vm_info[0]['name'], 'status': vcdStatusCode2manoFormat[the_vapp.me.get_status()], - 'error_msg': vcdStatusCode2manoFormat[the_vapp.me.get_status()], - 'vim_info': yaml.safe_dump(the_vapp.get_vms_details()), 'interfaces': []} - - # get networks - vm_app_networks = the_vapp.get_vms_network_info() - - interfaces = [] + status_key = vm_info_dict['status'] + error = '' try: - org_network_dict = self.get_org(self.org_uuid)['networks'] - for vapp_network in vm_app_networks: - for vm_network in vapp_network: - if vm_network['name'] == vm_name: - interface = {} - # interface['vim_info'] = yaml.safe_dump(vm_network) - interface["mac_address"] = vm_network['mac'] - for net_uuid in org_network_dict: - if org_network_dict[net_uuid] == vm_network['network_name']: - interface["vim_net_id"] = net_uuid - interface["vim_interface_id"] = vm_network['network_name'] - interface['ip_address'] = vm_network['ip'] - interfaces.append(interface) + vm_dict = {'created': vm_info_dict['created'], + 'description': vm_info_dict['name'], + 'status': vcdStatusCode2manoFormat[int(status_key)], + 'hostId': vm_info_dict['vmuuid'], + 'error_msg': error, + 'vim_info': yaml.safe_dump(vm_info_dict), 'interfaces': []} + + if vm_info_dict.has_key('interfaces'): + vm_dict['interfaces'] = vm_info_dict['interfaces'] + else: + vm_dict['interfaces'] = [] except KeyError: - self.logger.debug("Error in respond {}".format(KeyError.message)) - self.logger.debug(traceback.format_exc()) - - vm_dict['interfaces'] = interfaces + vm_dict = {'created': '', + 'description': '', + 'status': vcdStatusCode2manoFormat[int(-1)], + 'hostId': vm_info_dict['vmuuid'], + 'error_msg': "Inconsistency state", + 'vim_info': yaml.safe_dump(vm_info_dict), 'interfaces': []} return vm_dict @@ -2268,3 +2301,125 @@ class vimconnector(vimconn.vimconnector): if response.status_code == 201: return response.content return None + + def get_vapp_details_rest(self, vapp_uuid=None): + """ + Method retrieve vapp detail from vCloud director + + Args: + vapp_uuid - is vapp identifier. + + Returns: + The return network uuid or return None + """ + + parsed_respond = {} + + vca = self.connect() + if not vca: + raise vimconn.vimconnConnectionException("self.connect() is failed") + if vapp_uuid is None: + return None + + url_list = [vca.host, '/api/vApp/vapp-', vapp_uuid] + get_vapp_restcall = ''.join(url_list) + if not (not vca.vcloud_session or not vca.vcloud_session.organization): + response = Http.get(url=get_vapp_restcall, + headers=vca.vcloud_session.get_vcloud_headers(), + verify=vca.verify, + logger=vca.logger) + + if response.status_code != requests.codes.ok: + self.logger.debug("REST API call {} failed. Return status code {}".format(get_vapp_restcall, + response.status_code)) + return parsed_respond + + try: + xmlroot_respond = XmlElementTree.fromstring(response.content) + parsed_respond['ovfDescriptorUploaded'] = xmlroot_respond.attrib['ovfDescriptorUploaded'] + + namespaces_ovf = {'ovf': 'http://schemas.dmtf.org/ovf/envelope/1'} + namespace_vmm = {'vmw': 'http://www.vmware.com/schema/ovf'} + namespace_vm = {'vm': 'http://www.vmware.com/vcloud/v1.5'} + + created_section = xmlroot_respond.find('vm:DateCreated', namespace_vm) + if created_section is not None: + parsed_respond['created'] = created_section.text + + network_section = xmlroot_respond.find('vm:NetworkConfigSection/vm:NetworkConfig', namespace_vm) + if network_section is not None and network_section.attrib.has_key('networkName'): + parsed_respond['networkname'] = network_section.attrib['networkName'] + + ipscopes_section = \ + xmlroot_respond.find('vm:NetworkConfigSection/vm:NetworkConfig/vm:Configuration/vm:IpScopes', + namespace_vm) + if ipscopes_section is not None: + for ipscope in ipscopes_section: + for scope in ipscope: + tag_key = scope.tag.split("}")[1] + if tag_key == 'IpRanges': + ip_ranges = scope.getchildren() + for ipblock in ip_ranges: + for block in ipblock: + parsed_respond[block.tag.split("}")[1]] = block.text + else: + parsed_respond[tag_key] = scope.text + + # parse children section for other attrib + children_section = xmlroot_respond.find('vm:Children/', namespace_vm) + if children_section is not None: + parsed_respond['name'] = children_section.attrib['name'] + parsed_respond['nestedHypervisorEnabled'] = children_section.attrib['nestedHypervisorEnabled'] + parsed_respond['deployed'] = children_section.attrib['deployed'] + parsed_respond['status'] = children_section.attrib['status'] + parsed_respond['vmuuid'] = children_section.attrib['id'].split(":")[-1] + network_adapter = children_section.find('vm:NetworkConnectionSection', namespace_vm) + nic_list = [] + for adapters in network_adapter: + adapter_key = adapters.tag.split("}")[1] + if adapter_key == 'PrimaryNetworkConnectionIndex': + parsed_respond['primarynetwork'] = adapters.text + if adapter_key == 'NetworkConnection': + vnic = {} + if adapters.attrib.has_key('network'): + vnic['network'] = adapters.attrib['network'] + for adapter in adapters: + setting_key = adapter.tag.split("}")[1] + vnic[setting_key] = adapter.text + nic_list.append(vnic) + + for link in children_section: + if link.tag.split("}")[1] == 'Link' and link.attrib.has_key('rel'): + if link.attrib['rel'] == 'screen:acquireTicket': + parsed_respond['acquireTicket'] = link.attrib + if link.attrib['rel'] == 'screen:acquireMksTicket': + parsed_respond['acquireMksTicket'] = link.attrib + + parsed_respond['interfaces'] = nic_list + except: + pass + + return parsed_respond + + def acuireConsole(self, vm_uuid=None): + + vca = self.connect() + if not vca: + raise vimconn.vimconnConnectionException("self.connect() is failed") + if vm_uuid is None: + return None + + if not (not vca.vcloud_session or not vca.vcloud_session.organization): + vm_dict = self.get_vapp_details_rest(self, vm_uuid=vm_uuid) + console_dict = vm_dict['acquireTicket'] + console_rest_call = console_dict['href'] + + response = Http.post(url=console_rest_call, + headers=vca.vcloud_session.get_vcloud_headers(), + verify=vca.verify, + logger=vca.logger) + + if response.status_code != requests.codes.ok: + return None + + return response.content diff --git a/vmwarerecli.py b/vmwarerecli.py index c332cdb6..c85b1d57 100755 --- a/vmwarerecli.py +++ b/vmwarerecli.py @@ -62,6 +62,7 @@ import uuid from xml.etree import ElementTree as ET +import sys from pyvcloud import Http import logging @@ -420,7 +421,6 @@ def view_actions(vim=None, action=None, namespace=None): # view vapp action if action == 'vapp' or namespace.action == 'vapp': - print namespace.vapp_name if namespace.vapp_name is not None and namespace.uuid: logger.debug("Requesting vapp {} for vdc {}".format(namespace.vapp_name, namespace.vcdvdc)) vapp_dict = {} @@ -432,8 +432,12 @@ def view_actions(vim=None, action=None, namespace=None): print("Can't find vapp by given name {}".format(namespace.vapp_name)) return - vapp_dict = vim.get_vapp(vdc_name=namespace.vcdvdc, vapp_name=vapp_uuid, isuuid=True) - if vapp_dict is not None: + print " namespace {}".format(namespace) + if vapp_dict is not None and namespace.osm: + vm_info_dict = vim.get_vminstance(vim_vm_uuid=vapp_uuid) + print vm_info_dict + if vapp_dict is not None and namespace.osm != True: + vapp_dict = vim.get_vapp(vdc_name=namespace.vcdvdc, vapp_name=vapp_uuid, isuuid=True) print_vapp(vapp_dict=vapp_dict) # view network @@ -512,13 +516,13 @@ def upload_image(vim=None, image_file=None): The return true if image uploaded correctly """ try: - catalog_uuid = vim.get_image_id_from_path(path=image_file) + catalog_uuid = vim.get_image_id_from_path(path=image_file, progress=True) if catalog_uuid is not None and validate_uuid4(catalog_uuid): print("Image uploaded and uuid {}".format(catalog_uuid)) return True - except: + except vimconn.vimconnException as upload_exception: print("Failed uploaded {} image".format(image_file)) - + print("Error Reason: {}".format(upload_exception.message)) return False @@ -558,6 +562,8 @@ def boot_image(vim=None, image_name=None, vm_name=None): except: print("Failed uploaded {} image".format(image_name)) + return False + def image_action(vim=None, action=None, namespace=None): """ Function present set of action to manipulate with image. @@ -638,6 +644,7 @@ def vmwarecli(command=None, action=None, namespace=None): log_level="DEBUG", config={'admin_username': namespace.vcdamdin, 'admin_password': namespace.vcdadminpassword}) vim.vca = vim.connect() + except vimconn.vimconnConnectionException: print("Failed connect to vcloud director. Please check credential and hostname.") return @@ -746,6 +753,7 @@ if __name__ == '__main__': view_vapp_parser.add_argument('vapp_name', action='store', help='- view vapp for specific vapp name in vcloud director') view_vapp_parser.add_argument('-u', '--uuid', default=False, action='store_true', help='view vapp based on uuid') + view_vapp_parser.add_argument('-o', '--osm', default=False, action='store_true', help='provide view in OSM format') # view network view_network = view_sub_subparsers.add_parser('network') -- 2.25.1 From 5761ad1cf1c36df23ce8b0fd3312fba4f324ca13 Mon Sep 17 00:00:00 2001 From: bayramov Date: Tue, 4 Oct 2016 09:00:30 +0400 Subject: [PATCH 10/16] Added capability to duplicate name for network and vm Signed-off-by: bayramov --- vimconn_vmware.py | 124 ++++++++++++++++++++++++---------------------- vmwarerecli.py | 12 ++++- 2 files changed, 74 insertions(+), 62 deletions(-) diff --git a/vimconn_vmware.py b/vimconn_vmware.py index e59b93c9..7836eff6 100644 --- a/vimconn_vmware.py +++ b/vimconn_vmware.py @@ -21,10 +21,10 @@ # contact with: nfvlabs@tid.es ## -''' +""" vimconn_vmware implementation an Abstract class in order to interact with VMware vCloud Director. mbayramov@vmware.com -''' +""" from progressbar import Percentage, Bar, ETA, FileTransferSpeed, ProgressBar import vimconn @@ -156,7 +156,7 @@ class vimconnector(vimconn.vimconnector): self.logger.setLevel(10) if log_level: - self.logger.setLevel( getattr(logging, log_level) ) + self.logger.setLevel(getattr(logging, log_level)) try: self.admin_user = config['admin_username'] @@ -168,7 +168,7 @@ class vimconnector(vimconn.vimconnector): self.vca = None if not url: - raise TypeError, 'url param can not be NoneType' + raise vimconn.vimconnException('url param can not be NoneType') if not self.url_admin: # try to use normal url self.url_admin = self.url @@ -322,7 +322,7 @@ class vimconnector(vimconn.vimconnector): # we have two case if we want to initialize VDC ID or VDC name at run time # tenant_name provided but no tenant id - if self.tenant_id is None and self.tenant_name is not None and org_details_dict.has_key('vdcs'): + if self.tenant_id is None and self.tenant_name is not None and 'vdcs' in org_details_dict: vdcs_dict = org_details_dict['vdcs'] for vdc in vdcs_dict: if vdcs_dict[vdc] == self.tenant_name: @@ -333,7 +333,7 @@ class vimconnector(vimconn.vimconnector): else: raise vimconn.vimconnException("Tenant name indicated but not present in vcloud director.") # case two we have tenant_id but we don't have tenant name so we find and set it. - if self.tenant_id is not None and self.tenant_name is None and org_details_dict.has_key('vdcs'): + if self.tenant_id is not None and self.tenant_name is None and 'vdcs' in org_details_dict: vdcs_dict = org_details_dict['vdcs'] for vdc in vdcs_dict: if vdc == self.tenant_id: @@ -640,7 +640,7 @@ class vimconnector(vimconn.vimconnector): """Obtain flavor details from the VIM Returns the flavor dict details {'id':<>, 'name':<>, other vim specific } #TODO to concrete """ - if not flavorlist.has_key(flavor_id): + if flavor_id not in flavorlist: raise vimconn.vimconnNotFoundException("Flavor not found.") return flavorlist[flavor_id] @@ -678,19 +678,19 @@ class vimconnector(vimconn.vimconnector): Returns the used id or raise an exception """ - if not flavorlist.has_key(flavor_id): + if flavor_id not in flavorlist: raise vimconn.vimconnNotFoundException("Flavor not found.") flavorlist.pop(flavor_id, None) return flavor_id def new_image(self, image_dict): - ''' + """ Adds a tenant image to VIM Returns: 200, image-id if the image is created <0, message if there is an error - ''' + """ return self.get_image_id_from_path(image_dict['location']) @@ -700,7 +700,6 @@ class vimconnector(vimconn.vimconnector): :param image_id: :return: """ - self.vca; raise vimconn.vimconnNotImplemented("Should have implemented this") @@ -737,19 +736,23 @@ class vimconnector(vimconn.vimconnector): return False return self.catalog_exists(catalog_name, catalogs) + # noinspection PyIncorrectDocstring def upload_ovf(self, vca=None, catalog_name=None, image_name=None, media_file_name=None, description='', progress=False, chunk_bytes=128 * 1024): """ Uploads a OVF file to a vCloud catalog + :param chunk_bytes: + :param progress: + :param description: + :param image_name: + :param vca: :param catalog_name: (str): The name of the catalog to upload the media. - :param item_name: (str): The name of the media file in the catalog. :param media_file_name: (str): The name of the local media file to upload. :return: (bool) True if the media file was successfully uploaded, false otherwise. """ os.path.isfile(media_file_name) statinfo = os.stat(media_file_name) - statinfo.st_size # find a catalog entry where we upload OVF. # create vApp Template and check the status if vCD able to read OVF it will respond with appropirate @@ -1005,7 +1008,6 @@ class vimconnector(vimconn.vimconnector): """ Method takes vdc object and vApp name and returns vapp uuid or None Args: - vca: Connector to VCA vdc: The VDC object. vapp_name: is application vappp name identifier @@ -1035,6 +1037,8 @@ class vimconnector(vimconn.vimconnector): Returns: The return True if vApp deployed + :param vdc: + :param vapp_uuid: """ try: refs = filter(lambda ref: @@ -1109,10 +1113,14 @@ class vimconnector(vimconn.vimconnector): if not vca: raise vimconn.vimconnConnectionException("self.connect() is failed.") + #new vm name = vmname + tenant_id + uuid + new_vm_name = [name, '-', str(uuid.uuid4())] + full_name = ''.join(new_vm_name) + # if vm already deployed we return existing uuid - vapp_uuid = self.get_vappid(vca.get_vdc(self.tenant_name), name) - if vapp_uuid is not None: - return vapp_uuid + # vapp_uuid = self.get_vappid(vca.get_vdc(self.tenant_name), name) + # if vapp_uuid is not None: + # return vapp_uuid # we check for presence of VDC, Catalog entry and Flavor. vdc = vca.get_vdc(self.tenant_name) @@ -1122,8 +1130,7 @@ class vimconnector(vimconn.vimconnector): catalogs = vca.get_catalogs() if catalogs is None: raise vimconn.vimconnNotFoundException( - "new_vminstance(): Failed create vApp {}: Failed create vApp {}: " - "(Failed retrieve catalog information)".format(name)) + "new_vminstance(): Failed create vApp {}: ""(Failed retrieve catalog information)".format(name)) vm_cpus = None vm_memory = None @@ -1146,13 +1153,11 @@ class vimconnector(vimconn.vimconnector): power_on = 'true' # client must provide at least one entry in net_list if not we report error - primary_net = None primary_net_name = None if net_list is not None and len(net_list) > 0: primary_net = net_list[0] if primary_net is None: raise vimconn.vimconnUnexpectedResponse("new_vminstance(): Failed network list is empty.".format(name)) - else: try: primary_net_id = primary_net['net_id'] @@ -1163,24 +1168,24 @@ class vimconnector(vimconn.vimconnector): # use: 'data', 'bridge', 'mgmt' # create vApp. Set vcpu and ram based on flavor id. - vapptask = vca.create_vapp(self.tenant_name, name, templateName, + vapptask = vca.create_vapp(self.tenant_name, full_name, templateName, self.get_catalogbyid(image_id, catalogs), network_name=primary_net_name, # can be None if net_list None network_mode='bridged', - vm_name=name, + vm_name=full_name, vm_cpus=vm_cpus, # can be None if flavor is None vm_memory=vm_memory) # can be None if flavor is None if vapptask is None or vapptask is False: - raise vimconn.vimconnUnexpectedResponse("new_vminstance(): failed deploy vApp {}".format(name)) + raise vimconn.vimconnUnexpectedResponse("new_vminstance(): failed deploy vApp {}".format(full_name)) if type(vapptask) is VappTask: vca.block_until_completed(vapptask) # we should have now vapp in undeployed state. - vapp = vca.get_vapp(vca.get_vdc(self.tenant_name), name) + vapp = vca.get_vapp(vca.get_vdc(self.tenant_name), full_name) if vapp is None: raise vimconn.vimconnUnexpectedResponse( - "new_vminstance(): Failed failed retrieve vApp {} after we deployed".format(name)) + "new_vminstance(): Failed failed retrieve vApp {} after we deployed".format(full_name)) # add first NIC try: @@ -1221,7 +1226,7 @@ class vimconnector(vimconn.vimconnector): vca.block_until_completed(deploytask) # check if vApp deployed and if that the case return vApp UUID otherwise -1 - vapp_uuid = self.get_vappid(vca.get_vdc(self.tenant_name), name) + vapp_uuid = self.get_vappid(vca.get_vdc(self.tenant_name), full_name) if vapp_uuid is not None: return vapp_uuid else: @@ -1243,7 +1248,7 @@ class vimconnector(vimconn.vimconnector): # interfaces: … # def get_vminstance(self, vim_vm_uuid=None): - '''Returns the VM instance information from VIM''' + """Returns the VM instance information from VIM""" self.logger.debug("Client requesting vm instance {} ".format(vim_vm_uuid)) vca = self.connect() @@ -1270,7 +1275,7 @@ class vimconnector(vimconn.vimconnector): 'error_msg': error, 'vim_info': yaml.safe_dump(vm_info_dict), 'interfaces': []} - if vm_info_dict.has_key('interfaces'): + if 'interfaces' in vm_info_dict: vm_dict['interfaces'] = vm_info_dict['interfaces'] else: vm_dict['interfaces'] = [] @@ -1402,10 +1407,9 @@ class vimconnector(vimconn.vimconnector): vm_info = the_vapp.get_vms_details() vm_status = vm_info[0]['status'] - vm_dict = {'status': None, 'error_msg': None, 'vim_info': None, 'interfaces': []} - vm_dict['status'] = vcdStatusCode2manoFormat[the_vapp.me.get_status()] - vm_dict['error_msg'] = vcdStatusCode2manoFormat[the_vapp.me.get_status()] - vm_dict['vim_info'] = yaml.safe_dump(the_vapp.get_vms_details()) + vm_dict = {'status': vcdStatusCode2manoFormat[the_vapp.me.get_status()], + 'error_msg': vcdStatusCode2manoFormat[the_vapp.me.get_status()], + 'vim_info': yaml.safe_dump(the_vapp.get_vms_details()), 'interfaces': []} # get networks try: @@ -1413,12 +1417,11 @@ class vimconnector(vimconn.vimconnector): for vapp_network in vm_app_networks: for vm_network in vapp_network: if vm_network['name'] == vmname: - interface = {} + interface = {"mac_address": vm_network['mac'], + "vim_net_id": self.get_network_name_by_id(vm_network['network_name']), + "vim_interface_id": vm_network['network_name'], + 'ip_address': vm_network['ip']} # interface['vim_info'] = yaml.safe_dump(vm_network) - interface["mac_address"] = vm_network['mac'] - interface["vim_net_id"] = self.get_network_name_by_id(vm_network['network_name']) - interface["vim_interface_id"] = vm_network['network_name'] - interface['ip_address'] = vm_network['ip'] vm_dict["interfaces"].append(interface) # add a vm to vm dict vms_dict.setdefault(vmuuid, vm_dict) @@ -1502,47 +1505,47 @@ class vimconnector(vimconn.vimconnector): # NOT USED METHODS in current version def host_vim2gui(self, host, server_dict): - '''Transform host dictionary from VIM format to GUI format, + """Transform host dictionary from VIM format to GUI format, and append to the server_dict - ''' + """ raise vimconn.vimconnNotImplemented("Should have implemented this") def get_hosts_info(self): - '''Get the information of deployed hosts - Returns the hosts content''' + """Get the information of deployed hosts + Returns the hosts content""" raise vimconn.vimconnNotImplemented("Should have implemented this") def get_hosts(self, vim_tenant): - '''Get the hosts and deployed instances - Returns the hosts content''' + """Get the hosts and deployed instances + Returns the hosts content""" raise vimconn.vimconnNotImplemented("Should have implemented this") def get_processor_rankings(self): - '''Get the processor rankings in the VIM database''' + """Get the processor rankings in the VIM database""" raise vimconn.vimconnNotImplemented("Should have implemented this") def new_host(self, host_data): - '''Adds a new host to VIM''' + """Adds a new host to VIM""" '''Returns status code of the VIM response''' raise vimconn.vimconnNotImplemented("Should have implemented this") def new_external_port(self, port_data): - '''Adds a external port to VIM''' + """Adds a external port to VIM""" '''Returns the port identifier''' raise vimconn.vimconnNotImplemented("Should have implemented this") def new_external_network(self, net_name, net_type): - '''Adds a external network to VIM (shared)''' + """Adds a external network to VIM (shared)""" '''Returns the network identifier''' raise vimconn.vimconnNotImplemented("Should have implemented this") def connect_port_network(self, port_id, network_id, admin=False): - '''Connects a external port to a network''' + """Connects a external port to a network""" '''Returns status code of the VIM response''' raise vimconn.vimconnNotImplemented("Should have implemented this") def new_vminstancefromJSON(self, vm_data): - '''Adds a VM instance to VIM''' + """Adds a VM instance to VIM""" '''Returns the instance identifier''' raise vimconn.vimconnNotImplemented("Should have implemented this") @@ -1988,7 +1991,8 @@ class vimconnector(vimconn.vimconnector): The return network uuid or return None """ - content = self.create_network_rest(network_name=network_name, + new_network_name = [network_name, '-', str(uuid.uuid4())] + content = self.create_network_rest(network_name=''.join(new_network_name), parent_network_uuid=parent_network_uuid, isshared=isshared) if content is None: @@ -2020,7 +2024,7 @@ class vimconnector(vimconn.vimconnector): vca = self.connect_as_admin() if not vca: - raise vimconn.vimconnConnectionException("self.connect() is failed") + raise vimconn.vimconnConnectionException("self.connect() is failed.") if network_name is None: return None @@ -2347,7 +2351,7 @@ class vimconnector(vimconn.vimconnector): parsed_respond['created'] = created_section.text network_section = xmlroot_respond.find('vm:NetworkConfigSection/vm:NetworkConfig', namespace_vm) - if network_section is not None and network_section.attrib.has_key('networkName'): + if network_section is not None and 'networkName' in network_section.attrib: parsed_respond['networkname'] = network_section.attrib['networkName'] ipscopes_section = \ @@ -2381,7 +2385,7 @@ class vimconnector(vimconn.vimconnector): parsed_respond['primarynetwork'] = adapters.text if adapter_key == 'NetworkConnection': vnic = {} - if adapters.attrib.has_key('network'): + if 'network' in adapters.attrib: vnic['network'] = adapters.attrib['network'] for adapter in adapters: setting_key = adapter.tag.split("}")[1] @@ -2389,7 +2393,7 @@ class vimconnector(vimconn.vimconnector): nic_list.append(vnic) for link in children_section: - if link.tag.split("}")[1] == 'Link' and link.attrib.has_key('rel'): + if link.tag.split("}")[1] == 'Link' and 'rel' in link.attrib: if link.attrib['rel'] == 'screen:acquireTicket': parsed_respond['acquireTicket'] = link.attrib if link.attrib['rel'] == 'screen:acquireMksTicket': @@ -2401,7 +2405,7 @@ class vimconnector(vimconn.vimconnector): return parsed_respond - def acuireConsole(self, vm_uuid=None): + def acuire_console(self, vm_uuid=None): vca = self.connect() if not vca: @@ -2410,7 +2414,7 @@ class vimconnector(vimconn.vimconnector): return None if not (not vca.vcloud_session or not vca.vcloud_session.organization): - vm_dict = self.get_vapp_details_rest(self, vm_uuid=vm_uuid) + vm_dict = self.get_vapp_details_rest(self, vapp_uuid=vm_uuid) console_dict = vm_dict['acquireTicket'] console_rest_call = console_dict['href'] @@ -2419,7 +2423,7 @@ class vimconnector(vimconn.vimconnector): verify=vca.verify, logger=vca.logger) - if response.status_code != requests.codes.ok: - return None + if response.status_code == requests.codes.ok: + return response.content - return response.content + return None \ No newline at end of file diff --git a/vmwarerecli.py b/vmwarerecli.py index c85b1d57..acd4240b 100755 --- a/vmwarerecli.py +++ b/vmwarerecli.py @@ -552,6 +552,7 @@ def boot_image(vim=None, image_name=None, vm_name=None): if vim_catalog is None: return None + print (" Booting {} image id {} ".format(vm_name, vim_catalog)) vm_uuid = vim.new_vminstance(name=vm_name, image_id=vim_catalog) if vm_uuid is not None and validate_uuid4(vm_uuid): print("Image booted and vm uuid {}".format(vm_uuid)) @@ -559,10 +560,17 @@ def boot_image(vim=None, image_name=None, vm_name=None): if vapp_dict is not None: print_vapp(vapp_dict=vapp_dict) return True + except vimconn.vimconnNotFoundException as notFound: + print("Failed boot {} image".format(image_name)) + print(notFound.message) + except vimconn.vimconnException as vimconError: + print("Failed boot {} image".format(image_name)) + print(vimconError.message) except: - print("Failed uploaded {} image".format(image_name)) + print("Failed boot {} image".format(image_name)) - return False + + return False def image_action(vim=None, action=None, namespace=None): -- 2.25.1 From 7725a1e3552fe32fae12e94d47595c4789d3b809 Mon Sep 17 00:00:00 2001 From: tierno Date: Mon, 3 Oct 2016 14:06:10 +0000 Subject: [PATCH 11/16] fixed small typo at basictest Signed-off-by: tierno --- test/basictest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/basictest.sh b/test/basictest.sh index 5fff3c5d..5b7dca54 100755 --- a/test/basictest.sh +++ b/test/basictest.sh @@ -167,7 +167,7 @@ then [[ -z $OPENVIM_HOST ]] && OPENVIM_HOST=localhost [[ -z $OPENVIM_PORT ]] && OPENVIM_PORT=9080 URL_ADMIN_PARAM="" - [[ -n $OPENVIM_ADMIN_PORT ]] && URL_ADMIN_PARAM="--url_admin=http://${$OPENVIM_HOST}:${OPENVIM_ADMIN_PORT}/openvim" + [[ -n $OPENVIM_ADMIN_PORT ]] && URL_ADMIN_PARAM="--url_admin=http://${OPENVIM_HOST}:${OPENVIM_ADMIN_PORT}/openvim" result=`${DIRmano}/openmano datacenter-create TEST-dc "http://${OPENVIM_HOST}:${OPENVIM_PORT}/openvim" --type=openvim $URL_ADMIN_PARAM` datacenter=`echo $result |gawk '{print $1}'` #check a valid uuid is obtained -- 2.25.1 From 41f18bea4579ddd058832c9e36a2278f7da6cbff Mon Sep 17 00:00:00 2001 From: garciadeblas Date: Tue, 4 Oct 2016 09:09:58 +0200 Subject: [PATCH 12/16] Minor bug fixed in create_or_use_flavor when it contains a disk image Change-Id: I43dd1b4e822330908a46c8adf93ce26934000ad5 Signed-off-by: garciadeblas --- nfvo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nfvo.py b/nfvo.py index e8032064..2998c38a 100644 --- a/nfvo.py +++ b/nfvo.py @@ -344,7 +344,7 @@ def create_or_use_flavor(mydb, vims, flavor_dict, rollback_list, only_create_at_ if 'extended' in flavor_dict and flavor_dict['extended']!=None: dev_nb=0 for device in flavor_dict['extended'].get('devices',[]): - if "image" not in device or "image name" not in device: + if "image" not in device and "image name" not in device: continue image_dict={} image_dict['name']=device.get('image name',flavor_dict['name']+str(dev_nb)+"-img") -- 2.25.1 From 8b413241c07347b196b81f5c340137fa8963b1e1 Mon Sep 17 00:00:00 2001 From: tierno Date: Tue, 4 Oct 2016 08:00:54 +0000 Subject: [PATCH 13/16] allow running test_vimconn without user ssh keys. Change installation to copy .gitignore with common parameters Signed-off-by: tierno --- scripts/install-openmano.sh | 1 + test/test_vimconn.sh | 9 ++------- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/scripts/install-openmano.sh b/scripts/install-openmano.sh index 9aaf028e..c7e03aa5 100755 --- a/scripts/install-openmano.sh +++ b/scripts/install-openmano.sh @@ -264,6 +264,7 @@ if [[ -z $NOCLONE ]]; then ##### DOWNLOAD SOURCE ##### #################################################################' su $SUDO_USER -c 'git clone '"${GIT_URL}"' openmano' + su $SUDO_USER -c 'cp openmano/.gitignore-common openmano/.gitignore' #[[ -z $DEVELOP ]] && su $SUDO_USER -c 'git checkout ' fi diff --git a/test/test_vimconn.sh b/test/test_vimconn.sh index aedf20ac..7542d6c2 100755 --- a/test/test_vimconn.sh +++ b/test/test_vimconn.sh @@ -268,13 +268,8 @@ then #USER_KEY="" key_param1="" key_param2="" - #for file_key in ${HOME}/.ssh/*.pub - #do - # [[ -n ${USER_KEY} ]] && USER_KEY="${USER_KEY}," - # USER_KEY="${USER_KEY}$(cat $file_key)" - #done - #[[ -n ${USER_KEY} ]] && key_param1="--keypair=${USER}:${USER_KEY}" && key_param2="--keypair=${USER_KEY}" - key_param1=--keypair-auto + #add user keys if present at .ssh + ls ${HOME}/.ssh/*.pub > /dev/null 2>&1 && key_param1=--keypair-auto for sce in simple complex2 do -- 2.25.1 From a2793919ce06ce40e809c3578a0aec27c7efbae4 Mon Sep 17 00:00:00 2001 From: tierno Date: Tue, 4 Oct 2016 08:15:08 +0000 Subject: [PATCH 14/16] v0.4.61 fixed 37 Deploying multisite get properly the information from sites. Deletion is properly done Signed-off-by: tierno --- nfvo.py | 410 +++++++++++++++++++++++---------------------------- nfvo_db.py | 13 +- openmanod.py | 4 +- 3 files changed, 195 insertions(+), 232 deletions(-) diff --git a/nfvo.py b/nfvo.py index e8032064..1229f4c6 100644 --- a/nfvo.py +++ b/nfvo.py @@ -92,7 +92,8 @@ def get_imagelist(mydb, vnf_id, nfvo_tenant=None): imageList.append(image['image_id']) return imageList -def get_vim(mydb, nfvo_tenant=None, datacenter_id=None, datacenter_name=None, vim_tenant=None, vim_tenant_name=None, vim_user=None, vim_passwd=None): +def get_vim(mydb, nfvo_tenant=None, datacenter_id=None, datacenter_name=None, datacenter_tenant_id=None, + vim_tenant=None, vim_tenant_name=None, vim_user=None, vim_passwd=None): '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters return dictionary with {datacenter_id: vim_class, ... }. vim_class contain: 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd' @@ -101,9 +102,11 @@ def get_vim(mydb, nfvo_tenant=None, datacenter_id=None, datacenter_name=None, vi WHERE_dict={} if nfvo_tenant is not None: WHERE_dict['nfvo_tenant_id'] = nfvo_tenant if datacenter_id is not None: WHERE_dict['d.uuid'] = datacenter_id + if datacenter_tenant_id is not None: WHERE_dict['datacenter_tenant_id'] = datacenter_tenant_id if datacenter_name is not None: WHERE_dict['d.name'] = datacenter_name if vim_tenant is not None: WHERE_dict['dt.vim_tenant_id'] = vim_tenant - if nfvo_tenant or vim_tenant: + if vim_tenant_name is not None: WHERE_dict['vim_tenant_name'] = vim_tenant_name + if nfvo_tenant or vim_tenant or vim_tenant_name or datacenter_tenant_id: from_= 'tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join datacenter_tenants as dt on td.datacenter_tenant_id=dt.uuid' select_ = ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name', 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id', @@ -1303,29 +1306,16 @@ def edit_scenario(mydb, tenant_id, scenario_id, data): def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instance_scenario_description, datacenter=None,vim_tenant=None, startvms=True): #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id" - datacenter_id = None - datacenter_name=None - if datacenter != None: - if utils.check_valid_uuid(datacenter): - datacenter_id = datacenter - else: - datacenter_name = datacenter - vims = get_vim(mydb, tenant_id, datacenter_id, datacenter_name, vim_tenant) - if len(vims) == 0: - raise NfvoException("datacenter '{}' not found".format(datacenter), HTTP_Not_Found) - elif len(vims)>1: - #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found") - raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict) - myvim = vims.values()[0] + datacenter_id, myvim = get_datacenter_by_name_uuid(mydb, tenant_id, datacenter, vim_tenant=vim_tenant) + vims = {datacenter_id: myvim} myvim_tenant = myvim['tenant_id'] - datacenter_id = myvim['id'] datacenter_name = myvim['name'] - datacenter_tenant_id = myvim['config']['datacenter_tenant_id'] + rollbackList=[] try: #print "Checking that the scenario_id exists and getting the scenario dictionary" scenarioDict = mydb.get_scenario(scenario_id, tenant_id, datacenter_id) - scenarioDict['datacenter_tenant_id'] = datacenter_tenant_id + scenarioDict['datacenter2tenant'] = { datacenter_id: myvim['config']['datacenter_tenant_id'] } scenarioDict['datacenter_id'] = datacenter_id #print '================scenarioDict=======================' #print json.dumps(scenarioDict, indent=4) @@ -1532,7 +1522,7 @@ def unify_cloud_config(cloud_config): for index in index_to_delete: del users[index] -def get_datacenter_by_name_uuid(mydb, tenant_id, datacenter_id_name=None): +def get_datacenter_by_name_uuid(mydb, tenant_id, datacenter_id_name=None, **extra_filter): datacenter_id = None datacenter_name = None if datacenter_id_name: @@ -1540,7 +1530,7 @@ def get_datacenter_by_name_uuid(mydb, tenant_id, datacenter_id_name=None): datacenter_id = datacenter_id_name else: datacenter_name = datacenter_id_name - vims = get_vim(mydb, tenant_id, datacenter_id, datacenter_name, vim_tenant=None) + vims = get_vim(mydb, tenant_id, datacenter_id, datacenter_name, **extra_filter) if len(vims) == 0: raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name)), HTTP_Not_Found) elif len(vims)>1: @@ -1678,12 +1668,13 @@ def create_instance(mydb, tenant_id, instance_dict): #find main datacenter myvims = {} + datacenter2tenant = {} datacenter = instance_dict.get("datacenter") default_datacenter_id, vim = get_datacenter_by_name_uuid(mydb, tenant_id, datacenter) myvims[default_datacenter_id] = vim + datacenter2tenant[default_datacenter_id] = vim['config']['datacenter_tenant_id'] #myvim_tenant = myvim['tenant_id'] # default_datacenter_name = vim['name'] - default_datacenter_tenant_id = vim['config']['datacenter_tenant_id'] #TODO review rollbackList=[] #print "Checking that the scenario exists and getting the scenario dictionary" @@ -1693,7 +1684,6 @@ def create_instance(mydb, tenant_id, instance_dict): #logger.debug(">>>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256))) #logger.debug(">>>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256))) - scenarioDict['datacenter_tenant_id'] = default_datacenter_tenant_id scenarioDict['datacenter_id'] = default_datacenter_id auxNetDict = {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id @@ -1721,6 +1711,7 @@ def create_instance(mydb, tenant_id, instance_dict): #Add this datacenter to myvims d, v = get_datacenter_by_name_uuid(mydb, tenant_id, site["datacenter"]) myvims[d] = v + datacenter2tenant[d] = v['config']['datacenter_tenant_id'] site["datacenter"] = d #change name to id else: if site_without_datacenter_field: @@ -1741,7 +1732,8 @@ def create_instance(mydb, tenant_id, instance_dict): if vnf_instance_desc["datacenter"] not in myvims: d, v = get_datacenter_by_name_uuid(mydb, tenant_id, vnf_instance_desc["datacenter"]) myvims[d] = v - scenario_vnf["datacenter"] = d #change name to id + datacenter2tenant[d] = v['config']['datacenter_tenant_id'] + scenario_vnf["datacenter"] = vnf_instance_desc["datacenter"] #0.1 parse cloud-config parameters cloud_config = scenarioDict.get("cloud-config", {}) if instance_dict.get("cloud-config"): @@ -1800,7 +1792,6 @@ def create_instance(mydb, tenant_id, instance_dict): else: vim = myvims[ default_datacenter_id ] datacenter_id = default_datacenter_id - net_type = sce_net['type'] lookfor_filter = {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True if sce_net["external"]: @@ -1854,7 +1845,6 @@ def create_instance(mydb, tenant_id, instance_dict): raise NfvoException("No candidate VIM network found for " + filter_text, HTTP_Bad_Request ) else: sce_net["vim_id_sites"][datacenter_id] = vim_nets[0]['id'] - auxNetDict['scenario'][sce_net['uuid']][datacenter_id] = vim_nets[0]['id'] create_network = False if create_network: @@ -1903,7 +1893,6 @@ def create_instance(mydb, tenant_id, instance_dict): vim = myvims[ default_datacenter_id ] datacenter_id = default_datacenter_id sce_vnf["datacenter_id"] = datacenter_id - sce_vnf["datacenter_tenant_id"] = vim['config']['datacenter_tenant_id'] i = 0 for vm in sce_vnf['vms']: i += 1 @@ -1928,7 +1917,7 @@ def create_instance(mydb, tenant_id, instance_dict): myVMDict['imageRef'] = vm['vim_image_id'] myVMDict['flavorRef'] = vm['vim_flavor_id'] myVMDict['networks'] = [] -#TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true + #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true for iface in vm['interfaces']: netDict = {} if iface['type']=="data": @@ -1994,9 +1983,9 @@ def create_instance(mydb, tenant_id, instance_dict): if net["name"]==iface["internal_name"]: iface["vim_id"]=net["vim_id"] break - logger.debug("create_instance Deployment done") - print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False) - #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict) + scenarioDict["datacenter2tenant"] = datacenter2tenant + logger.debug("create_instance Deployment done scenarioDict: %s", + yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False) ) instance_id = mydb.new_instance_scenario_as_a_whole(tenant_id,instance_name, instance_description, scenarioDict) return mydb.get_instance_scenario(instance_id) except (NfvoException, vimconn.vimconnException,db_base_Exception) as e: @@ -2017,44 +2006,41 @@ def delete_instance(mydb, tenant_id, instance_id): #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False) tenant_id = instanceDict["tenant_id"] #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id" - try: - vims = get_vim(mydb, tenant_id, instanceDict['datacenter_id']) - if len(vims) == 0: - logger.error("!!!!!! nfvo.delete_instance() datacenter not found!!!!") - myvim = None - else: - myvim = vims.values()[0] - except NfvoException as e: - logger.error("!!!!!! nfvo.delete_instance() datacenter Exception!!!! " + str(e)) - myvim = None - - - #1. Delete from Database - #result,c = mydb.delete_row_by_id('instance_scenarios', instance_id, nfvo_tenant) + #1. Delete from Database message = mydb.delete_instance_scenario(instance_id, tenant_id) #2. delete from VIM - if not myvim: - error_msg = "Not possible to delete VIM VMs and networks. Datacenter not found at database!!!" - else: - error_msg = "" + error_msg = "" + myvims={} #2.1 deleting VMs #vm_fail_list=[] for sce_vnf in instanceDict['vnfs']: - if not myvim: - continue + datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]) + if datacenter_key not in myvims: + vims = get_vim(mydb, tenant_id, datacenter_id=sce_vnf["datacenter_id"], + datacenter_tenant_id=sce_vnf["datacenter_tenant_id"]) + if len(vims) == 0: + logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], + sce_vnf["datacenter_tenant_id"])) + myvims[datacenter_key] = None + else: + myvims[datacenter_key] = vims.values()[0] + myvim = myvims[datacenter_key] for vm in sce_vnf['vms']: + if not myvim: + error_msg += "\n VM id={} cannot be deleted because datacenter={} not found".format(vm['vim_vm_id'], sce_vnf["datacenter_id"]) + continue try: myvim.delete_vminstance(vm['vim_vm_id']) except vimconn.vimconnNotFoundException as e: - error_msg+="\n VM id={} not found at VIM".format(vm['vim_vm_id']) + error_msg+="\n VM VIM_id={} not found at datacenter={}".format(vm['vim_vm_id'], sce_vnf["datacenter_id"]) logger.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found", vm['name'], vm['uuid'], vm['vim_vm_id'], sce_vnf['vnf_id']) except vimconn.vimconnException as e: - error_msg+="\n Error: " + e.http_code + " VM id=" + vm['vim_vm_id'] - logger.error("Error %d deleting VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s': %s", + error_msg+="\n VM VIM_id={} at datacenter={} Error: {} {}".format(vm['vim_vm_id'], sce_vnf["datacenter_id"], e.http_code, str(e)) + logger.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s", e.http_code, vm['name'], vm['uuid'], vm['vim_vm_id'], sce_vnf['vnf_id'], str(e)) #2.2 deleting NETS @@ -2062,18 +2048,30 @@ def delete_instance(mydb, tenant_id, instance_id): for net in instanceDict['nets']: if not net['created']: continue #skip not created nets + datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"]) + if datacenter_key not in myvims: + vims = get_vim(mydb, tenant_id, datacenter_id=net["datacenter_id"], + datacenter_tenant_id=net["datacenter_tenant_id"]) + if len(vims) == 0: + logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])) + myvims[datacenter_key] = None + else: + myvims[datacenter_key] = vims.values()[0] + myvim = myvims[datacenter_key] + if not myvim: + error_msg += "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net['vim_net_id'], net["datacenter_id"]) continue try: myvim.delete_network(net['vim_net_id']) except vimconn.vimconnNotFoundException as e: - error_msg+="\n NET id={} not found at VIM".format(net['vim_net_id']) - logger.warn("NET '%s', VIM id '%s', from VNF_id '%s' not found", - net['uuid'], net['vim_net_id'], sce_vnf['vnf_id']) + error_msg+="\n NET VIM_id={} not found at datacenter={}".format(net['vim_net_id'], net["datacenter_id"]) + logger.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found", + net['uuid'], net['vim_net_id'], str(net['vnf_net_id'])) except vimconn.vimconnException as e: - error_msg+="\n Error: " + e.http_code + " Net id=" + net['vim_vm_id'] - logger.error("Error %d deleting NET '%s', VIM id '%s', from VNF_id '%s': %s", - e.http_code, net['uuid'], net['vim_net_id'], sce_vnf['vnf_id'], str(e)) + error_msg+="\n NET VIM_id={} at datacenter={} Error: {} {}".format(net['vim_net_id'], net["datacenter_id"], e.http_code, str(e)) + logger.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s", + e.http_code, net['uuid'], net['vim_net_id'], str(net['vnf_net_id']), str(e)) if len(error_msg)>0: return 'instance ' + message + ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg else: @@ -2090,93 +2088,143 @@ def refresh_instance(mydb, nfvo_tenant, instanceDict, datacenter=None, vim_tenan #print json.dumps(instanceDict, indent=4) #print "Getting the VIM URL and the VIM tenant_id" - vims = get_vim(mydb, nfvo_tenant, instanceDict['datacenter_id']) - if len(vims) == 0: - raise NfvoException("datacenter '{}' not found".format(str(instanceDict['datacenter_id'])), HTTP_Not_Found) - myvim = vims.values()[0] - + myvims={} + # 1. Getting VIM vm and net list vms_updated = [] #List of VM instance uuids in openmano that were updated vms_notupdated=[] - vm_list = [] + vm_list = {} for sce_vnf in instanceDict['vnfs']: + datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]) + if datacenter_key not in vm_list: + vm_list[datacenter_key] = [] + if datacenter_key not in myvims: + vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"], + datacenter_tenant_id=sce_vnf["datacenter_tenant_id"]) + if len(vims) == 0: + logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])) + myvims[datacenter_key] = None + else: + myvims[datacenter_key] = vims.values()[0] for vm in sce_vnf['vms']: - vm_list.append(vm['vim_vm_id']) + vm_list[datacenter_key].append(vm['vim_vm_id']) vms_notupdated.append(vm["uuid"]) nets_updated = [] #List of VM instance uuids in openmano that were updated nets_notupdated=[] - net_list=[] + net_list = {} for net in instanceDict['nets']: - net_list.append(net['vim_net_id']) + datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"]) + if datacenter_key not in net_list: + net_list[datacenter_key] = [] + if datacenter_key not in myvims: + vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"], + datacenter_tenant_id=net["datacenter_tenant_id"]) + if len(vims) == 0: + logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])) + myvims[datacenter_key] = None + else: + myvims[datacenter_key] = vims.values()[0] + + net_list[datacenter_key].append(net['vim_net_id']) nets_notupdated.append(net["uuid"]) - try: - # 1. Getting the status of all VMs - vm_dict = myvim.refresh_vms_status(vm_list) + # 1. Getting the status of all VMs + vm_dict={} + for datacenter_key in myvims: + if not vm_list.get(datacenter_key): + continue + failed = True + failed_message="" + if not myvims[datacenter_key]: + failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]) + else: + try: + vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) ) + failed = False + except vimconn.vimconnException as e: + logger.error("VIM exception %s %s", type(e).__name__, str(e)) + failed_message = str(e) + if failed: + for vm in vm_list[datacenter_key]: + vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message} - # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed - for sce_vnf in instanceDict['vnfs']: - for vm in sce_vnf['vms']: - vm_id = vm['vim_vm_id'] - interfaces = vm_dict[vm_id].pop('interfaces', []) - #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE - has_mgmt_iface = False - for iface in vm["interfaces"]: - if iface["type"]=="mgmt": - has_mgmt_iface = True - if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface: - vm_dict[vm_id]['status'] = "ACTIVE" - if vm['status'] != vm_dict[vm_id]['status'] or vm.get('error_msg')!=vm_dict[vm_id].get('error_msg') or vm.get('vim_info')!=vm_dict[vm_id].get('vim_info'): - vm['status'] = vm_dict[vm_id]['status'] - vm['error_msg'] = vm_dict[vm_id].get('error_msg') - vm['vim_info'] = vm_dict[vm_id].get('vim_info') - # 2.1. Update in openmano DB the VMs whose status changed - try: - updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]}) - vms_notupdated.remove(vm["uuid"]) - if updates>0: - vms_updated.append(vm["uuid"]) - except db_base_Exception as e: - logger.error("nfvo.refresh_instance error database update: %s", str(e)) - # 2.2. Update in openmano DB the interface VMs - for interface in interfaces: - #translate from vim_net_id to instance_net_id - network_id_list=[] - for net in instanceDict['nets']: - if net["vim_net_id"] == interface["vim_net_id"]: - network_id_list.append(net["uuid"]) - if not network_id_list: - continue - del interface["vim_net_id"] - try: - for network_id in network_id_list: - mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id}) - except db_base_Exception as e: - logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id) - - # 3. Getting the status of all nets - net_dict = myvim.refresh_nets_status(net_list) - - # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed - # TODO: update nets inside a vnf - for net in instanceDict['nets']: - net_id = net['vim_net_id'] - if net['status'] != net_dict[net_id]['status'] or net.get('error_msg')!=net_dict[net_id].get('error_msg') or net.get('vim_info')!=net_dict[net_id].get('vim_info'): - net['status'] = net_dict[net_id]['status'] - net['error_msg'] = net_dict[net_id].get('error_msg') - net['vim_info'] = net_dict[net_id].get('vim_info') - # 5.1. Update in openmano DB the nets whose status changed + # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed + for sce_vnf in instanceDict['vnfs']: + for vm in sce_vnf['vms']: + vm_id = vm['vim_vm_id'] + interfaces = vm_dict[vm_id].pop('interfaces', []) + #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE + has_mgmt_iface = False + for iface in vm["interfaces"]: + if iface["type"]=="mgmt": + has_mgmt_iface = True + if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface: + vm_dict[vm_id]['status'] = "ACTIVE" + if vm['status'] != vm_dict[vm_id]['status'] or vm.get('error_msg')!=vm_dict[vm_id].get('error_msg') or vm.get('vim_info')!=vm_dict[vm_id].get('vim_info'): + vm['status'] = vm_dict[vm_id]['status'] + vm['error_msg'] = vm_dict[vm_id].get('error_msg') + vm['vim_info'] = vm_dict[vm_id].get('vim_info') + # 2.1. Update in openmano DB the VMs whose status changed try: - updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]}) - nets_notupdated.remove(net["uuid"]) - if updated>0: - nets_updated.append(net["uuid"]) + updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]}) + vms_notupdated.remove(vm["uuid"]) + if updates>0: + vms_updated.append(vm["uuid"]) except db_base_Exception as e: logger.error("nfvo.refresh_instance error database update: %s", str(e)) - except vimconn.vimconnException as e: - #logger.error("VIM exception %s %s", type(e).__name__, str(e)) - raise NfvoException(str(e), e.http_code) + # 2.2. Update in openmano DB the interface VMs + for interface in interfaces: + #translate from vim_net_id to instance_net_id + network_id_list=[] + for net in instanceDict['nets']: + if net["vim_net_id"] == interface["vim_net_id"]: + network_id_list.append(net["uuid"]) + if not network_id_list: + continue + del interface["vim_net_id"] + try: + for network_id in network_id_list: + mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id}) + except db_base_Exception as e: + logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id) + + # 3. Getting the status of all nets + net_dict = {} + for datacenter_key in myvims: + if not net_list.get(datacenter_key): + continue + failed = True + failed_message = "" + if not myvims[datacenter_key]: + failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]) + else: + try: + net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) ) + failed = False + except vimconn.vimconnException as e: + logger.error("VIM exception %s %s", type(e).__name__, str(e)) + failed_message = str(e) + if failed: + for net in net_list[datacenter_key]: + net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message} + + # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed + # TODO: update nets inside a vnf + for net in instanceDict['nets']: + net_id = net['vim_net_id'] + if net['status'] != net_dict[net_id]['status'] or net.get('error_msg')!=net_dict[net_id].get('error_msg') or net.get('vim_info')!=net_dict[net_id].get('vim_info'): + net['status'] = net_dict[net_id]['status'] + net['error_msg'] = net_dict[net_id].get('error_msg') + net['vim_info'] = net_dict[net_id].get('vim_info') + # 5.1. Update in openmano DB the nets whose status changed + try: + updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]}) + nets_notupdated.remove(net["uuid"]) + if updated>0: + nets_updated.append(net["uuid"]) + except db_base_Exception as e: + logger.error("nfvo.refresh_instance error database update: %s", str(e)) # Returns appropriate output #print "nfvo.refresh_instance finishes" @@ -2355,18 +2403,7 @@ def delete_datacenter(mydb, datacenter): def associate_datacenter_to_tenant(mydb, nfvo_tenant, datacenter, vim_tenant_id=None, vim_tenant_name=None, vim_username=None, vim_password=None): #get datacenter info - if utils.check_valid_uuid(datacenter): - vims = get_vim(mydb, datacenter_id=datacenter, vim_tenant_name=vim_tenant_name, vim_user=vim_username, vim_passwd=vim_password) - else: - vims = get_vim(mydb, datacenter_name=datacenter, vim_tenant_name=vim_tenant_name, vim_user=vim_username, vim_passwd=vim_password) - if len(vims) == 0: - raise NfvoException("datacenter '{}' not found".format(str(datacenter)), HTTP_Not_Found) - elif len(vims)>1: - #print "nfvo.datacenter_action() error. Several datacenters found" - raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict) - - datacenter_id=vims.keys()[0] - myvim=vims[datacenter_id] + datacenter_id, myvim = get_datacenter_by_name_uuid(mydb, None, datacenter) datacenter_name=myvim["name"] create_vim_tenant=True if vim_tenant_id==None and vim_tenant_name==None else False @@ -2424,17 +2461,7 @@ def associate_datacenter_to_tenant(mydb, nfvo_tenant, datacenter, vim_tenant_id= def deassociate_datacenter_to_tenant(mydb, tenant_id, datacenter, vim_tenant_id=None): #get datacenter info - if utils.check_valid_uuid(datacenter): - vims = get_vim(mydb, datacenter_id=datacenter) - else: - vims = get_vim(mydb, datacenter_name=datacenter) - if len(vims) == 0: - raise NfvoException("datacenter '{}' not found".format(str(datacenter)), HTTP_Not_Found) - elif len(vims)>1: - #print "nfvo.datacenter_action() error. Several datacenters found" - raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict) - datacenter_id=vims.keys()[0] - myvim=vims[datacenter_id] + datacenter_id, myvim = get_datacenter_by_name_uuid(mydb, None, datacenter) #get nfvo_tenant info if not tenant_id or tenant_id=="any": @@ -2477,17 +2504,7 @@ def deassociate_datacenter_to_tenant(mydb, tenant_id, datacenter, vim_tenant_id= def datacenter_action(mydb, tenant_id, datacenter, action_dict): #DEPRECATED #get datacenter info - if utils.check_valid_uuid(datacenter): - vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter) - else: - vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter) - if len(vims) == 0: - raise NfvoException("datacenter '{}' not found".format(str(datacenter)), HTTP_Not_Found) - elif len(vims)>1: - #print "nfvo.datacenter_action() error. Several datacenters found" - raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict) - datacenter_id=vims.keys()[0] - myvim=vims[datacenter_id] + datacenter_id, myvim = get_datacenter_by_name_uuid(mydb, tenant_id, datacenter) if 'net-update' in action_dict: try: @@ -2528,16 +2545,7 @@ def datacenter_action(mydb, tenant_id, datacenter, action_dict): def datacenter_edit_netmap(mydb, tenant_id, datacenter, netmap, action_dict): #get datacenter info - if utils.check_valid_uuid(datacenter): - vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter) - else: - vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter) - if len(vims) == 0: - raise NfvoException("datacenter '{}' not found".format(str(datacenter)), HTTP_Not_Found) - elif len(vims)>1: - #print "nfvo.datacenter_action() error. Several datacenters found" - raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict) - datacenter_id=vims.keys()[0] + datacenter_id, _ = get_datacenter_by_name_uuid(mydb, tenant_id, datacenter) what = 'uuid' if utils.check_valid_uuid(netmap) else 'name' result = mydb.update_rows('datacenter_nets', action_dict['netmap'], @@ -2546,17 +2554,7 @@ def datacenter_edit_netmap(mydb, tenant_id, datacenter, netmap, action_dict): def datacenter_new_netmap(mydb, tenant_id, datacenter, action_dict=None): #get datacenter info - if utils.check_valid_uuid(datacenter): - vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter) - else: - vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter) - if len(vims) == 0: - raise NfvoException("datacenter '{}' not found".format(datacenter), HTTP_Not_Found) - elif len(vims)>1: - #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found") - raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict) - datacenter_id=vims.keys()[0] - myvim=vims[datacenter_id] + datacenter_id, myvim = get_datacenter_by_name_uuid(mydb, tenant_id, datacenter) filter_dict={} if action_dict: action_dict = action_dict["netmap"] @@ -2602,17 +2600,7 @@ def datacenter_new_netmap(mydb, tenant_id, datacenter, action_dict=None): def vim_action_get(mydb, tenant_id, datacenter, item, name): #get datacenter info - if utils.check_valid_uuid(datacenter): - vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter) - else: - vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter) - if len(vims) == 0: - raise NfvoException("datacenter '{}' not found".format(datacenter), HTTP_Not_Found) - elif len(vims)>1: - #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found") - raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict) - datacenter_id=vims.keys()[0] - myvim=vims[datacenter_id] + datacenter_id, myvim = get_datacenter_by_name_uuid(mydb, tenant_id, datacenter) filter_dict={} if name: if utils.check_valid_uuid(name): @@ -2644,17 +2632,7 @@ def vim_action_delete(mydb, tenant_id, datacenter, item, name): if tenant_id == "any": tenant_id=None - if utils.check_valid_uuid(datacenter): - vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter) - else: - vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter) - if len(vims) == 0: - raise NfvoException("datacenter '{}' not found".format(datacenter), HTTP_Not_Found) - elif len(vims)>1: - #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found") - raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict) - datacenter_id=vims.keys()[0] - myvim=vims[datacenter_id] + datacenter_id, myvim = get_datacenter_by_name_uuid(mydb, tenant_id, datacenter) #get uuid name content = vim_action_get(mydb, tenant_id, datacenter, item, name) logger.debug("vim_action_delete vim response: " + str(content)) @@ -2682,22 +2660,10 @@ def vim_action_delete(mydb, tenant_id, datacenter, item, name): def vim_action_create(mydb, tenant_id, datacenter, item, descriptor): #get datacenter info - print "vim_action_create descriptor", descriptor + logger.debug("vim_action_create descriptor %s", str(descriptor)) if tenant_id == "any": tenant_id=None - - if utils.check_valid_uuid(datacenter): - vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter) - else: - vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter) - if len(vims) == 0: - raise NfvoException("datacenter '{}' not found".format(datacenter), HTTP_Not_Found) - elif len(vims)>1: - #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found") - raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict) - datacenter_id=vims.keys()[0] - myvim=vims[datacenter_id] - + datacenter_id, myvim = get_datacenter_by_name_uuid(mydb, tenant_id, datacenter) try: if item=="networks": net = descriptor["network"] diff --git a/nfvo_db.py b/nfvo_db.py index 9d3b6485..1fa5d723 100644 --- a/nfvo_db.py +++ b/nfvo_db.py @@ -44,7 +44,6 @@ class nfvo_db(db_base.db_base): db_base.db_base.tables_with_created_field=tables_with_createdat_field return - def new_vnf_as_a_whole(self,nfvo_tenant,vnf_name,vnf_descriptor,VNFCDict): self.logger.debug("Adding new vnf to the NFVO database") tries = 2 @@ -707,7 +706,6 @@ class nfvo_db(db_base.db_base): self._format_error(e, tries) tries -= 1 - def delete_scenario(self, scenario_id, tenant_id=None): '''Deletes a scenario, filtering by one or several of the tenant, uuid or name scenario_id is the uuid or the name if it is not a valid uuid format @@ -752,10 +750,9 @@ class nfvo_db(db_base.db_base): with self.con: self.cur = self.con.cursor() #instance_scenarios - datacenter_tenant_id = scenarioDict['datacenter_tenant_id'] datacenter_id = scenarioDict['datacenter_id'] INSERT_={'tenant_id': tenant_id, - 'datacenter_tenant_id': datacenter_tenant_id, + 'datacenter_tenant_id': scenarioDict["datacenter2tenant"][datacenter_id], 'name': instance_scenario_name, 'description': instance_scenario_description, 'scenario_id' : scenarioDict['uuid'], @@ -773,12 +770,13 @@ class nfvo_db(db_base.db_base): datacenter_site_id = net.get('datacenter_id', datacenter_id) if not "vim_id_sites" in net: net["vim_id_sites"] ={datacenter_site_id: net['vim_id']} + net["vim_id_sites"]["datacenter_site_id"] = {datacenter_site_id: net['vim_id']} sce_net_id = net.get("uuid") for datacenter_site_id,vim_id in net["vim_id_sites"].iteritems(): INSERT_={'vim_net_id': vim_id, 'created': net.get('created', False), 'instance_scenario_id':instance_uuid } #, 'type': net['type'] INSERT_['datacenter_id'] = datacenter_site_id - INSERT_['datacenter_tenant_id'] = net.get('datacenter_tenant_id', datacenter_tenant_id) #TODO revise + INSERT_['datacenter_tenant_id'] = scenarioDict["datacenter2tenant"][datacenter_site_id] if sce_net_id: INSERT_['sce_net_id'] = sce_net_id created_time += 0.00001 @@ -796,10 +794,9 @@ class nfvo_db(db_base.db_base): #instance_vnfs for vnf in scenarioDict['vnfs']: datacenter_site_id = vnf.get('datacenter_id', datacenter_id) - datacenter_site_tenant_id = vnf.get('datacenter_tenant_id', datacenter_id) INSERT_={'instance_scenario_id': instance_uuid, 'vnf_id': vnf['vnf_id'] } INSERT_['datacenter_id'] = datacenter_site_id - INSERT_['datacenter_tenant_id'] = datacenter_site_tenant_id #TODO revise + INSERT_['datacenter_tenant_id'] = scenarioDict["datacenter2tenant"][datacenter_site_id] if vnf.get("uuid"): INSERT_['sce_vnf_id'] = vnf['uuid'] created_time += 0.00001 @@ -811,7 +808,7 @@ class nfvo_db(db_base.db_base): net_scene2instance[ net['uuid'] ] = {} INSERT_={'vim_net_id': net['vim_id'], 'created': net.get('created', False), 'instance_scenario_id':instance_uuid } #, 'type': net['type'] INSERT_['datacenter_id'] = net.get('datacenter_id', datacenter_site_id) - INSERT_['datacenter_tenant_id'] = net.get('datacenter_tenant_id', datacenter_site_tenant_id) + INSERT_['datacenter_tenant_id'] = scenarioDict["datacenter2tenant"][datacenter_id] if net.get("uuid"): INSERT_['net_id'] = net['uuid'] created_time += 0.00001 diff --git a/openmanod.py b/openmanod.py index 6df29d11..d01ea641 100755 --- a/openmanod.py +++ b/openmanod.py @@ -33,8 +33,8 @@ It loads the configuration file and launches the http_server thread that will li ''' __author__="Alfonso Tierno, Gerardo Garcia, Pablo Montes" __date__ ="$26-aug-2014 11:09:29$" -__version__="0.4.60-r503" -version_date="Sep 2016" +__version__="0.4.61-r505" +version_date="Oct 2016" database_version="0.15" #expected database schema version import httpserver -- 2.25.1 From 5e91eb8987aea037647103633909bf894bbed3c5 Mon Sep 17 00:00:00 2001 From: tierno Date: Tue, 4 Oct 2016 09:39:07 +0000 Subject: [PATCH 15/16] v0.4.62 Get properly a vimconn error at image/flavor list/create Signed-off-by: tierno --- nfvo.py | 18 +++++++++++++----- openmanod.py | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/nfvo.py b/nfvo.py index 1229f4c6..005e065b 100644 --- a/nfvo.py +++ b/nfvo.py @@ -255,10 +255,12 @@ def check_vnf_descriptor(vnf_descriptor): HTTP_Bad_Request) return -HTTP_Bad_Request, -def create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vim=False, return_on_error = False): +def create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vim=False, return_on_error = None): #look if image exist if only_create_at_vim: image_mano_id = image_dict['uuid'] + if return_on_error == None: + return_on_error = True else: if image_dict['location'] is not None: images = mydb.get_rows(FROM="images", WHERE={'location':image_dict['location'], 'metadata':image_dict['metadata']}) @@ -306,12 +308,15 @@ def create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vi if return_on_error: logger.error("Error creating image at VIM: %s", str(e)) raise - image_vim_id = str(e) + image_vim_id = None logger.warn("Error creating image at VIM: %s", str(e)) continue except vimconn.vimconnException as e: + if return_on_error: + logger.error("Error contacting VIM to know if the image exists at VIM: %s", str(e)) + raise logger.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e)) - image_vim_id = str(e) + image_vim_id = None continue #if we reach here, the image has been created or existed if len(image_db)==0: @@ -323,7 +328,7 @@ def create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vi return image_vim_id if only_create_at_vim else image_mano_id -def create_or_use_flavor(mydb, vims, flavor_dict, rollback_list, only_create_at_vim=False, return_on_error = False): +def create_or_use_flavor(mydb, vims, flavor_dict, rollback_list, only_create_at_vim=False, return_on_error = None): temp_flavor_dict= {'disk':flavor_dict.get('disk',1), 'ram':flavor_dict.get('ram'), 'vcpus':flavor_dict.get('vcpus'), @@ -336,6 +341,8 @@ def create_or_use_flavor(mydb, vims, flavor_dict, rollback_list, only_create_at_ #look if flavor exist if only_create_at_vim: flavor_mano_id = flavor_dict['uuid'] + if return_on_error == None: + return_on_error = True else: flavors = mydb.get_rows(FROM="flavors", WHERE=temp_flavor_dict) if len(flavors)>=1: @@ -437,6 +444,7 @@ def create_or_use_flavor(mydb, vims, flavor_dict, rollback_list, only_create_at_ logger.error("Error creating flavor at VIM %s: %s.", vim["name"], str(e)) raise logger.warn("Error creating flavor at VIM %s: %s.", vim["name"], str(e)) + flavor_vim_id = None continue #if reach here the flavor has been create or exist if len(flavor_db)==0: @@ -1904,7 +1912,7 @@ def create_instance(mydb, tenant_id, instance_dict): myVMDict['name'] = myVMDict['name'][0:255] #limit name length #create image at vim in case it not exist image_dict = mydb.get_table_by_uuid_name("images", vm['image_id']) - image_id = create_or_use_image(mydb, {datacenter_id: vim}, image_dict, [], True) + image_id = create_or_use_image(mydb, {datacenter_id: vim}, image_dict, [], True) vm['vim_image_id'] = image_id #create flavor at vim in case it not exist diff --git a/openmanod.py b/openmanod.py index d01ea641..535a11f8 100755 --- a/openmanod.py +++ b/openmanod.py @@ -33,7 +33,7 @@ It loads the configuration file and launches the http_server thread that will li ''' __author__="Alfonso Tierno, Gerardo Garcia, Pablo Montes" __date__ ="$26-aug-2014 11:09:29$" -__version__="0.4.61-r505" +__version__="0.4.62-r506" version_date="Oct 2016" database_version="0.15" #expected database schema version -- 2.25.1 From 65a0b964858817a012c1d86adf18fa87b53d5f74 Mon Sep 17 00:00:00 2001 From: tierno Date: Tue, 4 Oct 2016 12:43:11 +0000 Subject: [PATCH 16/16] v0.5.0 openmano for OSM Release One Signed-off-by: tierno --- openmanod.py | 2 +- scripts/install-openmano.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openmanod.py b/openmanod.py index 535a11f8..7d183eb7 100755 --- a/openmanod.py +++ b/openmanod.py @@ -33,7 +33,7 @@ It loads the configuration file and launches the http_server thread that will li ''' __author__="Alfonso Tierno, Gerardo Garcia, Pablo Montes" __date__ ="$26-aug-2014 11:09:29$" -__version__="0.4.62-r506" +__version__="0.5.0-r507" version_date="Oct 2016" database_version="0.15" #expected database schema version diff --git a/scripts/install-openmano.sh b/scripts/install-openmano.sh index c7e03aa5..85d3293b 100755 --- a/scripts/install-openmano.sh +++ b/scripts/install-openmano.sh @@ -265,7 +265,7 @@ if [[ -z $NOCLONE ]]; then #################################################################' su $SUDO_USER -c 'git clone '"${GIT_URL}"' openmano' su $SUDO_USER -c 'cp openmano/.gitignore-common openmano/.gitignore' - #[[ -z $DEVELOP ]] && su $SUDO_USER -c 'git checkout ' + [[ -z $DEVELOP ]] && su $SUDO_USER -c 'git checkout tags/v1.0' fi echo ' -- 2.25.1