1 # -*- coding: utf-8 -*-
4 # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
5 # This file is part of openmano
8 # Licensed under the Apache License, Version 2.0 (the "License"); you may
9 # not use this file except in compliance with the License. You may obtain
10 # a copy of the License at
12 # http://www.apache.org/licenses/LICENSE-2.0
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17 # License for the specific language governing permissions and limitations
20 # For those usages not covered by the Apache License, Version 2.0 please
21 # contact with: nfvlabs@tid.es
25 NFVO engine, implementing all the methods for the creation, deletion and management of vnfs, scenarios and instances
27 __author__
="Alfonso Tierno, Gerardo Garcia, Pablo Montes"
28 __date__
="$16-sep-2014 22:05:01$"
35 from db_base
import HTTP_Unauthorized
, HTTP_Bad_Request
, HTTP_Internal_Server_Error
, HTTP_Not_Found
,\
36 HTTP_Conflict
, HTTP_Method_Not_Allowed
37 import console_proxy_thread
as cli
42 from uuid
import uuid4
43 from db_base
import db_base_Exception
46 from threading
import Lock
48 from lib_osm_openvim
import ovim
as ovim_module
49 from lib_osm_openvim
.ovim
import ovimException
50 from Crypto
.PublicKey
import RSA
52 import osm_im
.vnfd
as vnfd_catalog
53 import osm_im
.nsd
as nsd_catalog
54 from pyangbind
.lib
.serialise
import pybindJSONDecoder
55 from itertools
import chain
58 global vimconn_imported
60 global default_volume_size
61 default_volume_size
= '5' #size in GB
66 vimconn_imported
= {} # dictionary with VIM type as key, loaded module as value
67 vim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-VIMs
68 vim_persistent_info
= {}
69 logger
= logging
.getLogger('openmano.nfvo')
75 class NfvoException(Exception):
76 def __init__(self
, message
, http_code
):
77 self
.http_code
= http_code
78 Exception.__init
__(self
, message
)
84 if task_id
<= last_task_id
:
85 task_id
= last_task_id
+ 0.000001
86 last_task_id
= task_id
87 return "ACTION-{:.6f}".format(task_id
)
88 # return (t.strftime("%Y%m%dT%H%M%S.{}%Z", t.localtime(task_id))).format(int((task_id % 1)*1e6))
91 def new_task(name
, params
, depends
=None):
93 task_id
= get_task_id()
94 task
= {"status": "enqueued", "id": task_id
, "name": name
, "params": params
}
96 task
["depends"] = depends
101 return True if id[:5] == "TASK-" else False
104 def get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_name
, tenant_id
):
105 name
= datacenter_name
[:16]
106 if name
not in vim_threads
["names"]:
107 vim_threads
["names"].append(name
)
109 name
= datacenter_name
[:16] + "." + tenant_name
[:16]
110 if name
not in vim_threads
["names"]:
111 vim_threads
["names"].append(name
)
113 name
= datacenter_id
+ "-" + tenant_id
114 vim_threads
["names"].append(name
)
118 def start_service(mydb
):
119 global db
, global_config
120 db
= nfvo_db
.nfvo_db()
121 db
.connect(global_config
['db_host'], global_config
['db_user'], global_config
['db_passwd'], global_config
['db_name'])
124 # Initialize openvim for SDN control
125 # TODO: Avoid static configuration by adding new parameters to openmanod.cfg
126 # TODO: review ovim.py to delete not needed configuration
127 ovim_configuration
= {
128 'logger_name': 'openmano.ovim',
129 'network_vlan_range_start': 1000,
130 'network_vlan_range_end': 4096,
131 'db_name': global_config
["db_ovim_name"],
132 'db_host': global_config
["db_ovim_host"],
133 'db_user': global_config
["db_ovim_user"],
134 'db_passwd': global_config
["db_ovim_passwd"],
137 'network_type': 'bridge',
138 #TODO: log_level_of should not be needed. To be modified in ovim
139 'log_level_of': 'DEBUG'
142 # starts ovim library
143 ovim
= ovim_module
.ovim(ovim_configuration
)
146 #delete old unneeded vim_actions
150 from_
= 'tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join '\
151 'datacenter_tenants as dt on td.datacenter_tenant_id=dt.uuid'
152 select_
= ('type', 'd.config as config', 'd.uuid as datacenter_id', 'vim_url', 'vim_url_admin',
153 'd.name as datacenter_name', 'dt.uuid as datacenter_tenant_id',
154 'dt.vim_tenant_name as vim_tenant_name', 'dt.vim_tenant_id as vim_tenant_id',
155 'user', 'passwd', 'dt.config as dt_config', 'nfvo_tenant_id')
156 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
)
158 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
159 'datacenter_id': vim
.get('datacenter_id')}
161 extra
.update(yaml
.load(vim
["config"]))
162 if vim
.get('dt_config'):
163 extra
.update(yaml
.load(vim
["dt_config"]))
164 if vim
["type"] not in vimconn_imported
:
167 module
= "vimconn_" + vim
["type"]
168 pkg
= __import__("osm_ro." + module
)
169 vim_conn
= getattr(pkg
, module
)
170 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
171 # vim_conn = imp.load_module(vim["type"], *module_info)
172 vimconn_imported
[vim
["type"]] = vim_conn
173 except (IOError, ImportError) as e
:
174 # if module_info and module_info[0]:
175 # file.close(module_info[0])
176 raise NfvoException("Unknown vim type '{}'. Cannot open file '{}.py'; {}: {}".format(
177 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
179 thread_id
= vim
['datacenter_tenant_id']
180 vim_persistent_info
[thread_id
] = {}
183 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
184 myvim
= vimconn_imported
[ vim
["type"] ].vimconnector(
185 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
186 tenant_id
=vim
['vim_tenant_id'], tenant_name
=vim
['vim_tenant_name'],
187 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
188 user
=vim
['user'], passwd
=vim
['passwd'],
189 config
=extra
, persistent_info
=vim_persistent_info
[thread_id
]
191 except vimconn
.vimconnException
as e
:
193 logger
.error("Cannot launch thread for VIM {} '{}': {}".format(vim
['datacenter_name'],
194 vim
['datacenter_id'], e
))
195 except Exception as e
:
196 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, e
),
197 HTTP_Internal_Server_Error
)
198 thread_name
= get_non_used_vim_name(vim
['datacenter_name'], vim
['vim_tenant_id'], vim
['vim_tenant_name'],
199 vim
['vim_tenant_id'])
200 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, vim
['datacenter_name'],
201 vim
['datacenter_tenant_id'], db
=db
, db_lock
=db_lock
, ovim
=ovim
)
203 vim_threads
["running"][thread_id
] = new_thread
204 except db_base_Exception
as e
:
205 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
206 except ovim_module
.ovimException
as e
:
208 if message
[:22] == "DATABASE wrong version":
209 message
= "DATABASE wrong version of lib_osm_openvim {msg} -d{dbname} -u{dbuser} -p{dbpass} {ver}' "\
210 "at host {dbhost}".format(
211 msg
=message
[22:-3], dbname
=global_config
["db_ovim_name"],
212 dbuser
=global_config
["db_ovim_user"], dbpass
=global_config
["db_ovim_passwd"],
213 ver
=message
[-3:-1], dbhost
=global_config
["db_ovim_host"])
214 raise NfvoException(message
, HTTP_Bad_Request
)
218 global ovim
, global_config
221 for thread_id
,thread
in vim_threads
["running"].items():
222 thread
.insert_task("exit")
223 vim_threads
["deleting"][thread_id
] = thread
224 vim_threads
["running"] = {}
225 if global_config
and global_config
.get("console_thread"):
226 for thread
in global_config
["console_thread"]:
227 thread
.terminate
= True
230 return ("openmanod version {} {}\n(c) Copyright Telefonica".format(global_config
["version"],
231 global_config
["version_date"] ))
235 Clean unused or old entries at database to avoid unlimited growing
236 :param mydb: database connector
239 # get and delete unused vim_actions: all elements deleted, one week before, instance not present
240 now
= t
.time()-3600*24*7
241 instance_action_id
= None
244 actions_to_delete
= mydb
.get_rows(
245 SELECT
=("item", "item_id", "instance_action_id"),
246 FROM
="vim_actions as va join instance_actions as ia on va.instance_action_id=ia.uuid "
247 "left join instance_scenarios as i on ia.instance_id=i.uuid",
248 WHERE
={"va.action": "DELETE", "va.modified_at<": now
, "i.uuid": None,
249 "va.status": ("DONE", "SUPERSEDED")},
252 for to_delete
in actions_to_delete
:
253 mydb
.delete_row(FROM
="vim_actions", WHERE
=to_delete
)
254 if instance_action_id
!= to_delete
["instance_action_id"]:
255 instance_action_id
= to_delete
["instance_action_id"]
256 mydb
.delete_row(FROM
="instance_actions", WHERE
={"uuid": instance_action_id
})
257 nb_deleted
+= len(actions_to_delete
)
258 if len(actions_to_delete
) < 100:
261 logger
.debug("Removed {} unused vim_actions".format(nb_deleted
))
265 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
267 return result, content:
268 <0, error_text upon error
269 nb_records, flavor_list on success
272 WHERE_dict
['vnf_id'] = vnf_id
273 if nfvo_tenant
is not None:
274 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
276 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
277 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
278 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
279 #print "get_flavor_list result:", result
280 #print "get_flavor_list content:", content
282 for flavor
in flavors
:
283 flavorList
.append(flavor
['flavor_id'])
287 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
289 return result, content:
290 <0, error_text upon error
291 nb_records, flavor_list on success
294 WHERE_dict
['vnf_id'] = vnf_id
295 if nfvo_tenant
is not None:
296 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
298 #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
299 images
= mydb
.get_rows(FROM
='vms join images on vms.image_id=images.uuid',SELECT
=('image_id',),WHERE
=WHERE_dict
)
302 imageList
.append(image
['image_id'])
306 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
307 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None):
308 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
309 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
310 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
311 raise exception upon error
314 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
315 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
316 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
317 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
318 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
319 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
320 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
321 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'
322 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
323 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
324 'user','passwd', 'dt.config as dt_config')
326 from_
= 'datacenters as d'
327 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
329 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
332 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
333 'datacenter_id': vim
.get('datacenter_id')}
335 extra
.update(yaml
.load(vim
["config"]))
336 if vim
.get('dt_config'):
337 extra
.update(yaml
.load(vim
["dt_config"]))
338 if vim
["type"] not in vimconn_imported
:
341 module
= "vimconn_" + vim
["type"]
342 pkg
= __import__("osm_ro." + module
)
343 vim_conn
= getattr(pkg
, module
)
344 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
345 # vim_conn = imp.load_module(vim["type"], *module_info)
346 vimconn_imported
[vim
["type"]] = vim_conn
347 except (IOError, ImportError) as e
:
348 # if module_info and module_info[0]:
349 # file.close(module_info[0])
350 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
351 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
354 if 'datacenter_tenant_id' in vim
:
355 thread_id
= vim
["datacenter_tenant_id"]
356 if thread_id
not in vim_persistent_info
:
357 vim_persistent_info
[thread_id
] = {}
358 persistent_info
= vim_persistent_info
[thread_id
]
362 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
363 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
364 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
365 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
),
366 tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
367 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
368 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
369 config
=extra
, persistent_info
=persistent_info
371 except Exception as e
:
372 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
374 except db_base_Exception
as e
:
375 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
378 def rollback(mydb
, vims
, rollback_list
):
380 #delete things by reverse order
381 for i
in range(len(rollback_list
)-1, -1, -1):
382 item
= rollback_list
[i
]
383 if item
["where"]=="vim":
384 if item
["vim_id"] not in vims
:
386 if is_task_id(item
["uuid"]):
388 vim
= vims
[item
["vim_id"]]
390 if item
["what"]=="image":
391 vim
.delete_image(item
["uuid"])
392 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_vim_id": vim
["id"], "vim_id":item
["uuid"]})
393 elif item
["what"]=="flavor":
394 vim
.delete_flavor(item
["uuid"])
395 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_vim_id": vim
["id"], "vim_id":item
["uuid"]})
396 elif item
["what"]=="network":
397 vim
.delete_network(item
["uuid"])
398 elif item
["what"]=="vm":
399 vim
.delete_vminstance(item
["uuid"])
400 except vimconn
.vimconnException
as e
:
401 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
402 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
403 except db_base_Exception
as e
:
404 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
408 if item
["what"]=="image":
409 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
410 elif item
["what"]=="flavor":
411 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
412 except db_base_Exception
as e
:
413 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
414 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
415 if len(undeleted_items
)==0:
416 return True," Rollback successful."
418 return False," Rollback fails to delete: " + str(undeleted_items
)
421 def check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1):
423 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
425 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
427 #dataplane interfaces
428 for numa
in vnfc
.get("numas",() ):
429 for interface
in numa
.get("interfaces",()):
430 if interface
["name"] in name_dict
:
432 "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
433 vnfc
["name"], interface
["name"]),
435 name_dict
[ interface
["name"] ] = "underlay"
437 for interface
in vnfc
.get("bridge-ifaces",() ):
438 if interface
["name"] in name_dict
:
440 "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
441 vnfc
["name"], interface
["name"]),
443 name_dict
[ interface
["name"] ] = "overlay"
444 vnfc_interfaces
[ vnfc
["name"] ] = name_dict
445 # check bood-data info
446 # if "boot-data" in vnfc:
447 # # check that user-data is incompatible with users and config-files
448 # if (vnfc["boot-data"].get("users") or vnfc["boot-data"].get("config-files")) and vnfc["boot-data"].get("user-data"):
449 # raise NfvoException(
450 # "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
453 #check if the info in external_connections matches with the one in the vnfcs
455 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
456 if external_connection
["name"] in name_list
:
458 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
459 external_connection
["name"]),
461 name_list
.append(external_connection
["name"])
462 if external_connection
["VNFC"] not in vnfc_interfaces
:
464 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
465 external_connection
["name"], external_connection
["VNFC"]),
468 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
470 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
471 external_connection
["name"],
472 external_connection
["local_iface_name"]),
475 #check if the info in internal_connections matches with the one in the vnfcs
477 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
478 if internal_connection
["name"] in name_list
:
480 "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection".format(
481 internal_connection
["name"]),
483 name_list
.append(internal_connection
["name"])
484 #We should check that internal-connections of type "ptp" have only 2 elements
486 if len(internal_connection
["elements"])>2 and (internal_connection
.get("type") == "ptp" or internal_connection
.get("type") == "e-line"):
488 "Error at 'vnf:internal-connections[name:'{}']:elements', size must be 2 for a '{}' type. Consider change it to '{}' type".format(
489 internal_connection
["name"],
490 'ptp' if vnf_descriptor_version
==1 else 'e-line',
491 'data' if vnf_descriptor_version
==1 else "e-lan"),
493 for port
in internal_connection
["elements"]:
495 iface
= port
["local_iface_name"]
496 if vnf
not in vnfc_interfaces
:
498 "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
499 internal_connection
["name"], vnf
),
501 if iface
not in vnfc_interfaces
[ vnf
]:
503 "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
504 internal_connection
["name"], iface
),
506 return -HTTP_Bad_Request
,
507 if vnf_descriptor_version
==1 and "type" not in internal_connection
:
508 if vnfc_interfaces
[vnf
][iface
] == "overlay":
509 internal_connection
["type"] = "bridge"
511 internal_connection
["type"] = "data"
512 if vnf_descriptor_version
==2 and "implementation" not in internal_connection
:
513 if vnfc_interfaces
[vnf
][iface
] == "overlay":
514 internal_connection
["implementation"] = "overlay"
516 internal_connection
["implementation"] = "underlay"
517 if (internal_connection
.get("type") == "data" or internal_connection
.get("type") == "ptp" or \
518 internal_connection
.get("implementation") == "underlay") and vnfc_interfaces
[vnf
][iface
] == "overlay":
520 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
521 internal_connection
["name"],
522 iface
, 'bridge' if vnf_descriptor_version
==1 else 'overlay',
523 'data' if vnf_descriptor_version
==1 else 'underlay'),
525 if (internal_connection
.get("type") == "bridge" or internal_connection
.get("implementation") == "overlay") and \
526 vnfc_interfaces
[vnf
][iface
] == "underlay":
528 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
529 internal_connection
["name"], iface
,
530 'data' if vnf_descriptor_version
==1 else 'underlay',
531 'bridge' if vnf_descriptor_version
==1 else 'overlay'),
535 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=None):
537 if only_create_at_vim
:
538 image_mano_id
= image_dict
['uuid']
539 if return_on_error
== None:
540 return_on_error
= True
542 if image_dict
['location']:
543 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
545 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
547 image_mano_id
= images
[0]['uuid']
549 #create image in MANO DB
550 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
551 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
552 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
554 #temp_image_dict['location'] = image_dict.get('new_location') if image_dict['location'] is None
555 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
556 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
557 #create image at every vim
558 for vim_id
,vim
in vims
.iteritems():
559 datacenter_vim_id
= vim
["config"]["datacenter_tenant_id"]
560 image_created
="false"
562 image_db
= mydb
.get_rows(FROM
="datacenters_images",
563 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'image_id': image_mano_id
})
564 #look at VIM if this image exist
566 if image_dict
['location'] is not None:
567 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
570 filter_dict
['name'] = image_dict
['universal_name']
571 if image_dict
.get('checksum') != None:
572 filter_dict
['checksum'] = image_dict
['checksum']
573 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
574 vim_images
= vim
.get_image_list(filter_dict
)
575 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
576 if len(vim_images
) > 1:
577 raise vimconn
.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict
)), HTTP_Conflict
)
578 elif len(vim_images
) == 0:
579 raise vimconn
.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict
)))
581 #logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
582 image_vim_id
= vim_images
[0]['id']
584 except vimconn
.vimconnNotFoundException
as e
:
585 #Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
587 #image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
588 if image_dict
['location']:
589 image_vim_id
= vim
.new_image(image_dict
)
590 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
593 #If we reach this point, then the image has image name, and optionally checksum, and could not be found
594 raise vimconn
.vimconnException(str(e
))
595 except vimconn
.vimconnException
as e
:
597 logger
.error("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
600 logger
.warn("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
602 except vimconn
.vimconnException
as e
:
604 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
606 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
609 #if we reach here, the image has been created or existed
611 #add new vim_id at datacenters_images
612 mydb
.new_row('datacenters_images', {'datacenter_vim_id': datacenter_vim_id
,
613 'image_id':image_mano_id
,
614 'vim_id': image_vim_id
,
615 'created':image_created
})
616 elif image_db
[0]["vim_id"]!=image_vim_id
:
617 #modify existing vim_id at datacenters_images
618 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_vim_id':vim_id
, 'image_id':image_mano_id
})
620 return image_vim_id
if only_create_at_vim
else image_mano_id
623 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
624 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',0),
625 'ram':flavor_dict
.get('ram'),
626 'vcpus':flavor_dict
.get('vcpus'),
628 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
629 del flavor_dict
['extended']
630 if 'extended' in flavor_dict
:
631 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
633 #look if flavor exist
634 if only_create_at_vim
:
635 flavor_mano_id
= flavor_dict
['uuid']
636 if return_on_error
== None:
637 return_on_error
= True
639 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
641 flavor_mano_id
= flavors
[0]['uuid']
644 #create one by one the images of aditional disks
645 dev_image_list
=[] #list of images
646 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
648 for device
in flavor_dict
['extended'].get('devices',[]):
649 if "image" not in device
and "image name" not in device
:
652 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
653 image_dict
['universal_name']=device
.get('image name')
654 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
655 image_dict
['location']=device
.get('image')
656 #image_dict['new_location']=vnfc.get('image location')
657 image_dict
['checksum']=device
.get('image checksum')
658 image_metadata_dict
= device
.get('image metadata', None)
659 image_metadata_str
= None
660 if image_metadata_dict
!= None:
661 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
662 image_dict
['metadata']=image_metadata_str
663 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
664 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
665 dev_image_list
.append(image_id
)
667 temp_flavor_dict
['name'] = flavor_dict
['name']
668 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
669 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
670 flavor_mano_id
= content
671 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
672 #create flavor at every vim
673 if 'uuid' in flavor_dict
:
674 del flavor_dict
['uuid']
676 for vim_id
,vim
in vims
.items():
677 datacenter_vim_id
= vim
["config"]["datacenter_tenant_id"]
678 flavor_created
="false"
680 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors",
681 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
})
682 #look at VIM if this flavor exist SKIPPED
683 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
685 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
689 # Create the flavor in VIM
690 # Translate images at devices from MANO id to VIM id
692 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
693 # make a copy of original devices
696 for device
in flavor_dict
["extended"].get("devices",[]):
699 devices_original
.append(dev
)
700 if 'image' in device
:
702 if 'image metadata' in device
:
703 del device
['image metadata']
704 if 'image checksum' in device
:
705 del device
['image checksum']
707 for index
in range(0,len(devices_original
)) :
708 device
=devices_original
[index
]
709 if "image" not in device
and "image name" not in device
:
711 disk_list
.append({'size': device
.get('size', default_volume_size
)})
714 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
715 image_dict
['universal_name']=device
.get('image name')
716 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
717 image_dict
['location']=device
.get('image')
718 # image_dict['new_location']=device.get('image location')
719 image_dict
['checksum']=device
.get('image checksum')
720 image_metadata_dict
= device
.get('image metadata', None)
721 image_metadata_str
= None
722 if image_metadata_dict
!= None:
723 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
724 image_dict
['metadata']=image_metadata_str
725 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
726 image_dict
["uuid"]=image_mano_id
727 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
729 #save disk information (image must be based on and size
730 disk_list
.append({'image_id': image_vim_id
, 'size': device
.get('size', default_volume_size
)})
732 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
735 #check that this vim_id exist in VIM, if not create
736 flavor_vim_id
=flavor_db
[0]["vim_id"]
738 vim
.get_flavor(flavor_vim_id
)
739 continue #flavor exist
740 except vimconn
.vimconnException
:
742 #create flavor at vim
743 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
746 flavor_vim_id
=vim
.get_flavor_id_from_data(flavor_dict
)
747 flavor_create
="false"
748 except vimconn
.vimconnException
as e
:
751 if not flavor_vim_id
:
752 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
753 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
754 flavor_created
="true"
755 except vimconn
.vimconnException
as e
:
757 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
759 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
762 #if reach here the flavor has been create or exist
763 if len(flavor_db
)==0:
764 #add new vim_id at datacenters_flavors
765 extended_devices_yaml
= None
766 if len(disk_list
) > 0:
767 extended_devices
= dict()
768 extended_devices
['disks'] = disk_list
769 extended_devices_yaml
= yaml
.safe_dump(extended_devices
,default_flow_style
=True,width
=256)
770 mydb
.new_row('datacenters_flavors',
771 {'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
, 'vim_id': flavor_vim_id
,
772 'created': flavor_created
, 'extended': extended_devices_yaml
})
773 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
774 #modify existing vim_id at datacenters_flavors
775 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
},
776 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
})
778 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
781 def get_str(obj
, field
, length
):
783 Obtain the str value,
788 value
= obj
.get(field
)
789 if value
is not None:
790 value
= str(value
)[:length
]
793 def _lookfor_or_create_image(db_image
, mydb
, descriptor
):
795 fill image content at db_image dictionary. Check if the image with this image and checksum exist
796 :param db_image: dictionary to insert data
797 :param mydb: database connector
798 :param descriptor: yang descriptor
799 :return: uuid if the image exist at DB, or None if a new image must be created with the data filled at db_image
802 db_image
["name"] = get_str(descriptor
, "image", 255)
803 db_image
["checksum"] = get_str(descriptor
, "image-checksum", 32)
804 if not db_image
["checksum"]: # Ensure that if empty string, None is stored
805 db_image
["checksum"] = None
806 if db_image
["name"].startswith("/"):
807 db_image
["location"] = db_image
["name"]
808 existing_images
= mydb
.get_rows(FROM
="images", WHERE
={'location': db_image
["location"]})
810 db_image
["universal_name"] = db_image
["name"]
811 existing_images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name': db_image
['universal_name'],
812 'checksum': db_image
['checksum']})
814 return existing_images
[0]["uuid"]
816 image_uuid
= str(uuid4())
817 db_image
["uuid"] = image_uuid
820 def new_vnfd_v3(mydb
, tenant_id
, vnf_descriptor
):
822 Parses an OSM IM vnfd_catalog and insert at DB
825 :param vnf_descriptor:
826 :return: The list of cretated vnf ids
829 myvnfd
= vnfd_catalog
.vnfd()
831 pybindJSONDecoder
.load_ietf_json(vnf_descriptor
, None, None, obj
=myvnfd
, path_helper
=True)
832 except Exception as e
:
833 raise NfvoException("Error. Invalid VNF descriptor format " + str(e
), HTTP_Bad_Request
)
841 db_ip_profiles_index
= 0
845 vnfd_catalog_descriptor
= vnf_descriptor
.get("vnfd:vnfd-catalog")
846 if not vnfd_catalog_descriptor
:
847 vnfd_catalog_descriptor
= vnf_descriptor
.get("vnfd-catalog")
848 vnfd_descriptor_list
= vnfd_catalog_descriptor
.get("vnfd")
849 if not vnfd_descriptor_list
:
850 vnfd_descriptor_list
= vnfd_catalog_descriptor
.get("vnfd:vnfd")
851 for vnfd_yang
in myvnfd
.vnfd_catalog
.vnfd
.itervalues():
852 vnfd
= vnfd_yang
.get()
855 vnf_uuid
= str(uuid4())
856 uuid_list
.append(vnf_uuid
)
857 vnfd_uuid_list
.append(vnf_uuid
)
858 vnfd_id
= get_str(vnfd
, "id", 255)
862 "name": get_str(vnfd
, "name", 255),
863 "description": get_str(vnfd
, "description", 255),
864 "tenant_id": tenant_id
,
865 "vendor": get_str(vnfd
, "vendor", 255),
866 "short_name": get_str(vnfd
, "short-name", 255),
867 "descriptor": str(vnf_descriptor
)[:60000]
870 for vnfd_descriptor
in vnfd_descriptor_list
:
871 if vnfd_descriptor
["id"] == str(vnfd
["id"]):
874 # table ip_profiles (ip-profiles)
875 ip_profile_name2db_table_index
= {}
876 for ip_profile
in vnfd
.get("ip-profiles").itervalues():
878 "ip_version": str(ip_profile
["ip-profile-params"].get("ip-version", "ipv4")),
879 "subnet_address": str(ip_profile
["ip-profile-params"].get("subnet-address")),
880 "gateway_address": str(ip_profile
["ip-profile-params"].get("gateway-address")),
881 "dhcp_enabled": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("enabled", True)),
882 "dhcp_start_address": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("start-address")),
883 "dhcp_count": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("count")),
886 for dns
in ip_profile
["ip-profile-params"]["dns-server"].itervalues():
887 dns_list
.append(str(dns
.get("address")))
888 db_ip_profile
["dns_address"] = ";".join(dns_list
)
889 if ip_profile
["ip-profile-params"].get('security-group'):
890 db_ip_profile
["security_group"] = ip_profile
["ip-profile-params"]['security-group']
891 ip_profile_name2db_table_index
[str(ip_profile
["name"])] = db_ip_profiles_index
892 db_ip_profiles_index
+= 1
893 db_ip_profiles
.append(db_ip_profile
)
895 # table nets (internal-vld)
896 net_id2uuid
= {} # for mapping interface with network
897 for vld
in vnfd
.get("internal-vld").itervalues():
898 net_uuid
= str(uuid4())
899 uuid_list
.append(net_uuid
)
901 "name": get_str(vld
, "name", 255),
904 "description": get_str(vld
, "description", 255),
905 "type": "bridge", # TODO adjust depending on connection point type
907 net_id2uuid
[vld
.get("id")] = net_uuid
908 db_nets
.append(db_net
)
909 # ip-profile, link db_ip_profile with db_sce_net
910 if vld
.get("ip-profile-ref"):
911 ip_profile_name
= vld
.get("ip-profile-ref")
912 if ip_profile_name
not in ip_profile_name2db_table_index
:
913 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vld[{}]':'ip-profile-ref':"
914 "'{}'. Reference to a non-existing 'ip_profiles'".format(
915 str(vnfd
["id"]), str(vld
["id"]), str(vld
["ip-profile-ref"])),
917 db_ip_profiles
[ip_profile_name2db_table_index
[ip_profile_name
]]["net_id"] = net_uuid
918 else: #check no ip-address has been defined
919 for icp
in vld
.get("internal-connection-point"):
920 if icp
.get("ip-address"):
921 raise NfvoException("Error at 'vnfd[{}]':'vld[{}]':'internal-connection-point[{}]' "
922 "contains an ip-address but no ip-profile has been defined at VLD".format(
923 str(vnfd
["id"]), str(vld
["id"]), str(icp
["id"])),
926 # connection points vaiable declaration
927 cp_name2iface_uuid
= {}
929 cp_name2db_interface
= {}
933 vdu_id2db_table_index
= {}
934 for vdu
in vnfd
.get("vdu").itervalues():
936 for vdu_descriptor
in vnfd_descriptor
["vdu"]:
937 if vdu_descriptor
["id"] == str(vdu
["id"]):
939 vm_uuid
= str(uuid4())
940 uuid_list
.append(vm_uuid
)
941 vdu_id
= get_str(vdu
, "id", 255)
945 "name": get_str(vdu
, "name", 255),
946 "description": get_str(vdu
, "description", 255),
949 vdu_id2uuid
[db_vm
["osm_id"]] = vm_uuid
950 vdu_id2db_table_index
[db_vm
["osm_id"]] = db_vms_index
952 db_vm
["count"] = int(vdu
["count"])
955 image_present
= False
959 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, vdu
)
961 image_uuid
= db_image
["uuid"]
962 db_images
.append(db_image
)
963 db_vm
["image_id"] = image_uuid
967 if vdu
.get("volumes"):
968 for volume_key
in sorted(vdu
["volumes"]):
969 volume
= vdu
["volumes"][volume_key
]
970 if not image_present
:
971 # Convert the first volume to vnfc.image
974 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, volume
)
976 image_uuid
= db_image
["uuid"]
977 db_images
.append(db_image
)
978 db_vm
["image_id"] = image_uuid
980 # Add Openmano devices
982 device
["type"] = str(volume
.get("device-type"))
983 if volume
.get("size"):
984 device
["size"] = int(volume
["size"])
985 if volume
.get("image"):
986 device
["image name"] = str(volume
["image"])
987 if volume
.get("image-checksum"):
988 device
["image checksum"] = str(volume
["image-checksum"])
989 devices
.append(device
)
993 if vdu
.get("cloud-init"):
994 boot_data
["user-data"] = str(vdu
["cloud-init"])
995 elif vdu
.get("cloud-init-file"):
996 # TODO Where this file content is present???
997 # boot_data["user-data"] = vnfd_yang.files[vdu["cloud-init-file"]]
998 boot_data
["user-data"] = str(vdu
["cloud-init-file"])
1000 if vdu
.get("supplemental-boot-data"):
1001 if vdu
["supplemental-boot-data"].get('boot-data-drive'):
1002 boot_data
['boot-data-drive'] = True
1003 if vdu
["supplemental-boot-data"].get('config-file'):
1004 om_cfgfile_list
= list()
1005 for custom_config_file
in vdu
["supplemental-boot-data"]['config-file'].itervalues():
1006 # TODO Where this file content is present???
1007 cfg_source
= str(custom_config_file
["source"])
1008 om_cfgfile_list
.append({"dest": custom_config_file
["dest"],
1009 "content": cfg_source
})
1010 boot_data
['config-files'] = om_cfgfile_list
1012 db_vm
["boot_data"] = yaml
.safe_dump(boot_data
, default_flow_style
=True, width
=256)
1014 db_vms
.append(db_vm
)
1017 # table interfaces (internal/external interfaces)
1018 flavor_epa_interfaces
= []
1019 vdu_id2cp_name
= {} # stored only when one external connection point is presented at this VDU
1020 # for iface in chain(vdu.get("internal-interface").itervalues(), vdu.get("external-interface").itervalues()):
1021 for iface
in vdu
.get("interface").itervalues():
1022 flavor_epa_interface
= {}
1023 iface_uuid
= str(uuid4())
1024 uuid_list
.append(iface_uuid
)
1027 "internal_name": get_str(iface
, "name", 255),
1030 flavor_epa_interface
["name"] = db_interface
["internal_name"]
1031 if iface
.get("virtual-interface").get("vpci"):
1032 db_interface
["vpci"] = get_str(iface
.get("virtual-interface"), "vpci", 12)
1033 flavor_epa_interface
["vpci"] = db_interface
["vpci"]
1035 if iface
.get("virtual-interface").get("bandwidth"):
1036 bps
= int(iface
.get("virtual-interface").get("bandwidth"))
1037 db_interface
["bw"] = int(math
.ceil(bps
/1000000.0))
1038 flavor_epa_interface
["bandwidth"] = "{} Mbps".format(db_interface
["bw"])
1040 if iface
.get("virtual-interface").get("type") == "OM-MGMT":
1041 db_interface
["type"] = "mgmt"
1042 elif iface
.get("virtual-interface").get("type") in ("VIRTIO", "E1000"):
1043 db_interface
["type"] = "bridge"
1044 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1045 elif iface
.get("virtual-interface").get("type") in ("SR-IOV", "PCI-PASSTHROUGH"):
1046 db_interface
["type"] = "data"
1047 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1048 flavor_epa_interface
["dedicated"] = "no" if iface
["virtual-interface"]["type"] == "SR-IOV" \
1050 flavor_epa_interfaces
.append(flavor_epa_interface
)
1052 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vdu[{}]':'interface':'virtual"
1053 "-interface':'type':'{}'. Interface type is not supported".format(
1054 vnfd_id
, vdu_id
, iface
.get("virtual-interface").get("type")),
1057 if iface
.get("external-connection-point-ref"):
1059 cp
= vnfd
.get("connection-point")[iface
.get("external-connection-point-ref")]
1060 db_interface
["external_name"] = get_str(cp
, "name", 255)
1061 cp_name2iface_uuid
[db_interface
["external_name"]] = iface_uuid
1062 cp_name2vm_uuid
[db_interface
["external_name"]] = vm_uuid
1063 cp_name2db_interface
[db_interface
["external_name"]] = db_interface
1064 for cp_descriptor
in vnfd_descriptor
["connection-point"]:
1065 if cp_descriptor
["name"] == db_interface
["external_name"]:
1070 if vdu_id
in vdu_id2cp_name
:
1071 vdu_id2cp_name
[vdu_id
] = None # more than two connecdtion point for this VDU
1073 vdu_id2cp_name
[vdu_id
] = db_interface
["external_name"]
1076 if str(cp_descriptor
.get("port-security-enabled")).lower() == "false":
1077 db_interface
["port_security"] = 0
1078 elif str(cp_descriptor
.get("port-security-enabled")).lower() == "true":
1079 db_interface
["port_security"] = 1
1081 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1082 "'interface[{iface}]':'vnfd-connection-point-ref':'{cp}' is not present"
1083 " at connection-point".format(
1084 vnf
=vnfd_id
, vdu
=vdu_id
, iface
=iface
["name"],
1085 cp
=iface
.get("vnfd-connection-point-ref")),
1087 elif iface
.get("internal-connection-point-ref"):
1089 for icp_descriptor
in vdu_descriptor
["internal-connection-point"]:
1090 if icp_descriptor
["id"] == str(iface
.get("internal-connection-point-ref")):
1093 raise KeyError("does not exist at vdu:internal-connection-point")
1096 for vld
in vnfd
.get("internal-vld").itervalues():
1097 for cp
in vld
.get("internal-connection-point").itervalues():
1098 if cp
.get("id-ref") == iface
.get("internal-connection-point-ref"):
1100 raise KeyError("is referenced by more than one 'internal-vld'")
1104 raise KeyError("is not referenced by any 'internal-vld'")
1106 db_interface
["net_id"] = net_id2uuid
[icp_vld
.get("id")]
1107 if str(icp_descriptor
.get("port-security-enabled")).lower() == "false":
1108 db_interface
["port_security"] = 0
1109 elif str(icp_descriptor
.get("port-security-enabled")).lower() == "true":
1110 db_interface
["port_security"] = 1
1111 if icp
.get("ip-address"):
1112 if not icp_vld
.get("ip-profile-ref"):
1114 db_interface
["ip_address"] = str(icp
.get("ip-address"))
1115 except KeyError as e
:
1116 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1117 "'interface[{iface}]':'internal-connection-point-ref':'{cp}'"
1119 vnf
=vnfd_id
, vdu
=vdu_id
, iface
=iface
["name"],
1120 cp
=iface
.get("internal-connection-point-ref"), msg
=str(e
)),
1122 if iface
.get("position") is not None:
1123 db_interface
["created_at"] = int(iface
.get("position")) - 1000
1124 if iface
.get("mac-address"):
1125 db_interface
["mac"] = str(iface
.get("mac-address"))
1126 db_interfaces
.append(db_interface
)
1130 "name": get_str(vdu
, "name", 250) + "-flv",
1131 "vcpus": int(vdu
["vm-flavor"].get("vcpu-count", 1)),
1132 "ram": int(vdu
["vm-flavor"].get("memory-mb", 1)),
1133 "disk": int(vdu
["vm-flavor"].get("storage-gb", 0)),
1135 # TODO revise the case of several numa-node-policy node
1139 extended
["devices"] = devices
1140 if flavor_epa_interfaces
:
1141 numa
["interfaces"] = flavor_epa_interfaces
1142 if vdu
.get("guest-epa"): # TODO or dedicated_int:
1143 epa_vcpu_set
= False
1144 if vdu
["guest-epa"].get("numa-node-policy"): # TODO or dedicated_int:
1145 numa_node_policy
= vdu
["guest-epa"].get("numa-node-policy")
1146 if numa_node_policy
.get("node"):
1147 numa_node
= numa_node_policy
["node"].values()[0]
1148 if numa_node
.get("num-cores"):
1149 numa
["cores"] = numa_node
["num-cores"]
1151 if numa_node
.get("paired-threads"):
1152 if numa_node
["paired-threads"].get("num-paired-threads"):
1153 numa
["paired-threads"] = int(numa_node
["paired-threads"]["num-paired-threads"])
1155 if len(numa_node
["paired-threads"].get("paired-thread-ids")):
1156 numa
["paired-threads-id"] = []
1157 for pair
in numa_node
["paired-threads"]["paired-thread-ids"].itervalues():
1158 numa
["paired-threads-id"].append(
1159 (str(pair
["thread-a"]), str(pair
["thread-b"]))
1161 if numa_node
.get("num-threads"):
1162 numa
["threads"] = int(numa_node
["num-threads"])
1164 if numa_node
.get("memory-mb"):
1165 numa
["memory"] = max(int(numa_node
["memory-mb"] / 1024), 1)
1166 if vdu
["guest-epa"].get("mempage-size"):
1167 if vdu
["guest-epa"]["mempage-size"] != "SMALL":
1168 numa
["memory"] = max(int(db_flavor
["ram"] / 1024), 1)
1169 if vdu
["guest-epa"].get("cpu-pinning-policy") and not epa_vcpu_set
:
1170 if vdu
["guest-epa"]["cpu-pinning-policy"] == "DEDICATED":
1171 if vdu
["guest-epa"].get("cpu-thread-pinning-policy") and \
1172 vdu
["guest-epa"]["cpu-thread-pinning-policy"] != "PREFER":
1173 numa
["cores"] = max(db_flavor
["vcpus"], 1)
1175 numa
["threads"] = max(db_flavor
["vcpus"], 1)
1177 extended
["numas"] = [numa
]
1179 extended_text
= yaml
.safe_dump(extended
, default_flow_style
=True, width
=256)
1180 db_flavor
["extended"] = extended_text
1181 # look if flavor exist
1182 temp_flavor_dict
= {'disk': db_flavor
.get('disk', 0),
1183 'ram': db_flavor
.get('ram'),
1184 'vcpus': db_flavor
.get('vcpus'),
1185 'extended': db_flavor
.get('extended')
1187 existing_flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
1188 if existing_flavors
:
1189 flavor_uuid
= existing_flavors
[0]["uuid"]
1191 flavor_uuid
= str(uuid4())
1192 uuid_list
.append(flavor_uuid
)
1193 db_flavor
["uuid"] = flavor_uuid
1194 db_flavors
.append(db_flavor
)
1195 db_vm
["flavor_id"] = flavor_uuid
1197 # VNF affinity and antiaffinity
1198 for pg
in vnfd
.get("placement-groups").itervalues():
1199 pg_name
= get_str(pg
, "name", 255)
1200 for vdu
in pg
.get("member-vdus").itervalues():
1201 vdu_id
= get_str(vdu
, "member-vdu-ref", 255)
1202 if vdu_id
not in vdu_id2db_table_index
:
1203 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'placement-groups[{pg}]':"
1204 "'member-vdus':'{vdu}'. Reference to a non-existing vdu".format(
1205 vnf
=vnfd_id
, pg
=pg_name
, vdu
=vdu_id
),
1207 db_vms
[vdu_id2db_table_index
[vdu_id
]]["availability_zone"] = pg_name
1208 # TODO consider the case of isolation and not colocation
1209 # if pg.get("strategy") == "ISOLATION":
1211 # VNF mgmt configuration
1213 if vnfd
["mgmt-interface"].get("vdu-id"):
1214 mgmt_vdu_id
= get_str(vnfd
["mgmt-interface"], "vdu-id", 255)
1215 if mgmt_vdu_id
not in vdu_id2uuid
:
1216 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'vdu-id':"
1217 "'{vdu}'. Reference to a non-existing vdu".format(
1218 vnf
=vnfd_id
, vdu
=mgmt_vdu_id
),
1220 mgmt_access
["vm_id"] = vdu_id2uuid
[vnfd
["mgmt-interface"]["vdu-id"]]
1221 # if only one cp is defined by this VDU, mark this interface as of type "mgmt"
1222 if vdu_id2cp_name
.get(mgmt_vdu_id
):
1223 cp_name2db_interface
[vdu_id2cp_name
[mgmt_vdu_id
]]["type"] = "mgmt"
1225 if vnfd
["mgmt-interface"].get("ip-address"):
1226 mgmt_access
["ip-address"] = str(vnfd
["mgmt-interface"].get("ip-address"))
1227 if vnfd
["mgmt-interface"].get("cp"):
1228 if vnfd
["mgmt-interface"]["cp"] not in cp_name2iface_uuid
:
1229 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'cp':'{cp}'. "
1230 "Reference to a non-existing connection-point".format(
1231 vnf
=vnfd_id
, cp
=vnfd
["mgmt-interface"]["cp"]),
1233 mgmt_access
["vm_id"] = cp_name2vm_uuid
[vnfd
["mgmt-interface"]["cp"]]
1234 mgmt_access
["interface_id"] = cp_name2iface_uuid
[vnfd
["mgmt-interface"]["cp"]]
1235 # mark this interface as of type mgmt
1236 cp_name2db_interface
[vnfd
["mgmt-interface"]["cp"]]["type"] = "mgmt"
1238 default_user
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1242 mgmt_access
["default_user"] = default_user
1243 required
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1246 mgmt_access
["required"] = required
1249 db_vnf
["mgmt_access"] = yaml
.safe_dump(mgmt_access
, default_flow_style
=True, width
=256)
1251 db_vnfs
.append(db_vnf
)
1255 {"images": db_images
},
1256 {"flavors": db_flavors
},
1257 {"ip_profiles": db_ip_profiles
},
1259 {"interfaces": db_interfaces
},
1262 logger
.debug("create_vnf Deployment done vnfDict: %s",
1263 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
1264 mydb
.new_rows(db_tables
, uuid_list
)
1265 return vnfd_uuid_list
1266 except NfvoException
:
1268 except Exception as e
:
1269 logger
.error("Exception {}".format(e
))
1270 raise # NfvoException("Exception {}".format(e), HTTP_Bad_Request)
1273 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
1274 global global_config
1276 # Step 1. Check the VNF descriptor
1277 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
1278 # Step 2. Check tenant exist
1280 if tenant_id
!= "any":
1281 check_tenant(mydb
, tenant_id
)
1282 if "tenant_id" in vnf_descriptor
["vnf"]:
1283 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1284 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1287 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1288 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1289 if global_config
["auto_push_VNF_to_VIMs"]:
1290 vims
= get_vim(mydb
, tenant_id
)
1292 # Step 4. Review the descriptor and add missing fields
1293 #print vnf_descriptor
1294 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1295 vnf_name
= vnf_descriptor
['vnf']['name']
1296 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1297 if "physical" in vnf_descriptor
['vnf']:
1298 del vnf_descriptor
['vnf']['physical']
1299 #print vnf_descriptor
1301 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1302 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1303 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1305 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1306 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1307 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1309 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1310 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1312 VNFCitem
["name"] = vnfc
['name']
1313 VNFCitem
["availability_zone"] = vnfc
.get('availability_zone')
1314 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
1316 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1319 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1320 myflavorDict
["description"] = VNFCitem
["description"]
1321 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1322 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1323 myflavorDict
["disk"] = vnfc
.get("disk", 0)
1324 myflavorDict
["extended"] = {}
1326 devices
= vnfc
.get("devices")
1328 myflavorDict
["extended"]["devices"] = devices
1331 # Mapping from processor models to rankings should be available somehow in the NFVO. They could be taken from VIM or directly from a new database table
1332 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1334 # Previous code has been commented
1335 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1336 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1337 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1338 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1340 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1342 # print "Error creating flavor: unknown processor model. Rollback successful."
1343 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1345 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1346 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1348 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1349 myflavorDict
['extended']['numas'] = vnfc
['numas']
1353 # Step 6.2 New flavors are created in the VIM
1354 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1356 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1357 VNFCitem
["flavor_id"] = flavor_id
1358 VNFCDict
[vnfc
['name']] = VNFCitem
1360 logger
.debug("Creating new images in the VIM for each VNFC")
1361 # Step 6.3 New images are created in the VIM
1362 #For each VNFC, we must create the appropriate image.
1363 #This "for" loop might be integrated with the previous one
1364 #In case this integration is made, the VNFCDict might become a VNFClist.
1365 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1366 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1368 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1369 image_dict
['universal_name']=vnfc
.get('image name')
1370 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1371 image_dict
['location']=vnfc
.get('VNFC image')
1372 #image_dict['new_location']=vnfc.get('image location')
1373 image_dict
['checksum']=vnfc
.get('image checksum')
1374 image_metadata_dict
= vnfc
.get('image metadata', None)
1375 image_metadata_str
= None
1376 if image_metadata_dict
is not None:
1377 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1378 image_dict
['metadata']=image_metadata_str
1379 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1380 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1381 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1382 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1383 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1384 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1385 if vnfc
.get("boot-data"):
1386 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1389 # Step 7. Storing the VNF descriptor in the repository
1390 if "descriptor" not in vnf_descriptor
["vnf"]:
1391 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1393 # Step 8. Adding the VNF to the NFVO DB
1394 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1396 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1397 _
, message
= rollback(mydb
, vims
, rollback_list
)
1398 if isinstance(e
, db_base_Exception
):
1399 error_text
= "Exception at database"
1400 elif isinstance(e
, KeyError):
1401 error_text
= "KeyError exception "
1402 e
.http_code
= HTTP_Internal_Server_Error
1404 error_text
= "Exception at VIM"
1405 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1406 #logger.error("start_scenario %s", error_text)
1407 raise NfvoException(error_text
, e
.http_code
)
1410 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
1411 global global_config
1413 # Step 1. Check the VNF descriptor
1414 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
1415 # Step 2. Check tenant exist
1417 if tenant_id
!= "any":
1418 check_tenant(mydb
, tenant_id
)
1419 if "tenant_id" in vnf_descriptor
["vnf"]:
1420 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1421 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1424 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1425 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1426 if global_config
["auto_push_VNF_to_VIMs"]:
1427 vims
= get_vim(mydb
, tenant_id
)
1429 # Step 4. Review the descriptor and add missing fields
1430 #print vnf_descriptor
1431 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1432 vnf_name
= vnf_descriptor
['vnf']['name']
1433 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1434 if "physical" in vnf_descriptor
['vnf']:
1435 del vnf_descriptor
['vnf']['physical']
1436 #print vnf_descriptor
1438 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1439 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1440 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1442 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1443 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1444 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1446 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1447 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1449 VNFCitem
["name"] = vnfc
['name']
1450 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
1452 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1455 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1456 myflavorDict
["description"] = VNFCitem
["description"]
1457 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1458 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1459 myflavorDict
["disk"] = vnfc
.get("disk", 0)
1460 myflavorDict
["extended"] = {}
1462 devices
= vnfc
.get("devices")
1464 myflavorDict
["extended"]["devices"] = devices
1467 # Mapping from processor models to rankings should be available somehow in the NFVO. They could be taken from VIM or directly from a new database table
1468 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1470 # Previous code has been commented
1471 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1472 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1473 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1474 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1476 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1478 # print "Error creating flavor: unknown processor model. Rollback successful."
1479 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1481 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1482 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1484 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1485 myflavorDict
['extended']['numas'] = vnfc
['numas']
1489 # Step 6.2 New flavors are created in the VIM
1490 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1492 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1493 VNFCitem
["flavor_id"] = flavor_id
1494 VNFCDict
[vnfc
['name']] = VNFCitem
1496 logger
.debug("Creating new images in the VIM for each VNFC")
1497 # Step 6.3 New images are created in the VIM
1498 #For each VNFC, we must create the appropriate image.
1499 #This "for" loop might be integrated with the previous one
1500 #In case this integration is made, the VNFCDict might become a VNFClist.
1501 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1502 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1504 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1505 image_dict
['universal_name']=vnfc
.get('image name')
1506 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1507 image_dict
['location']=vnfc
.get('VNFC image')
1508 #image_dict['new_location']=vnfc.get('image location')
1509 image_dict
['checksum']=vnfc
.get('image checksum')
1510 image_metadata_dict
= vnfc
.get('image metadata', None)
1511 image_metadata_str
= None
1512 if image_metadata_dict
is not None:
1513 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1514 image_dict
['metadata']=image_metadata_str
1515 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1516 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1517 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1518 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1519 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1520 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1521 if vnfc
.get("boot-data"):
1522 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1524 # Step 7. Storing the VNF descriptor in the repository
1525 if "descriptor" not in vnf_descriptor
["vnf"]:
1526 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1528 # Step 8. Adding the VNF to the NFVO DB
1529 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1531 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1532 _
, message
= rollback(mydb
, vims
, rollback_list
)
1533 if isinstance(e
, db_base_Exception
):
1534 error_text
= "Exception at database"
1535 elif isinstance(e
, KeyError):
1536 error_text
= "KeyError exception "
1537 e
.http_code
= HTTP_Internal_Server_Error
1539 error_text
= "Exception at VIM"
1540 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1541 #logger.error("start_scenario %s", error_text)
1542 raise NfvoException(error_text
, e
.http_code
)
1545 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
1546 #check valid tenant_id
1547 check_tenant(mydb
, tenant_id
)
1550 if tenant_id
!= "any":
1551 where_or
["tenant_id"] = tenant_id
1552 where_or
["public"] = True
1553 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1555 vnf_id
= vnf
["uuid"]
1556 filter_keys
= ('uuid', 'name', 'description', 'public', "tenant_id", "osm_id", "created_at")
1557 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
1558 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
1559 data
={'vnf' : filtered_content
}
1561 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
1562 SELECT
=('vms.uuid as uuid', 'vms.osm_id as osm_id', 'vms.name as name', 'vms.description as description',
1564 WHERE
={'vnfs.uuid': vnf_id
} )
1566 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1567 # change boot_data into boot-data
1569 if vm
.get("boot_data"):
1570 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
1573 data
['vnf']['VNFC'] = content
1574 #TODO: GET all the information from a VNFC and include it in the output.
1577 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
1578 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
1579 WHERE
={'vnfs.uuid': vnf_id
} )
1580 data
['vnf']['nets'] = content
1582 #GET ip-profile for each net
1583 for net
in data
['vnf']['nets']:
1584 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1585 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1586 WHERE
={'net_id': net
["uuid"]} )
1587 if len(ipprofiles
)==1:
1588 net
["ip_profile"] = ipprofiles
[0]
1589 elif len(ipprofiles
)>1:
1590 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
1593 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1595 #GET External Interfaces
1596 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1597 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1598 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1599 WHERE
={'vnfs.uuid': vnf_id
, 'interfaces.external_name<>': None} )
1601 data
['vnf']['external-connections'] = content
1606 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1607 # Check tenant exist
1608 if tenant_id
!= "any":
1609 check_tenant(mydb
, tenant_id
)
1610 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1611 vims
= get_vim(mydb
, tenant_id
)
1615 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1617 if tenant_id
!= "any":
1618 where_or
["tenant_id"] = tenant_id
1619 where_or
["public"] = True
1620 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1621 vnf_id
= vnf
["uuid"]
1623 # "Getting the list of flavors and tenants of the VNF"
1624 flavorList
= get_flavorlist(mydb
, vnf_id
)
1625 if len(flavorList
)==0:
1626 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1628 imageList
= get_imagelist(mydb
, vnf_id
)
1629 if len(imageList
)==0:
1630 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1632 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1634 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1637 for flavor
in flavorList
:
1638 #check if flavor is used by other vnf
1640 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1642 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1644 #flavor not used, must be deleted
1646 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id': flavor
})
1647 for flavor_vim
in c
:
1648 if not flavor_vim
['created']: # skip this flavor because not created by openmano
1652 for vim
in vims
.values():
1653 if vim
["config"]["datacenter_tenant_id"] == flavor_vim
["datacenter_vim_id"]:
1659 myvim
.delete_flavor(flavor_vim
["vim_id"])
1660 except vimconn
.vimconnNotFoundException
:
1661 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"],
1662 flavor_vim
["datacenter_vim_id"] )
1663 except vimconn
.vimconnException
as e
:
1664 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1665 flavor_vim
["vim_id"], flavor_vim
["datacenter_vim_id"], type(e
).__name
__, str(e
))
1666 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"],
1667 flavor_vim
["datacenter_vim_id"]))
1668 # delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1669 mydb
.delete_row_by_id('flavors', flavor
)
1670 except db_base_Exception
as e
:
1671 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1672 undeletedItems
.append("flavor {}".format(flavor
))
1675 for image
in imageList
:
1677 #check if image is used by other vnf
1678 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
1680 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1682 #image not used, must be deleted
1684 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1686 if image_vim
["datacenter_vim_id"] not in vims
: # TODO change to datacenter_tenant_id
1688 if image_vim
['created']=='false': #skip this image because not created by openmano
1690 myvim
=vims
[ image_vim
["datacenter_id"] ]
1692 myvim
.delete_image(image_vim
["vim_id"])
1693 except vimconn
.vimconnNotFoundException
as e
:
1694 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1695 except vimconn
.vimconnException
as e
:
1696 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1697 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1698 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1699 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1700 mydb
.delete_row_by_id('images', image
)
1701 except db_base_Exception
as e
:
1702 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1703 undeletedItems
.append("image %s" % image
)
1705 return vnf_id
+ " " + vnf
["name"]
1707 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1710 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1711 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1715 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
1716 myvim
= vims
.values()[0]
1717 result
,servers
= myvim
.get_hosts_info()
1719 return result
, servers
1720 topology
= {'name':myvim
['name'] , 'servers': servers
}
1721 return result
, topology
1724 def get_hosts(mydb
, nfvo_tenant_id
):
1725 vims
= get_vim(mydb
, nfvo_tenant_id
)
1727 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
1729 #print "nfvo.datacenter_action() error. Several datacenters found"
1730 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1731 myvim
= vims
.values()[0]
1733 hosts
= myvim
.get_hosts()
1734 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1736 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1738 server
={'name':host
['name'], 'vms':[]}
1739 for vm
in host
['instances']:
1740 #get internal name and model
1742 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1743 WHERE
={'vim_vm_id':vm
['id']} )
1745 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1747 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1749 except db_base_Exception
as e
:
1750 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1751 datacenter
['Datacenters'][0]['servers'].append(server
)
1752 #return -400, "en construccion"
1754 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1756 except vimconn
.vimconnException
as e
:
1757 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1760 def new_scenario(mydb
, tenant_id
, topo
):
1762 # result, vims = get_vim(mydb, tenant_id)
1764 # return result, vims
1766 if tenant_id
!= "any":
1767 check_tenant(mydb
, tenant_id
)
1768 if "tenant_id" in topo
:
1769 if topo
["tenant_id"] != tenant_id
:
1770 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1775 #1.1: get VNFs and external_networks (other_nets).
1777 other_nets
={} #external_networks, bridge_networks and data_networkds
1778 nodes
= topo
['topology']['nodes']
1779 for k
in nodes
.keys():
1780 if nodes
[k
]['type'] == 'VNF':
1782 vnfs
[k
]['ifaces'] = {}
1783 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1784 other_nets
[k
] = nodes
[k
]
1785 other_nets
[k
]['external']=True
1786 elif nodes
[k
]['type'] == 'network':
1787 other_nets
[k
] = nodes
[k
]
1788 other_nets
[k
]['external']=False
1791 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1792 for name
,vnf
in vnfs
.items():
1793 where
= {"OR": {"tenant_id": tenant_id
, 'public': "true"}}
1795 error_pos
= "'topology':'nodes':'" + name
+ "'"
1797 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1798 where
['uuid'] = vnf
['vnf_id']
1799 if 'VNF model' in vnf
:
1800 error_text
+= " 'VNF model' " + vnf
['VNF model']
1801 where
['name'] = vnf
['VNF model']
1803 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
1805 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1809 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1811 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1812 vnf
['uuid']=vnf_db
[0]['uuid']
1813 vnf
['description']=vnf_db
[0]['description']
1814 #get external interfaces
1815 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1816 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1817 WHERE
={'vnfs.uuid':vnf
['uuid'], 'external_name<>': None} )
1818 for ext_iface
in ext_ifaces
:
1819 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1821 #1.4 get list of connections
1822 conections
= topo
['topology']['connections']
1823 conections_list
= []
1824 conections_list_name
= []
1825 for k
in conections
.keys():
1826 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1827 ifaces_list
= conections
[k
]['nodes'].items()
1828 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1830 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1831 for k2
in conection_pair_list
:
1834 con_type
= conections
[k
].get("type", "link")
1835 if con_type
!= "link":
1837 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
1838 other_nets
[k
] = {'external': False}
1839 if conections
[k
].get("graph"):
1840 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1841 ifaces_list
.append( (k
, None) )
1844 if con_type
== "external_network":
1845 other_nets
[k
]['external'] = True
1846 if conections
[k
].get("model"):
1847 other_nets
[k
]["model"] = conections
[k
]["model"]
1849 other_nets
[k
]["model"] = k
1850 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1851 other_nets
[k
]["model"] = con_type
1853 conections_list_name
.append(k
)
1854 conections_list
.append(set(ifaces_list
)) #from list to set to operate as a set (this conversion removes elements that are repeated in a list)
1855 #print set(ifaces_list)
1856 #check valid VNF and iface names
1857 for iface
in ifaces_list
:
1858 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1859 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1860 str(k
), iface
[0]), HTTP_Not_Found
)
1861 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1862 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1863 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
1865 #1.5 unify connections from the pair list to a consolidated list
1867 while index
< len(conections_list
):
1869 while index2
< len(conections_list
):
1870 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1871 conections_list
[index
] |
= conections_list
[index2
]
1872 del conections_list
[index2
]
1873 del conections_list_name
[index2
]
1876 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1878 #for k in conections_list:
1883 #1.6 Delete non external nets
1884 # for k in other_nets.keys():
1885 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1886 # for con in conections_list:
1888 # for index in range(0,len(con)):
1889 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1890 # for index in delete_indexes:
1893 #1.7: Check external_ports are present at database table datacenter_nets
1894 for k
,net
in other_nets
.items():
1895 error_pos
= "'topology':'nodes':'" + k
+ "'"
1896 if net
['external']==False:
1897 if 'name' not in net
:
1899 if 'model' not in net
:
1900 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1901 if net
['model']=='bridge_net':
1902 net
['type']='bridge';
1903 elif net
['model']=='dataplane_net':
1906 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1908 #IF we do not want to check that external network exist at datacenter
1913 # if 'net_id' in net:
1914 # error_text += " 'net_id' " + net['net_id']
1915 # WHERE_['uuid'] = net['net_id']
1916 # if 'model' in net:
1917 # error_text += " 'model' " + net['model']
1918 # WHERE_['name'] = net['model']
1919 # if len(WHERE_) == 0:
1920 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1921 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1922 # FROM='datacenter_nets', WHERE=WHERE_ )
1924 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1926 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1927 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1929 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1930 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1931 # other_nets[k].update(net_db[0])
1934 net_nb
=0 #Number of nets
1935 for con
in conections_list
:
1936 #check if this is connected to a external net
1940 for index
in range(0,len(con
)):
1941 #check if this is connected to a external net
1942 for net_key
in other_nets
.keys():
1943 if con
[index
][0]==net_key
:
1944 if other_net_index
>=0:
1945 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1946 #print "nfvo.new_scenario " + error_text
1947 raise NfvoException(error_text
, HTTP_Bad_Request
)
1949 other_net_index
= index
1950 net_target
= net_key
1952 #print "other_net_index", other_net_index
1954 if other_net_index
>=0:
1955 del con
[other_net_index
]
1956 #IF we do not want to check that external network exist at datacenter
1957 if other_nets
[net_target
]['external'] :
1958 if "name" not in other_nets
[net_target
]:
1959 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1960 if other_nets
[net_target
]["type"] == "external_network":
1961 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1962 other_nets
[net_target
]["type"] = "data"
1964 other_nets
[net_target
]["type"] = "bridge"
1966 # if other_nets[net_target]['external'] :
1967 # type_='data' if len(con)>1 else 'ptp' #an external net is connected to a external port, so it is ptp if only one connection is done to this net
1968 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1969 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1970 # print "nfvo.new_scenario " + error_text
1971 # return -HTTP_Bad_Request, error_text
1974 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1977 net_type_bridge
=False
1979 net_target
= "__-__net"+str(net_nb
)
1980 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
1981 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1984 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1985 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1986 if iface_type
=='mgmt' or iface_type
=='bridge':
1987 net_type_bridge
= True
1989 net_type_data
= True
1990 if net_type_bridge
and net_type_data
:
1991 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1992 #print "nfvo.new_scenario " + error_text
1993 raise NfvoException(error_text
, HTTP_Bad_Request
)
1994 elif net_type_bridge
:
1997 type_
='data' if len(con
)>2 else 'ptp'
1998 net_list
[net_target
]['type'] = type_
2001 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
2002 #print "nfvo.new_scenario " + error_text
2004 raise NfvoException(error_text
, HTTP_Bad_Request
)
2006 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
2007 #1.8.1 obtain management net
2008 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
2009 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
2010 #1.8.2 check all interfaces from all vnfs
2012 add_mgmt_net
= False
2013 for vnf
in vnfs
.values():
2014 for iface
in vnf
['ifaces'].values():
2015 if iface
['type']=='mgmt' and 'net_key' not in iface
:
2016 #iface not connected
2017 iface
['net_key'] = 'mgmt'
2019 if add_mgmt_net
and 'mgmt' not in net_list
:
2020 net_list
['mgmt']=mgmt_net
[0]
2021 net_list
['mgmt']['external']=True
2022 net_list
['mgmt']['graph']={'visible':False}
2024 net_list
.update(other_nets
)
2026 #print 'net_list', net_list
2031 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
2032 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
2033 'tenant_id':tenant_id
, 'name':topo
['name'],
2034 'description':topo
.get('description',topo
['name']),
2035 'public': topo
.get('public', False)
2041 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
2042 """ This creates a new scenario for version 0.2 and 0.3"""
2043 scenario
= scenario_dict
["scenario"]
2044 if tenant_id
!= "any":
2045 check_tenant(mydb
, tenant_id
)
2046 if "tenant_id" in scenario
:
2047 if scenario
["tenant_id"] != tenant_id
:
2048 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
2049 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
2050 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
2054 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
2055 for name
,vnf
in scenario
["vnfs"].iteritems():
2056 where
= {"OR": {"tenant_id": tenant_id
, 'public': "true"}}
2058 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
2060 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
2061 where
['uuid'] = vnf
['vnf_id']
2062 if 'vnf_name' in vnf
:
2063 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
2064 where
['name'] = vnf
['vnf_name']
2066 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
2067 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
2070 if len(vnf_db
) == 0:
2071 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
2072 elif len(vnf_db
) > 1:
2073 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
2074 vnf
['uuid'] = vnf_db
[0]['uuid']
2075 vnf
['description'] = vnf_db
[0]['description']
2077 # get external interfaces
2078 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
2079 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
2080 WHERE
={'vnfs.uuid':vnf
['uuid'], 'external_name<>': None} )
2081 for ext_iface
in ext_ifaces
:
2082 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
2083 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
2085 # 2: Insert net_key and ip_address at every vnf interface
2086 for net_name
, net
in scenario
["networks"].items():
2087 net_type_bridge
= False
2088 net_type_data
= False
2089 for iface_dict
in net
["interfaces"]:
2090 if version
== "0.2":
2091 temp_dict
= iface_dict
2093 elif version
== "0.3":
2094 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
2095 ip_address
= iface_dict
.get('ip_address', None)
2096 for vnf
, iface
in temp_dict
.items():
2097 if vnf
not in scenario
["vnfs"]:
2098 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
2100 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2101 raise NfvoException(error_text
, HTTP_Not_Found
)
2102 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
2103 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
2104 .format(net_name
, iface
)
2105 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2106 raise NfvoException(error_text
, HTTP_Bad_Request
)
2107 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
2108 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
2109 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
2110 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2111 raise NfvoException(error_text
, HTTP_Bad_Request
)
2112 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
2113 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
2114 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
2115 if iface_type
== 'mgmt' or iface_type
== 'bridge':
2116 net_type_bridge
= True
2118 net_type_data
= True
2120 if net_type_bridge
and net_type_data
:
2121 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
2123 # logger.debug("nfvo.new_scenario " + error_text)
2124 raise NfvoException(error_text
, HTTP_Bad_Request
)
2125 elif net_type_bridge
:
2128 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
2130 if net
.get("implementation"): # for v0.3
2131 if type_
== "bridge" and net
["implementation"] == "underlay":
2132 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
2133 "'network':'{}'".format(net_name
)
2134 # logger.debug(error_text)
2135 raise NfvoException(error_text
, HTTP_Bad_Request
)
2136 elif type_
!= "bridge" and net
["implementation"] == "overlay":
2137 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
2138 "'network':'{}'".format(net_name
)
2139 # logger.debug(error_text)
2140 raise NfvoException(error_text
, HTTP_Bad_Request
)
2141 net
.pop("implementation")
2142 if "type" in net
and version
== "0.3": # for v0.3
2143 if type_
== "data" and net
["type"] == "e-line":
2144 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
2145 "'e-line' at 'network':'{}'".format(net_name
)
2146 # logger.debug(error_text)
2147 raise NfvoException(error_text
, HTTP_Bad_Request
)
2148 elif type_
== "ptp" and net
["type"] == "e-lan":
2152 net
['name'] = net_name
2153 net
['external'] = net
.get('external', False)
2155 # 3: insert at database
2156 scenario
["nets"] = scenario
["networks"]
2157 scenario
['tenant_id'] = tenant_id
2158 scenario_id
= mydb
.new_scenario(scenario
)
2162 def new_nsd_v3(mydb
, tenant_id
, nsd_descriptor
):
2164 Parses an OSM IM nsd_catalog and insert at DB
2167 :param nsd_descriptor:
2168 :return: The list of created NSD ids
2171 mynsd
= nsd_catalog
.nsd()
2173 pybindJSONDecoder
.load_ietf_json(nsd_descriptor
, None, None, obj
=mynsd
)
2174 except Exception as e
:
2175 raise NfvoException("Error. Invalid NS descriptor format: " + str(e
), HTTP_Bad_Request
)
2179 db_sce_interfaces
= []
2182 db_sce_rsp_hops
= []
2183 db_sce_classifiers
= []
2184 db_sce_classifier_matches
= []
2186 db_ip_profiles_index
= 0
2189 for nsd_yang
in mynsd
.nsd_catalog
.nsd
.itervalues():
2190 nsd
= nsd_yang
.get()
2193 scenario_uuid
= str(uuid4())
2194 uuid_list
.append(scenario_uuid
)
2195 nsd_uuid_list
.append(scenario_uuid
)
2197 "uuid": scenario_uuid
,
2198 "osm_id": get_str(nsd
, "id", 255),
2199 "name": get_str(nsd
, "name", 255),
2200 "description": get_str(nsd
, "description", 255),
2201 "tenant_id": tenant_id
,
2202 "vendor": get_str(nsd
, "vendor", 255),
2203 "short_name": get_str(nsd
, "short-name", 255),
2204 "descriptor": str(nsd_descriptor
)[:60000],
2206 db_scenarios
.append(db_scenario
)
2208 # table sce_vnfs (constituent-vnfd)
2209 vnf_index2scevnf_uuid
= {}
2210 vnf_index2vnf_uuid
= {}
2211 for vnf
in nsd
.get("constituent-vnfd").itervalues():
2212 existing_vnf
= mydb
.get_rows(FROM
="vnfs", WHERE
={'osm_id': str(vnf
["vnfd-id-ref"])[:255],
2213 'tenant_id': tenant_id
})
2214 if not existing_vnf
:
2215 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'constituent-vnfd':'vnfd-id-ref':"
2216 "'{}'. Reference to a non-existing VNFD in the catalog".format(
2217 str(nsd
["id"]), str(vnf
["vnfd-id-ref"])[:255]),
2219 sce_vnf_uuid
= str(uuid4())
2220 uuid_list
.append(sce_vnf_uuid
)
2222 "uuid": sce_vnf_uuid
,
2223 "scenario_id": scenario_uuid
,
2224 "name": existing_vnf
[0]["name"][:200] + "." + get_str(vnf
, "member-vnf-index", 5),
2225 "vnf_id": existing_vnf
[0]["uuid"],
2226 "member_vnf_index": int(vnf
["member-vnf-index"]),
2227 # TODO 'start-by-default': True
2229 vnf_index2scevnf_uuid
[int(vnf
['member-vnf-index'])] = sce_vnf_uuid
2230 vnf_index2vnf_uuid
[int(vnf
['member-vnf-index'])] = existing_vnf
[0]["uuid"]
2231 db_sce_vnfs
.append(db_sce_vnf
)
2233 # table ip_profiles (ip-profiles)
2234 ip_profile_name2db_table_index
= {}
2235 for ip_profile
in nsd
.get("ip-profiles").itervalues():
2237 "ip_version": str(ip_profile
["ip-profile-params"].get("ip-version", "ipv4")),
2238 "subnet_address": str(ip_profile
["ip-profile-params"].get("subnet-address")),
2239 "gateway_address": str(ip_profile
["ip-profile-params"].get("gateway-address")),
2240 "dhcp_enabled": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("enabled", True)),
2241 "dhcp_start_address": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("start-address")),
2242 "dhcp_count": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("count")),
2245 for dns
in ip_profile
["ip-profile-params"]["dns-server"].itervalues():
2246 dns_list
.append(str(dns
.get("address")))
2247 db_ip_profile
["dns_address"] = ";".join(dns_list
)
2248 if ip_profile
["ip-profile-params"].get('security-group'):
2249 db_ip_profile
["security_group"] = ip_profile
["ip-profile-params"]['security-group']
2250 ip_profile_name2db_table_index
[str(ip_profile
["name"])] = db_ip_profiles_index
2251 db_ip_profiles_index
+= 1
2252 db_ip_profiles
.append(db_ip_profile
)
2254 # table sce_nets (internal-vld)
2255 for vld
in nsd
.get("vld").itervalues():
2256 sce_net_uuid
= str(uuid4())
2257 uuid_list
.append(sce_net_uuid
)
2259 "uuid": sce_net_uuid
,
2260 "name": get_str(vld
, "name", 255),
2261 "scenario_id": scenario_uuid
,
2263 "multipoint": not vld
.get("type") == "ELINE",
2265 "description": get_str(vld
, "description", 255),
2267 # guess type of network
2268 if vld
.get("mgmt-network"):
2269 db_sce_net
["type"] = "bridge"
2270 db_sce_net
["external"] = True
2271 elif vld
.get("provider-network").get("overlay-type") == "VLAN":
2272 db_sce_net
["type"] = "data"
2274 # later on it will be fixed to bridge or data depending on the type of interfaces attached to it
2275 db_sce_net
["type"] = None
2276 db_sce_nets
.append(db_sce_net
)
2278 # ip-profile, link db_ip_profile with db_sce_net
2279 if vld
.get("ip-profile-ref"):
2280 ip_profile_name
= vld
.get("ip-profile-ref")
2281 if ip_profile_name
not in ip_profile_name2db_table_index
:
2282 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'ip-profile-ref':'{}'."
2283 " Reference to a non-existing 'ip_profiles'".format(
2284 str(nsd
["id"]), str(vld
["id"]), str(vld
["ip-profile-ref"])),
2286 db_ip_profiles
[ip_profile_name2db_table_index
[ip_profile_name
]]["sce_net_id"] = sce_net_uuid
2288 # table sce_interfaces (vld:vnfd-connection-point-ref)
2289 for iface
in vld
.get("vnfd-connection-point-ref").itervalues():
2290 vnf_index
= int(iface
['member-vnf-index-ref'])
2291 # check correct parameters
2292 if vnf_index
not in vnf_index2vnf_uuid
:
2293 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2294 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2295 "'nsd':'constituent-vnfd'".format(
2296 str(nsd
["id"]), str(vld
["id"]), str(iface
["member-vnf-index-ref"])),
2299 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid', 'i.type as iface_type'),
2300 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2301 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2302 'external_name': get_str(iface
, "vnfd-connection-point-ref",
2304 if not existing_ifaces
:
2305 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2306 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2307 "connection-point name at VNFD '{}'".format(
2308 str(nsd
["id"]), str(vld
["id"]), str(iface
["vnfd-connection-point-ref"]),
2309 str(iface
.get("vnfd-id-ref"))[:255]),
2311 interface_uuid
= existing_ifaces
[0]["uuid"]
2312 if existing_ifaces
[0]["iface_type"] == "data" and not db_sce_net
["type"]:
2313 db_sce_net
["type"] = "data"
2314 sce_interface_uuid
= str(uuid4())
2315 uuid_list
.append(sce_net_uuid
)
2316 iface_ip_address
= None
2317 if iface
.get("ip-address"):
2318 iface_ip_address
= str(iface
.get("ip-address"))
2319 db_sce_interface
= {
2320 "uuid": sce_interface_uuid
,
2321 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2322 "sce_net_id": sce_net_uuid
,
2323 "interface_id": interface_uuid
,
2324 "ip_address": iface_ip_address
,
2326 db_sce_interfaces
.append(db_sce_interface
)
2327 if not db_sce_net
["type"]:
2328 db_sce_net
["type"] = "bridge"
2330 # table sce_vnffgs (vnffgd)
2331 for vnffg
in nsd
.get("vnffgd").itervalues():
2332 sce_vnffg_uuid
= str(uuid4())
2333 uuid_list
.append(sce_vnffg_uuid
)
2335 "uuid": sce_vnffg_uuid
,
2336 "name": get_str(vnffg
, "name", 255),
2337 "scenario_id": scenario_uuid
,
2338 "vendor": get_str(vnffg
, "vendor", 255),
2339 "description": get_str(vld
, "description", 255),
2341 db_sce_vnffgs
.append(db_sce_vnffg
)
2345 for rsp
in vnffg
.get("rsp").itervalues():
2346 sce_rsp_uuid
= str(uuid4())
2347 uuid_list
.append(sce_rsp_uuid
)
2349 "uuid": sce_rsp_uuid
,
2350 "name": get_str(rsp
, "name", 255),
2351 "sce_vnffg_id": sce_vnffg_uuid
,
2352 "id": get_str(rsp
, "id", 255), # only useful to link with classifiers; will be removed later in the code
2354 db_sce_rsps
.append(db_sce_rsp
)
2355 db_sce_rsp_hops
= []
2356 for iface
in rsp
.get("vnfd-connection-point-ref").itervalues():
2357 vnf_index
= int(iface
['member-vnf-index-ref'])
2358 if_order
= int(iface
['order'])
2359 # check correct parameters
2360 if vnf_index
not in vnf_index2vnf_uuid
:
2361 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2362 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2363 "'nsd':'constituent-vnfd'".format(
2364 str(nsd
["id"]), str(rsp
["id"]), str(iface
["member-vnf-index-ref"])),
2367 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2368 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2369 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2370 'external_name': get_str(iface
, "vnfd-connection-point-ref",
2372 if not existing_ifaces
:
2373 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2374 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2375 "connection-point name at VNFD '{}'".format(
2376 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-connection-point-ref"]),
2377 str(iface
.get("vnfd-id-ref"))[:255]),
2379 interface_uuid
= existing_ifaces
[0]["uuid"]
2380 sce_rsp_hop_uuid
= str(uuid4())
2381 uuid_list
.append(sce_rsp_hop_uuid
)
2383 "uuid": sce_rsp_hop_uuid
,
2384 "if_order": if_order
,
2385 "interface_id": interface_uuid
,
2386 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2387 "sce_rsp_id": sce_rsp_uuid
,
2389 db_sce_rsp_hops
.append(db_sce_rsp_hop
)
2391 # deal with classifiers
2392 db_sce_classifiers
= []
2393 for classifier
in vnffg
.get("classifier").itervalues():
2394 sce_classifier_uuid
= str(uuid4())
2395 uuid_list
.append(sce_classifier_uuid
)
2398 vnf_index
= int(classifier
['member-vnf-index-ref'])
2399 if vnf_index
not in vnf_index2vnf_uuid
:
2400 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'classifier[{}]':'vnfd-connection-point"
2401 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2402 "'nsd':'constituent-vnfd'".format(
2403 str(nsd
["id"]), str(classifier
["id"]), str(classifier
["member-vnf-index-ref"])),
2405 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2406 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2407 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2408 'external_name': get_str(classifier
, "vnfd-connection-point-ref",
2410 if not existing_ifaces
:
2411 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2412 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2413 "connection-point name at VNFD '{}'".format(
2414 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-connection-point-ref"]),
2415 str(iface
.get("vnfd-id-ref"))[:255]),
2417 interface_uuid
= existing_ifaces
[0]["uuid"]
2419 db_sce_classifier
= {
2420 "uuid": sce_classifier_uuid
,
2421 "name": get_str(classifier
, "name", 255),
2422 "sce_vnffg_id": sce_vnffg_uuid
,
2423 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2424 "interface_id": interface_uuid
,
2426 rsp_id
= get_str(classifier
, "rsp-id-ref", 255)
2427 rsp
= next((item
for item
in db_sce_rsps
if item
["id"] == rsp_id
), None)
2428 db_sce_classifier
["sce_rsp_id"] = rsp
["uuid"]
2429 db_sce_classifiers
.append(db_sce_classifier
)
2431 db_sce_classifier_matches
= []
2432 for match
in classifier
.get("match-attributes").itervalues():
2433 sce_classifier_match_uuid
= str(uuid4())
2434 uuid_list
.append(sce_classifier_match_uuid
)
2435 db_sce_classifier_match
= {
2436 "uuid": sce_classifier_match_uuid
,
2437 "ip_proto": get_str(match
, "ip-proto", 2),
2438 "source_ip": get_str(match
, "source-ip-address", 16),
2439 "destination_ip": get_str(match
, "destination-ip-address", 16),
2440 "source_port": get_str(match
, "source-port", 5),
2441 "destination_port": get_str(match
, "destination-port", 5),
2442 "sce_classifier_id": sce_classifier_uuid
,
2444 db_sce_classifier_matches
.append(db_sce_classifier_match
)
2447 # remove unneeded id's in sce_rsps
2448 for rsp
in db_sce_rsps
:
2452 {"scenarios": db_scenarios
},
2453 {"sce_nets": db_sce_nets
},
2454 {"ip_profiles": db_ip_profiles
},
2455 {"sce_vnfs": db_sce_vnfs
},
2456 {"sce_interfaces": db_sce_interfaces
},
2457 {"sce_vnffgs": db_sce_vnffgs
},
2458 {"sce_rsps": db_sce_rsps
},
2459 {"sce_rsp_hops": db_sce_rsp_hops
},
2460 {"sce_classifiers": db_sce_classifiers
},
2461 {"sce_classifier_matches": db_sce_classifier_matches
},
2464 logger
.debug("new_nsd_v3 done: %s",
2465 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
2466 mydb
.new_rows(db_tables
, uuid_list
)
2467 return nsd_uuid_list
2468 except NfvoException
:
2470 except Exception as e
:
2471 logger
.error("Exception {}".format(e
))
2472 raise # NfvoException("Exception {}".format(e), HTTP_Bad_Request)
2475 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
2476 data
["uuid"] = scenario_id
2477 data
["tenant_id"] = tenant_id
2478 c
= mydb
.edit_scenario( data
)
2482 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
2483 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2484 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
2485 vims
= {datacenter_id
: myvim
}
2486 myvim_tenant
= myvim
['tenant_id']
2487 datacenter_name
= myvim
['name']
2491 #print "Checking that the scenario_id exists and getting the scenario dictionary"
2492 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
=datacenter_id
)
2493 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
2494 scenarioDict
['datacenter_id'] = datacenter_id
2495 #print '================scenarioDict======================='
2496 #print json.dumps(scenarioDict, indent=4)
2497 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
2499 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
2500 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2502 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
2503 auxNetDict
['scenario'] = {}
2505 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
2506 for sce_net
in scenarioDict
['nets']:
2507 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
2509 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
2510 myNetName
= myNetName
[0:255] #limit length
2511 myNetType
= sce_net
['type']
2513 myNetDict
["name"] = myNetName
2514 myNetDict
["type"] = myNetType
2515 myNetDict
["tenant_id"] = myvim_tenant
2516 myNetIPProfile
= sce_net
.get('ip_profile', None)
2518 #We should use the dictionary as input parameter for new_network
2520 if not sce_net
["external"]:
2521 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2522 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
2523 sce_net
['vim_id'] = network_id
2524 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
2525 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2526 sce_net
["created"] = True
2528 if sce_net
['vim_id'] == None:
2529 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
2530 _
, message
= rollback(mydb
, vims
, rollbackList
)
2531 logger
.error("nfvo.start_scenario: %s", error_text
)
2532 raise NfvoException(error_text
, HTTP_Bad_Request
)
2533 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
2534 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
2536 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
2537 #For each vnf net, we create it and we add it to instanceNetlist.
2539 for sce_vnf
in scenarioDict
['vnfs']:
2540 for net
in sce_vnf
['nets']:
2541 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
2543 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
2544 myNetName
= myNetName
[0:255] #limit length
2545 myNetType
= net
['type']
2547 myNetDict
["name"] = myNetName
2548 myNetDict
["type"] = myNetType
2549 myNetDict
["tenant_id"] = myvim_tenant
2550 myNetIPProfile
= net
.get('ip_profile', None)
2553 #We should use the dictionary as input parameter for new_network
2554 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2555 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
2556 net
['vim_id'] = network_id
2557 if sce_vnf
['uuid'] not in auxNetDict
:
2558 auxNetDict
[sce_vnf
['uuid']] = {}
2559 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
2560 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2561 net
["created"] = True
2563 #print "auxNetDict:"
2564 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2566 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
2567 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2569 for sce_vnf
in scenarioDict
['vnfs']:
2570 vnf_availability_zones
= []
2571 for vm
in sce_vnf
['vms']:
2572 vm_av
= vm
.get('availability_zone')
2573 if vm_av
and vm_av
not in vnf_availability_zones
:
2574 vnf_availability_zones
.append(vm_av
)
2576 # check if there is enough availability zones available at vim level.
2577 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
2578 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
2579 raise NfvoException('No enough availability zones at VIM for this deployment', HTTP_Bad_Request
)
2581 for vm
in sce_vnf
['vms']:
2584 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
2585 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
2586 #myVMDict['description'] = vm['description']
2587 myVMDict
['description'] = myVMDict
['name'][0:99]
2589 myVMDict
['start'] = "no"
2590 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2591 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
2593 #create image at vim in case it not exist
2594 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2595 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
2596 vm
['vim_image_id'] = image_id
2598 #create flavor at vim in case it not exist
2599 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2600 if flavor_dict
['extended']!=None:
2601 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2602 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
2603 vm
['vim_flavor_id'] = flavor_id
2606 myVMDict
['imageRef'] = vm
['vim_image_id']
2607 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2608 myVMDict
['networks'] = []
2609 for iface
in vm
['interfaces']:
2611 if iface
['type']=="data":
2612 netDict
['type'] = iface
['model']
2613 elif "model" in iface
and iface
["model"]!=None:
2614 netDict
['model']=iface
['model']
2615 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2616 #discover type of interface looking at flavor
2617 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2618 for flavor_iface
in numa
.get('interfaces',[]):
2619 if flavor_iface
.get('name') == iface
['internal_name']:
2620 if flavor_iface
['dedicated'] == 'yes':
2621 netDict
['type']="PF" #passthrough
2622 elif flavor_iface
['dedicated'] == 'no':
2623 netDict
['type']="VF" #siov
2624 elif flavor_iface
['dedicated'] == 'yes:sriov':
2625 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2626 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2628 netDict
["use"]=iface
['type']
2629 if netDict
["use"]=="data" and not netDict
.get("type"):
2630 #print "netDict", netDict
2631 #print "iface", iface
2632 e_text
= "Cannot determine the interface type PF or VF of VNF '%s' VM '%s' iface '%s'" %(sce_vnf
['name'], vm
['name'], iface
['internal_name'])
2633 if flavor_dict
.get('extended')==None:
2634 raise NfvoException(e_text
+ "After database migration some information is not available. \
2635 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
2637 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
2638 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2639 netDict
["type"]="virtual"
2640 if "vpci" in iface
and iface
["vpci"] is not None:
2641 netDict
['vpci'] = iface
['vpci']
2642 if "mac" in iface
and iface
["mac"] is not None:
2643 netDict
['mac_address'] = iface
['mac']
2644 if "port-security" in iface
and iface
["port-security"] is not None:
2645 netDict
['port_security'] = iface
['port-security']
2646 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2647 netDict
['floating_ip'] = iface
['floating-ip']
2648 netDict
['name'] = iface
['internal_name']
2649 if iface
['net_id'] is None:
2650 for vnf_iface
in sce_vnf
["interfaces"]:
2653 if vnf_iface
['interface_id']==iface
['uuid']:
2654 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
2657 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2658 #skip bridge ifaces not connected to any net
2659 #if 'net_id' not in netDict or netDict['net_id']==None:
2661 myVMDict
['networks'].append(netDict
)
2662 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2663 #print myVMDict['name']
2664 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2665 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2666 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2668 if 'availability_zone' in myVMDict
:
2669 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
2673 vm_id
, _
= myvim
.new_vminstance(myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2674 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2675 availability_zone_index
=av_index
,
2676 availability_zone_list
=vnf_availability_zones
)
2677 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
2678 vm
['vim_id'] = vm_id
2679 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2680 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2681 for net
in myVMDict
['networks']:
2683 for iface
in vm
['interfaces']:
2684 if net
["name"]==iface
["internal_name"]:
2685 iface
["vim_id"]=net
["vim_id"]
2688 logger
.debug("start scenario Deployment done")
2689 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2690 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
2691 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
2692 return mydb
.get_instance_scenario(instance_id
)
2694 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
2695 _
, message
= rollback(mydb
, vims
, rollbackList
)
2696 if isinstance(e
, db_base_Exception
):
2697 error_text
= "Exception at database"
2699 error_text
= "Exception at VIM"
2700 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2701 #logger.error("start_scenario %s", error_text)
2702 raise NfvoException(error_text
, e
.http_code
)
2704 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
2705 """ join the cloud config information into cloud_config_preserve.
2706 In case of conflict cloud_config_preserve preserves
2709 if not cloud_config_preserve
and not cloud_config
:
2712 new_cloud_config
= {"key-pairs":[], "users":[]}
2714 if cloud_config_preserve
:
2715 for key
in cloud_config_preserve
.get("key-pairs", () ):
2716 if key
not in new_cloud_config
["key-pairs"]:
2717 new_cloud_config
["key-pairs"].append(key
)
2719 for key
in cloud_config
.get("key-pairs", () ):
2720 if key
not in new_cloud_config
["key-pairs"]:
2721 new_cloud_config
["key-pairs"].append(key
)
2722 if not new_cloud_config
["key-pairs"]:
2723 del new_cloud_config
["key-pairs"]
2727 new_cloud_config
["users"] += cloud_config
.get("users", () )
2728 if cloud_config_preserve
:
2729 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
2730 index_to_delete
= []
2731 users
= new_cloud_config
.get("users", [])
2732 for index0
in range(0,len(users
)):
2733 if index0
in index_to_delete
:
2735 for index1
in range(index0
+1,len(users
)):
2736 if index1
in index_to_delete
:
2738 if users
[index0
]["name"] == users
[index1
]["name"]:
2739 index_to_delete
.append(index1
)
2740 for key
in users
[index1
].get("key-pairs",()):
2741 if "key-pairs" not in users
[index0
]:
2742 users
[index0
]["key-pairs"] = [key
]
2743 elif key
not in users
[index0
]["key-pairs"]:
2744 users
[index0
]["key-pairs"].append(key
)
2745 index_to_delete
.sort(reverse
=True)
2746 for index
in index_to_delete
:
2748 if not new_cloud_config
["users"]:
2749 del new_cloud_config
["users"]
2752 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
2753 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
2754 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
2755 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
2758 new_cloud_config
["user-data"] = []
2759 if cloud_config
and cloud_config
.get("user-data"):
2760 if isinstance(cloud_config
["user-data"], list):
2761 new_cloud_config
["user-data"] += cloud_config
["user-data"]
2763 new_cloud_config
["user-data"].append(cloud_config
["user-data"])
2764 if cloud_config_preserve
and cloud_config_preserve
.get("user-data"):
2765 if isinstance(cloud_config_preserve
["user-data"], list):
2766 new_cloud_config
["user-data"] += cloud_config_preserve
["user-data"]
2768 new_cloud_config
["user-data"].append(cloud_config_preserve
["user-data"])
2769 if not new_cloud_config
["user-data"]:
2770 del new_cloud_config
["user-data"]
2773 new_cloud_config
["config-files"] = []
2774 if cloud_config
and cloud_config
.get("config-files") != None:
2775 new_cloud_config
["config-files"] += cloud_config
["config-files"]
2776 if cloud_config_preserve
:
2777 for file in cloud_config_preserve
.get("config-files", ()):
2778 for index
in range(0, len(new_cloud_config
["config-files"])):
2779 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
2780 new_cloud_config
["config-files"][index
] = file
2783 new_cloud_config
["config-files"].append(file)
2784 if not new_cloud_config
["config-files"]:
2785 del new_cloud_config
["config-files"]
2786 return new_cloud_config
2789 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
2790 datacenter_id
= None
2791 datacenter_name
= None
2794 if datacenter_tenant_id
:
2795 thread_id
= datacenter_tenant_id
2796 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
2798 where_
={"td.nfvo_tenant_id": tenant_id
}
2799 if datacenter_id_name
:
2800 if utils
.check_valid_uuid(datacenter_id_name
):
2801 datacenter_id
= datacenter_id_name
2802 where_
["dt.datacenter_id"] = datacenter_id
2804 datacenter_name
= datacenter_id_name
2805 where_
["d.name"] = datacenter_name
2806 if datacenter_tenant_id
:
2807 where_
["dt.uuid"] = datacenter_tenant_id
2808 datacenters
= mydb
.get_rows(
2809 SELECT
=("dt.uuid as datacenter_tenant_id",),
2810 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
2811 "join datacenters as d on d.uuid=dt.datacenter_id",
2813 if len(datacenters
) > 1:
2814 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2816 thread_id
= datacenters
[0]["datacenter_tenant_id"]
2817 thread
= vim_threads
["running"].get(thread_id
)
2819 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
2820 return thread_id
, thread
2821 except db_base_Exception
as e
:
2822 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
2825 def get_datacenter_uuid(mydb
, tenant_id
, datacenter_id_name
):
2827 if utils
.check_valid_uuid(datacenter_id_name
):
2828 WHERE_dict
['d.uuid'] = datacenter_id_name
2830 WHERE_dict
['d.name'] = datacenter_id_name
2833 WHERE_dict
['nfvo_tenant_id'] = tenant_id
2834 from_
= "tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join datacenter_tenants as" \
2835 " dt on td.datacenter_tenant_id=dt.uuid"
2837 from_
= 'datacenters as d'
2838 vimaccounts
= mydb
.get_rows(FROM
=from_
, SELECT
=("d.uuid as uuid",), WHERE
=WHERE_dict
)
2839 if len(vimaccounts
) == 0:
2840 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
2841 elif len(vimaccounts
)>1:
2842 #print "nfvo.datacenter_action() error. Several datacenters found"
2843 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2844 return vimaccounts
[0]["uuid"]
2847 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
2848 datacenter_id
= None
2849 datacenter_name
= None
2850 if datacenter_id_name
:
2851 if utils
.check_valid_uuid(datacenter_id_name
):
2852 datacenter_id
= datacenter_id_name
2854 datacenter_name
= datacenter_id_name
2855 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
2857 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
2859 #print "nfvo.datacenter_action() error. Several datacenters found"
2860 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2861 return vims
.keys()[0], vims
.values()[0]
2865 '''Takes dict d and updates it with the values in dict u.'''
2866 '''It merges all depth levels'''
2867 for k
, v
in u
.iteritems():
2868 if isinstance(v
, collections
.Mapping
):
2869 r
= update(d
.get(k
, {}), v
)
2875 def create_instance(mydb
, tenant_id
, instance_dict
):
2876 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2877 # logger.debug("Creating instance...")
2878 scenario
= instance_dict
["scenario"]
2880 # find main datacenter
2882 myvim_threads_id
= {}
2883 datacenter
= instance_dict
.get("datacenter")
2884 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2885 myvims
[default_datacenter_id
] = vim
2886 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
2887 tenant
= mydb
.get_rows_by_id('nfvo_tenants', tenant_id
)
2888 # myvim_tenant = myvim['tenant_id']
2891 # print "Checking that the scenario exists and getting the scenario dictionary"
2892 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, datacenter_vim_id
=myvim_threads_id
[default_datacenter_id
],
2893 datacenter_id
=default_datacenter_id
)
2895 # logger.debug(">>>>>> Dictionaries before merging")
2896 # logger.debug(">>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
2897 # logger.debug(">>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
2899 db_instance_vnfs
= []
2900 db_instance_vms
= []
2901 db_instance_interfaces
= []
2902 db_instance_sfis
= []
2903 db_instance_sfs
= []
2904 db_instance_classifications
= []
2905 db_instance_sfps
= []
2910 instance_name
= instance_dict
["name"]
2911 instance_uuid
= str(uuid4())
2912 uuid_list
.append(instance_uuid
)
2913 db_instance_scenario
= {
2914 "uuid": instance_uuid
,
2915 "name": instance_name
,
2916 "tenant_id": tenant_id
,
2917 "scenario_id": scenarioDict
['uuid'],
2918 "datacenter_id": default_datacenter_id
,
2919 # filled bellow 'datacenter_tenant_id'
2920 "description": instance_dict
.get("description"),
2922 if scenarioDict
.get("cloud-config"):
2923 db_instance_scenario
["cloud_config"] = yaml
.safe_dump(scenarioDict
["cloud-config"],
2924 default_flow_style
=True, width
=256)
2925 instance_action_id
= get_task_id()
2926 db_instance_action
= {
2927 "uuid": instance_action_id
, # same uuid for the instance and the action on create
2928 "tenant_id": tenant_id
,
2929 "instance_id": instance_uuid
,
2930 "description": "CREATE",
2933 # Auxiliary dictionaries from x to y
2934 vnf_net2instance
= {}
2935 sce_net2instance
= {}
2936 net2task_id
= {'scenario': {}}
2938 # logger.debug("Creating instance from scenario-dict:\n%s",
2939 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
2941 # 0 check correct parameters
2942 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).iteritems():
2944 for scenario_net
in scenarioDict
['nets']:
2945 if net_name
== scenario_net
["name"]:
2949 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
),
2951 if "sites" not in net_instance_desc
:
2952 net_instance_desc
["sites"] = [ {} ]
2953 site_without_datacenter_field
= False
2954 for site
in net_instance_desc
["sites"]:
2955 if site
.get("datacenter"):
2956 site
["datacenter"] = get_datacenter_uuid(mydb
, tenant_id
, site
["datacenter"])
2957 if site
["datacenter"] not in myvims
:
2958 # Add this datacenter to myvims
2959 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
2961 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
2962 site
["datacenter"] = d
# change name to id
2964 if site_without_datacenter_field
:
2965 raise NfvoException("Found more than one entries without datacenter field at "
2966 "instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
2967 site_without_datacenter_field
= True
2968 site
["datacenter"] = default_datacenter_id
# change name to id
2970 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
2972 for scenario_vnf
in scenarioDict
['vnfs']:
2973 if vnf_name
== scenario_vnf
['name']:
2977 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
2978 if "datacenter" in vnf_instance_desc
:
2979 # Add this datacenter to myvims
2980 vnf_instance_desc
["datacenter"] = get_datacenter_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2981 if vnf_instance_desc
["datacenter"] not in myvims
:
2982 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2984 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2985 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
2987 # 0.1 parse cloud-config parameters
2988 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
2990 # 0.2 merge instance information into scenario
2991 # Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
2992 # However, this is not possible yet.
2993 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).iteritems():
2994 for scenario_net
in scenarioDict
['nets']:
2995 if net_name
== scenario_net
["name"]:
2996 if 'ip-profile' in net_instance_desc
:
2997 # translate from input format to database format
2998 ipprofile_in
= net_instance_desc
['ip-profile']
3000 ipprofile_db
['subnet_address'] = ipprofile_in
.get('subnet-address')
3001 ipprofile_db
['ip_version'] = ipprofile_in
.get('ip-version', 'IPv4')
3002 ipprofile_db
['gateway_address'] = ipprofile_in
.get('gateway-address')
3003 ipprofile_db
['dns_address'] = ipprofile_in
.get('dns-address')
3004 if isinstance(ipprofile_db
['dns_address'], (list, tuple)):
3005 ipprofile_db
['dns_address'] = ";".join(ipprofile_db
['dns_address'])
3006 if 'dhcp' in ipprofile_in
:
3007 ipprofile_db
['dhcp_start_address'] = ipprofile_in
['dhcp'].get('start-address')
3008 ipprofile_db
['dhcp_enabled'] = ipprofile_in
['dhcp'].get('enabled', True)
3009 ipprofile_db
['dhcp_count'] = ipprofile_in
['dhcp'].get('count' )
3010 if 'ip_profile' not in scenario_net
:
3011 scenario_net
['ip_profile'] = ipprofile_db
3013 update(scenario_net
['ip_profile'], ipprofile_db
)
3014 for interface
in net_instance_desc
.get('interfaces', ()):
3015 if 'ip_address' in interface
:
3016 for vnf
in scenarioDict
['vnfs']:
3017 if interface
['vnf'] == vnf
['name']:
3018 for vnf_interface
in vnf
['interfaces']:
3019 if interface
['vnf_interface'] == vnf_interface
['external_name']:
3020 vnf_interface
['ip_address'] = interface
['ip_address']
3022 # logger.debug(">>>>>>>> Merged dictionary")
3023 # logger.debug("Creating instance scenario-dict MERGED:\n%s",
3024 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
3026 # 1. Creating new nets (sce_nets) in the VIM"
3027 db_instance_nets
= []
3028 for sce_net
in scenarioDict
['nets']:
3029 descriptor_net
= instance_dict
.get("networks", {}).get(sce_net
["name"], {})
3030 net_name
= descriptor_net
.get("vim-network-name")
3031 sce_net2instance
[sce_net
['uuid']] = {}
3032 net2task_id
['scenario'][sce_net
['uuid']] = {}
3034 sites
= descriptor_net
.get("sites", [ {} ])
3036 if site
.get("datacenter"):
3037 vim
= myvims
[ site
["datacenter"] ]
3038 datacenter_id
= site
["datacenter"]
3039 myvim_thread_id
= myvim_threads_id
[ site
["datacenter"] ]
3041 vim
= myvims
[ default_datacenter_id
]
3042 datacenter_id
= default_datacenter_id
3043 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
3044 net_type
= sce_net
['type']
3045 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} # 'shared': True
3048 if sce_net
["external"]:
3049 net_name
= sce_net
["name"]
3051 net_name
= "{}.{}".format(instance_name
, sce_net
["name"])
3052 net_name
= net_name
[:255] # limit length
3054 if "netmap-use" in site
or "netmap-create" in site
:
3055 create_network
= False
3056 lookfor_network
= False
3057 if "netmap-use" in site
:
3058 lookfor_network
= True
3059 if utils
.check_valid_uuid(site
["netmap-use"]):
3060 filter_text
= "scenario id '%s'" % site
["netmap-use"]
3061 lookfor_filter
["id"] = site
["netmap-use"]
3063 filter_text
= "scenario name '%s'" % site
["netmap-use"]
3064 lookfor_filter
["name"] = site
["netmap-use"]
3065 if "netmap-create" in site
:
3066 create_network
= True
3067 net_vim_name
= net_name
3068 if site
["netmap-create"]:
3069 net_vim_name
= site
["netmap-create"]
3070 elif sce_net
["external"]:
3071 if sce_net
['vim_id'] != None:
3072 # there is a netmap at datacenter_nets database # TODO REVISE!!!!
3073 create_network
= False
3074 lookfor_network
= True
3075 lookfor_filter
["id"] = sce_net
['vim_id']
3076 filter_text
= "vim_id '{}' datacenter_netmap name '{}'. Try to reload vims with "\
3077 "datacenter-net-update".format(sce_net
['vim_id'], sce_net
["name"])
3078 # look for network at datacenter and return error
3080 # There is not a netmap, look at datacenter for a net with this name and create if not found
3081 create_network
= True
3082 lookfor_network
= True
3083 lookfor_filter
["name"] = sce_net
["name"]
3084 net_vim_name
= sce_net
["name"]
3085 filter_text
= "scenario name '%s'" % sce_net
["name"]
3087 net_vim_name
= net_name
3088 create_network
= True
3089 lookfor_network
= False
3093 task_action
= "CREATE"
3094 task_extra
["params"] = (net_vim_name
, net_type
, sce_net
.get('ip_profile', None))
3096 task_extra
["find"] = (lookfor_filter
,)
3097 elif lookfor_network
:
3098 task_action
= "FIND"
3099 task_extra
["params"] = (lookfor_filter
,)
3101 # fill database content
3102 net_uuid
= str(uuid4())
3103 uuid_list
.append(net_uuid
)
3104 sce_net2instance
[sce_net
['uuid']][datacenter_id
] = net_uuid
3108 "instance_scenario_id": instance_uuid
,
3109 "sce_net_id": sce_net
["uuid"],
3110 "created": create_network
,
3111 'datacenter_id': datacenter_id
,
3112 'datacenter_tenant_id': myvim_thread_id
,
3113 'status': 'BUILD' if create_network
else "ACTIVE"
3115 db_instance_nets
.append(db_net
)
3117 "instance_action_id": instance_action_id
,
3118 "status": "SCHEDULED",
3119 "task_index": task_index
,
3120 "datacenter_vim_id": myvim_thread_id
,
3121 "action": task_action
,
3122 "item": "instance_nets",
3123 "item_id": net_uuid
,
3124 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
3126 net2task_id
['scenario'][sce_net
['uuid']][datacenter_id
] = task_index
3128 db_vim_actions
.append(db_vim_action
)
3130 if 'ip_profile' in sce_net
:
3132 'instance_net_id': net_uuid
,
3133 'ip_version': sce_net
['ip_profile']['ip_version'],
3134 'subnet_address': sce_net
['ip_profile']['subnet_address'],
3135 'gateway_address': sce_net
['ip_profile']['gateway_address'],
3136 'dns_address': sce_net
['ip_profile']['dns_address'],
3137 'dhcp_enabled': sce_net
['ip_profile']['dhcp_enabled'],
3138 'dhcp_start_address': sce_net
['ip_profile']['dhcp_start_address'],
3139 'dhcp_count': sce_net
['ip_profile']['dhcp_count'],
3141 db_ip_profiles
.append(db_ip_profile
)
3143 # 2. Creating new nets (vnf internal nets) in the VIM"
3144 # For each vnf net, we create it and we add it to instanceNetlist.
3145 for sce_vnf
in scenarioDict
['vnfs']:
3146 for net
in sce_vnf
['nets']:
3147 if sce_vnf
.get("datacenter"):
3148 datacenter_id
= sce_vnf
["datacenter"]
3149 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
3151 datacenter_id
= default_datacenter_id
3152 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
3153 descriptor_net
= instance_dict
.get("vnfs", {}).get(sce_vnf
["name"], {})
3154 net_name
= descriptor_net
.get("name")
3156 net_name
= "{}.{}".format(instance_name
, net
["name"])
3157 net_name
= net_name
[:255] # limit length
3158 net_type
= net
['type']
3160 if sce_vnf
['uuid'] not in vnf_net2instance
:
3161 vnf_net2instance
[sce_vnf
['uuid']] = {}
3162 if sce_vnf
['uuid'] not in net2task_id
:
3163 net2task_id
[sce_vnf
['uuid']] = {}
3164 net2task_id
[sce_vnf
['uuid']][net
['uuid']] = task_index
3166 # fill database content
3167 net_uuid
= str(uuid4())
3168 uuid_list
.append(net_uuid
)
3169 vnf_net2instance
[sce_vnf
['uuid']][net
['uuid']] = net_uuid
3173 "instance_scenario_id": instance_uuid
,
3174 "net_id": net
["uuid"],
3176 'datacenter_id': datacenter_id
,
3177 'datacenter_tenant_id': myvim_thread_id
,
3179 db_instance_nets
.append(db_net
)
3182 "instance_action_id": instance_action_id
,
3183 "task_index": task_index
,
3184 "datacenter_vim_id": myvim_thread_id
,
3185 "status": "SCHEDULED",
3187 "item": "instance_nets",
3188 "item_id": net_uuid
,
3189 "extra": yaml
.safe_dump({"params": (net_name
, net_type
, net
.get('ip_profile',None))},
3190 default_flow_style
=True, width
=256)
3193 db_vim_actions
.append(db_vim_action
)
3195 if 'ip_profile' in net
:
3197 'instance_net_id': net_uuid
,
3198 'ip_version': net
['ip_profile']['ip_version'],
3199 'subnet_address': net
['ip_profile']['subnet_address'],
3200 'gateway_address': net
['ip_profile']['gateway_address'],
3201 'dns_address': net
['ip_profile']['dns_address'],
3202 'dhcp_enabled': net
['ip_profile']['dhcp_enabled'],
3203 'dhcp_start_address': net
['ip_profile']['dhcp_start_address'],
3204 'dhcp_count': net
['ip_profile']['dhcp_count'],
3206 db_ip_profiles
.append(db_ip_profile
)
3208 # print "vnf_net2instance:"
3209 # print yaml.safe_dump(vnf_net2instance, indent=4, default_flow_style=False)
3211 # 3. Creating new vm instances in the VIM
3212 # myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
3213 sce_vnf_list
= sorted(scenarioDict
['vnfs'], key
=lambda k
: k
['name'])
3214 for sce_vnf
in sce_vnf_list
:
3216 if sce_vnf
.get('mgmt_access'):
3217 ssh_access
= sce_vnf
['mgmt_access'].get('config-access', {}).get('ssh-access')
3218 vnf_availability_zones
= []
3219 for vm
in sce_vnf
['vms']:
3220 vm_av
= vm
.get('availability_zone')
3221 if vm_av
and vm_av
not in vnf_availability_zones
:
3222 vnf_availability_zones
.append(vm_av
)
3224 # check if there is enough availability zones available at vim level.
3225 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
3226 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
3227 raise NfvoException('No enough availability zones at VIM for this deployment', HTTP_Bad_Request
)
3229 if sce_vnf
.get("datacenter"):
3230 vim
= myvims
[ sce_vnf
["datacenter"] ]
3231 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"] ]
3232 datacenter_id
= sce_vnf
["datacenter"]
3234 vim
= myvims
[ default_datacenter_id
]
3235 myvim_thread_id
= myvim_threads_id
[ default_datacenter_id
]
3236 datacenter_id
= default_datacenter_id
3237 sce_vnf
["datacenter_id"] = datacenter_id
3240 vnf_uuid
= str(uuid4())
3241 uuid_list
.append(vnf_uuid
)
3244 'instance_scenario_id': instance_uuid
,
3245 'vnf_id': sce_vnf
['vnf_id'],
3246 'sce_vnf_id': sce_vnf
['uuid'],
3247 'datacenter_id': datacenter_id
,
3248 'datacenter_tenant_id': myvim_thread_id
,
3250 db_instance_vnfs
.append(db_instance_vnf
)
3252 for vm
in sce_vnf
['vms']:
3254 myVMDict
['name'] = "{}.{}.{}".format(instance_name
[:64], sce_vnf
['name'][:64], vm
["name"][:64])
3255 myVMDict
['description'] = myVMDict
['name'][0:99]
3257 # myVMDict['start'] = "no"
3258 myVMDict
['name'] = myVMDict
['name'][0:255] # limit name length
3259 #create image at vim in case it not exist
3260 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
3261 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
3262 vm
['vim_image_id'] = image_id
3264 # create flavor at vim in case it not exist
3265 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
3266 if flavor_dict
['extended']!=None:
3267 flavor_dict
['extended'] = yaml
.load(flavor_dict
['extended'])
3268 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
3270 # Obtain information for additional disks
3271 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',), WHERE
={'vim_id': flavor_id
})
3272 if not extended_flavor_dict
:
3273 raise NfvoException("flavor '{}' not found".format(flavor_id
), HTTP_Not_Found
)
3276 # extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
3277 myVMDict
['disks'] = None
3278 extended_info
= extended_flavor_dict
[0]['extended']
3279 if extended_info
!= None:
3280 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
3281 if 'disks' in extended_flavor_dict_yaml
:
3282 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
3284 vm
['vim_flavor_id'] = flavor_id
3285 myVMDict
['imageRef'] = vm
['vim_image_id']
3286 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
3287 myVMDict
['availability_zone'] = vm
.get('availability_zone')
3288 myVMDict
['networks'] = []
3289 task_depends_on
= []
3290 # TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
3292 for iface
in vm
['interfaces']:
3294 if iface
['type'] == "data":
3295 netDict
['type'] = iface
['model']
3296 elif "model" in iface
and iface
["model"] != None:
3297 netDict
['model'] = iface
['model']
3298 # TODO in future, remove this because mac_address will not be set, and the type of PV,VF
3299 # is obtained from iterface table model
3300 # discover type of interface looking at flavor
3301 for numa
in flavor_dict
.get('extended', {}).get('numas', []):
3302 for flavor_iface
in numa
.get('interfaces', []):
3303 if flavor_iface
.get('name') == iface
['internal_name']:
3304 if flavor_iface
['dedicated'] == 'yes':
3305 netDict
['type'] = "PF" # passthrough
3306 elif flavor_iface
['dedicated'] == 'no':
3307 netDict
['type'] = "VF" # siov
3308 elif flavor_iface
['dedicated'] == 'yes:sriov':
3309 netDict
['type'] = "VFnotShared" # sriov but only one sriov on the PF
3310 netDict
["mac_address"] = flavor_iface
.get("mac_address")
3312 netDict
["use"]=iface
['type']
3313 if netDict
["use"] == "data" and not netDict
.get("type"):
3314 # print "netDict", netDict
3315 # print "iface", iface
3316 e_text
= "Cannot determine the interface type PF or VF of VNF '{}' VM '{}' iface '{}'".fromat(
3317 sce_vnf
['name'], vm
['name'], iface
['internal_name'])
3318 if flavor_dict
.get('extended') == None:
3319 raise NfvoException(e_text
+ "After database migration some information is not available. \
3320 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
3322 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
3323 if netDict
["use"] == "mgmt" or netDict
["use"] == "bridge":
3324 netDict
["type"]="virtual"
3325 if iface
.get("vpci"):
3326 netDict
['vpci'] = iface
['vpci']
3327 if iface
.get("mac"):
3328 netDict
['mac_address'] = iface
['mac']
3329 if iface
.get("ip_address"):
3330 netDict
['ip_address'] = iface
['ip_address']
3331 if iface
.get("port-security") is not None:
3332 netDict
['port_security'] = iface
['port-security']
3333 if iface
.get("floating-ip") is not None:
3334 netDict
['floating_ip'] = iface
['floating-ip']
3335 netDict
['name'] = iface
['internal_name']
3336 if iface
['net_id'] is None:
3337 for vnf_iface
in sce_vnf
["interfaces"]:
3340 if vnf_iface
['interface_id'] == iface
['uuid']:
3341 netDict
['net_id'] = "TASK-{}".format(net2task_id
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
])
3342 instance_net_id
= sce_net2instance
[ vnf_iface
['sce_net_id'] ][datacenter_id
]
3343 task_depends_on
.append(net2task_id
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
])
3346 netDict
['net_id'] = "TASK-{}".format(net2task_id
[ sce_vnf
['uuid'] ][ iface
['net_id'] ])
3347 instance_net_id
= vnf_net2instance
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
3348 task_depends_on
.append(net2task_id
[sce_vnf
['uuid'] ][ iface
['net_id']])
3349 # skip bridge ifaces not connected to any net
3350 if 'net_id' not in netDict
or netDict
['net_id']==None:
3352 myVMDict
['networks'].append(netDict
)
3355 # 'instance_vm_id': instance_vm_uuid,
3356 "instance_net_id": instance_net_id
,
3357 'interface_id': iface
['uuid'],
3358 # 'vim_interface_id': ,
3359 'type': 'external' if iface
['external_name'] is not None else 'internal',
3360 'ip_address': iface
.get('ip_address'),
3361 'mac_address': iface
.get('mac'),
3362 'floating_ip': int(iface
.get('floating-ip', False)),
3363 'port_security': int(iface
.get('port-security', True))
3365 db_vm_ifaces
.append(db_vm_iface
)
3366 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3367 # print myVMDict['name']
3368 # print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
3369 # print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
3370 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3372 # We add the RO key to cloud_config if vnf will need ssh access
3373 cloud_config_vm
= cloud_config
3374 if ssh_access
and ssh_access
['required'] and ssh_access
['default-user'] and tenant
[0].get('RO_pub_key'):
3375 RO_key
= {"key-pairs": [tenant
[0]['RO_pub_key']]}
3376 cloud_config_vm
= unify_cloud_config(cloud_config_vm
, RO_key
)
3377 if vm
.get("boot_data"):
3378 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config_vm
)
3380 if myVMDict
.get('availability_zone'):
3381 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
3384 for vm_index
in range(0, vm
.get('count', 1)):
3386 if vm
.get('count', 1) > 1:
3387 vm_index_name
+= "." + chr(97 + vm_index
)
3388 task_params
= (myVMDict
['name']+vm_index_name
, myVMDict
['description'], myVMDict
.get('start', None),
3389 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'], cloud_config_vm
,
3390 myVMDict
['disks'], av_index
, vnf_availability_zones
)
3391 # put interface uuid back to scenario[vnfs][vms[[interfaces]
3392 for net
in myVMDict
['networks']:
3394 for iface
in vm
['interfaces']:
3395 if net
["name"] == iface
["internal_name"]:
3396 iface
["vim_id"] = net
["vim_id"]
3398 vm_uuid
= str(uuid4())
3399 uuid_list
.append(vm_uuid
)
3402 'instance_vnf_id': vnf_uuid
,
3403 #TODO delete "vim_vm_id": vm_id,
3404 "vm_id": vm
["uuid"],
3407 db_instance_vms
.append(db_vm
)
3410 for db_vm_iface
in db_vm_ifaces
:
3411 iface_uuid
= str(uuid4())
3412 uuid_list
.append(iface_uuid
)
3413 db_vm_iface_instance
= {
3415 "instance_vm_id": vm_uuid
3417 db_vm_iface_instance
.update(db_vm_iface
)
3418 if db_vm_iface_instance
.get("ip_address"): # increment ip_address
3419 ip
= db_vm_iface_instance
.get("ip_address")
3424 ip
= ip
[i
:] + str(int(ip
[:i
]) +1)
3425 db_vm_iface_instance
["ip_address"] = ip
3427 db_vm_iface_instance
["ip_address"] = None
3428 db_instance_interfaces
.append(db_vm_iface_instance
)
3429 myVMDict
['networks'][iface_index
]["uuid"] = iface_uuid
3433 "instance_action_id": instance_action_id
,
3434 "task_index": task_index
,
3435 "datacenter_vim_id": myvim_thread_id
,
3437 "status": "SCHEDULED",
3438 "item": "instance_vms",
3440 "extra": yaml
.safe_dump({"params": task_params
, "depends_on": task_depends_on
},
3441 default_flow_style
=True, width
=256)
3444 db_vim_actions
.append(db_vim_action
)
3446 task_depends_on
= []
3447 for vnffg
in scenarioDict
['vnffgs']:
3448 for rsp
in vnffg
['rsps']:
3450 for cp
in rsp
['connection_points']:
3451 count
= mydb
.get_rows(
3452 SELECT
=('vms.count'),
3453 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_rsp_hops as h on interfaces.uuid=h.interface_id",
3454 WHERE
={'h.uuid': cp
['uuid']})[0]['count']
3455 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == cp
['sce_vnf_id']), None)
3456 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3458 for instance_vm
in instance_vms
:
3459 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3461 dependencies
.append(action
['task_index'])
3462 # TODO: throw exception if count != len(instance_vms)
3463 # TODO: and action shouldn't ever be None
3465 for i
in range(count
):
3467 sfi_uuid
= str(uuid4())
3468 uuid_list
.append(sfi_uuid
)
3471 "instance_scenario_id": instance_uuid
,
3472 'sce_rsp_hop_id': cp
['uuid'],
3473 'datacenter_id': datacenter_id
,
3474 'datacenter_tenant_id': myvim_thread_id
,
3475 "vim_sfi_id": None, # vim thread will populate
3477 db_instance_sfis
.append(db_sfi
)
3479 "instance_action_id": instance_action_id
,
3480 "task_index": task_index
,
3481 "datacenter_vim_id": myvim_thread_id
,
3483 "status": "SCHEDULED",
3484 "item": "instance_sfis",
3485 "item_id": sfi_uuid
,
3486 "extra": yaml
.safe_dump({"params": "", "depends_on": [dependencies
[i
]]},
3487 default_flow_style
=True, width
=256)
3489 sfis_created
.append(task_index
)
3491 db_vim_actions
.append(db_vim_action
)
3493 sf_uuid
= str(uuid4())
3494 uuid_list
.append(sf_uuid
)
3497 "instance_scenario_id": instance_uuid
,
3498 'sce_rsp_hop_id': cp
['uuid'],
3499 'datacenter_id': datacenter_id
,
3500 'datacenter_tenant_id': myvim_thread_id
,
3501 "vim_sf_id": None, # vim thread will populate
3503 db_instance_sfs
.append(db_sf
)
3505 "instance_action_id": instance_action_id
,
3506 "task_index": task_index
,
3507 "datacenter_vim_id": myvim_thread_id
,
3509 "status": "SCHEDULED",
3510 "item": "instance_sfs",
3512 "extra": yaml
.safe_dump({"params": "", "depends_on": sfis_created
},
3513 default_flow_style
=True, width
=256)
3515 sfs_created
.append(task_index
)
3517 db_vim_actions
.append(db_vim_action
)
3518 classifier
= rsp
['classifier']
3520 # TODO the following ~13 lines can be reused for the sfi case
3521 count
= mydb
.get_rows(
3522 SELECT
=('vms.count'),
3523 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_classifiers as c on interfaces.uuid=c.interface_id",
3524 WHERE
={'c.uuid': classifier
['uuid']})[0]['count']
3525 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == classifier
['sce_vnf_id']), None)
3526 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3528 for instance_vm
in instance_vms
:
3529 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3531 dependencies
.append(action
['task_index'])
3532 # TODO: throw exception if count != len(instance_vms)
3533 # TODO: and action shouldn't ever be None
3534 classifications_created
= []
3535 for i
in range(count
):
3536 for match
in classifier
['matches']:
3537 # create classifications
3538 classification_uuid
= str(uuid4())
3539 uuid_list
.append(classification_uuid
)
3540 db_classification
= {
3541 "uuid": classification_uuid
,
3542 "instance_scenario_id": instance_uuid
,
3543 'sce_classifier_match_id': match
['uuid'],
3544 'datacenter_id': datacenter_id
,
3545 'datacenter_tenant_id': myvim_thread_id
,
3546 "vim_classification_id": None, # vim thread will populate
3548 db_instance_classifications
.append(db_classification
)
3549 classification_params
= {
3550 "ip_proto": match
["ip_proto"],
3551 "source_ip": match
["source_ip"],
3552 "destination_ip": match
["destination_ip"],
3553 "source_port": match
["source_port"],
3554 "destination_port": match
["destination_port"]
3557 "instance_action_id": instance_action_id
,
3558 "task_index": task_index
,
3559 "datacenter_vim_id": myvim_thread_id
,
3561 "status": "SCHEDULED",
3562 "item": "instance_classifications",
3563 "item_id": classification_uuid
,
3564 "extra": yaml
.safe_dump({"params": classification_params
, "depends_on": [dependencies
[i
]]},
3565 default_flow_style
=True, width
=256)
3567 classifications_created
.append(task_index
)
3569 db_vim_actions
.append(db_vim_action
)
3572 sfp_uuid
= str(uuid4())
3573 uuid_list
.append(sfp_uuid
)
3576 "instance_scenario_id": instance_uuid
,
3577 'sce_rsp_id': rsp
['uuid'],
3578 'datacenter_id': datacenter_id
,
3579 'datacenter_tenant_id': myvim_thread_id
,
3580 "vim_sfp_id": None, # vim thread will populate
3582 db_instance_sfps
.append(db_sfp
)
3584 "instance_action_id": instance_action_id
,
3585 "task_index": task_index
,
3586 "datacenter_vim_id": myvim_thread_id
,
3588 "status": "SCHEDULED",
3589 "item": "instance_sfps",
3590 "item_id": sfp_uuid
,
3591 "extra": yaml
.safe_dump({"params": "", "depends_on": sfs_created
+ classifications_created
},
3592 default_flow_style
=True, width
=256)
3595 db_vim_actions
.append(db_vim_action
)
3597 scenarioDict
["datacenter2tenant"] = myvim_threads_id
3599 db_instance_action
["number_tasks"] = task_index
3600 db_instance_scenario
['datacenter_tenant_id'] = myvim_threads_id
[default_datacenter_id
]
3601 db_instance_scenario
['datacenter_id'] = default_datacenter_id
3603 {"instance_scenarios": db_instance_scenario
},
3604 {"instance_vnfs": db_instance_vnfs
},
3605 {"instance_nets": db_instance_nets
},
3606 {"ip_profiles": db_ip_profiles
},
3607 {"instance_vms": db_instance_vms
},
3608 {"instance_interfaces": db_instance_interfaces
},
3609 {"instance_actions": db_instance_action
},
3610 {"instance_sfis": db_instance_sfis
},
3611 {"instance_sfs": db_instance_sfs
},
3612 {"instance_classifications": db_instance_classifications
},
3613 {"instance_sfps": db_instance_sfps
},
3614 {"vim_actions": db_vim_actions
}
3617 logger
.debug("create_instance done DB tables: %s",
3618 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
3619 mydb
.new_rows(db_tables
, uuid_list
)
3620 for myvim_thread_id
in myvim_threads_id
.values():
3621 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
3623 returned_instance
= mydb
.get_instance_scenario(instance_uuid
)
3624 returned_instance
["action_id"] = instance_action_id
3625 return returned_instance
3626 except (NfvoException
, vimconn
.vimconnException
, db_base_Exception
) as e
:
3627 message
= rollback(mydb
, myvims
, rollbackList
)
3628 if isinstance(e
, db_base_Exception
):
3629 error_text
= "database Exception"
3630 elif isinstance(e
, vimconn
.vimconnException
):
3631 error_text
= "VIM Exception"
3633 error_text
= "Exception"
3634 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
3635 # logger.error("create_instance: %s", error_text)
3636 raise NfvoException(error_text
, e
.http_code
)
3639 def delete_instance(mydb
, tenant_id
, instance_id
):
3640 # print "Checking that the instance_id exists and getting the instance dictionary"
3641 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
3642 # print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
3643 tenant_id
= instanceDict
["tenant_id"]
3644 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
3645 # 1. Delete from Database
3646 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
3648 # 2. delete from VIM
3652 vimthread_affected
= {}
3653 net2vm_dependencies
= {}
3656 instance_action_id
= get_task_id()
3658 db_instance_action
= {
3659 "uuid": instance_action_id
, # same uuid for the instance and the action on create
3660 "tenant_id": tenant_id
,
3661 "instance_id": instance_id
,
3662 "description": "DELETE",
3663 # "number_tasks": 0 # filled bellow
3668 for sce_vnf
in instanceDict
['vnfs']:
3669 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
3670 vimthread_affected
[sce_vnf
["datacenter_tenant_id"]] = None
3671 if datacenter_key
not in myvims
:
3673 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
3674 except NfvoException
as e
:
3675 logger
.error(str(e
))
3677 myvim_threads
[datacenter_key
] = myvim_thread
3678 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
3679 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
3681 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
3682 sce_vnf
["datacenter_tenant_id"]))
3683 myvims
[datacenter_key
] = None
3685 myvims
[datacenter_key
] = vims
.values()[0]
3686 myvim
= myvims
[datacenter_key
]
3687 myvim_thread
= myvim_threads
[datacenter_key
]
3688 for vm
in sce_vnf
['vms']:
3690 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
3693 "instance_action_id": instance_action_id
,
3694 "task_index": task_index
,
3695 "datacenter_vim_id": sce_vnf
["datacenter_tenant_id"],
3697 "status": "SCHEDULED",
3698 "item": "instance_vms",
3699 "item_id": vm
["uuid"],
3700 "extra": yaml
.safe_dump({"params": vm
["interfaces"]},
3701 default_flow_style
=True, width
=256)
3703 db_vim_actions
.append(db_vim_action
)
3704 for interface
in vm
["interfaces"]:
3705 if not interface
.get("instance_net_id"):
3707 if interface
["instance_net_id"] not in net2vm_dependencies
:
3708 net2vm_dependencies
[interface
["instance_net_id"]] = []
3709 net2vm_dependencies
[interface
["instance_net_id"]].append(task_index
)
3714 for net
in instanceDict
['nets']:
3715 vimthread_affected
[net
["datacenter_tenant_id"]] = None
3716 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
3717 if datacenter_key
not in myvims
:
3719 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
3720 except NfvoException
as e
:
3721 logger
.error(str(e
))
3723 myvim_threads
[datacenter_key
] = myvim_thread
3724 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
3725 datacenter_tenant_id
=net
["datacenter_tenant_id"])
3727 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
3728 myvims
[datacenter_key
] = None
3730 myvims
[datacenter_key
] = vims
.values()[0]
3731 myvim
= myvims
[datacenter_key
]
3732 myvim_thread
= myvim_threads
[datacenter_key
]
3735 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
3737 extra
= {"params": (net
['vim_net_id'], net
['sdn_net_id'])}
3738 if net2vm_dependencies
.get(net
["uuid"]):
3739 extra
["depends_on"] = net2vm_dependencies
[net
["uuid"]]
3741 "instance_action_id": instance_action_id
,
3742 "task_index": task_index
,
3743 "datacenter_vim_id": net
["datacenter_tenant_id"],
3745 "status": "SCHEDULED",
3746 "item": "instance_nets",
3747 "item_id": net
["uuid"],
3748 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
3751 db_vim_actions
.append(db_vim_action
)
3753 # 2.3 deleting VNFFGs
3755 for sfp
in instanceDict
.get('sfps', ()):
3756 vimthread_affected
[sfp
["datacenter_tenant_id"]] = None
3757 datacenter_key
= (sfp
["datacenter_id"], sfp
["datacenter_tenant_id"])
3758 if datacenter_key
not in myvims
:
3760 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sfp
["datacenter_id"], sfp
["datacenter_tenant_id"])
3761 except NfvoException
as e
:
3762 logger
.error(str(e
))
3764 myvim_threads
[datacenter_key
] = myvim_thread
3765 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sfp
["datacenter_id"],
3766 datacenter_tenant_id
=sfp
["datacenter_tenant_id"])
3768 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfp
["datacenter_id"], sfp
["datacenter_tenant_id"]))
3769 myvims
[datacenter_key
] = None
3771 myvims
[datacenter_key
] = vims
.values()[0]
3772 myvim
= myvims
[datacenter_key
]
3773 myvim_thread
= myvim_threads
[datacenter_key
]
3776 error_msg
+= "\n vim_sfp_id={} cannot be deleted because datacenter={} not found".format(sfp
['vim_sfp_id'], sfp
["datacenter_id"])
3778 extra
= {"params": (sfp
['vim_sfp_id'])}
3780 "instance_action_id": instance_action_id
,
3781 "task_index": task_index
,
3782 "datacenter_vim_id": sfp
["datacenter_tenant_id"],
3784 "status": "SCHEDULED",
3785 "item": "instance_sfps",
3786 "item_id": sfp
["uuid"],
3787 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
3790 db_vim_actions
.append(db_vim_action
)
3792 for sf
in instanceDict
.get('sfs', ()):
3793 vimthread_affected
[sf
["datacenter_tenant_id"]] = None
3794 datacenter_key
= (sf
["datacenter_id"], sf
["datacenter_tenant_id"])
3795 if datacenter_key
not in myvims
:
3797 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sf
["datacenter_id"], sf
["datacenter_tenant_id"])
3798 except NfvoException
as e
:
3799 logger
.error(str(e
))
3801 myvim_threads
[datacenter_key
] = myvim_thread
3802 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sf
["datacenter_id"],
3803 datacenter_tenant_id
=sf
["datacenter_tenant_id"])
3805 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sf
["datacenter_id"], sf
["datacenter_tenant_id"]))
3806 myvims
[datacenter_key
] = None
3808 myvims
[datacenter_key
] = vims
.values()[0]
3809 myvim
= myvims
[datacenter_key
]
3810 myvim_thread
= myvim_threads
[datacenter_key
]
3813 error_msg
+= "\n vim_sf_id={} cannot be deleted because datacenter={} not found".format(sf
['vim_sf_id'], sf
["datacenter_id"])
3815 extra
= {"params": (sf
['vim_sf_id'])}
3817 "instance_action_id": instance_action_id
,
3818 "task_index": task_index
,
3819 "datacenter_vim_id": sf
["datacenter_tenant_id"],
3821 "status": "SCHEDULED",
3822 "item": "instance_sfs",
3823 "item_id": sf
["uuid"],
3824 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
3827 db_vim_actions
.append(db_vim_action
)
3829 for sfi
in instanceDict
.get('sfis', ()):
3830 vimthread_affected
[sfi
["datacenter_tenant_id"]] = None
3831 datacenter_key
= (sfi
["datacenter_id"], sfi
["datacenter_tenant_id"])
3832 if datacenter_key
not in myvims
:
3834 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sfi
["datacenter_id"], sfi
["datacenter_tenant_id"])
3835 except NfvoException
as e
:
3836 logger
.error(str(e
))
3838 myvim_threads
[datacenter_key
] = myvim_thread
3839 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sfi
["datacenter_id"],
3840 datacenter_tenant_id
=sfi
["datacenter_tenant_id"])
3842 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfi
["datacenter_id"], sfi
["datacenter_tenant_id"]))
3843 myvims
[datacenter_key
] = None
3845 myvims
[datacenter_key
] = vims
.values()[0]
3846 myvim
= myvims
[datacenter_key
]
3847 myvim_thread
= myvim_threads
[datacenter_key
]
3850 error_msg
+= "\n vim_sfi_id={} cannot be deleted because datacenter={} not found".format(sfi
['vim_sfi_id'], sfi
["datacenter_id"])
3852 extra
= {"params": (sfi
['vim_sfi_id'])}
3854 "instance_action_id": instance_action_id
,
3855 "task_index": task_index
,
3856 "datacenter_vim_id": sfi
["datacenter_tenant_id"],
3858 "status": "SCHEDULED",
3859 "item": "instance_sfis",
3860 "item_id": sfi
["uuid"],
3861 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
3864 db_vim_actions
.append(db_vim_action
)
3866 for classification
in instanceDict
['classifications']:
3867 vimthread_affected
[classification
["datacenter_tenant_id"]] = None
3868 datacenter_key
= (classification
["datacenter_id"], classification
["datacenter_tenant_id"])
3869 if datacenter_key
not in myvims
:
3871 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, classification
["datacenter_id"], classification
["datacenter_tenant_id"])
3872 except NfvoException
as e
:
3873 logger
.error(str(e
))
3875 myvim_threads
[datacenter_key
] = myvim_thread
3876 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=classification
["datacenter_id"],
3877 datacenter_tenant_id
=classification
["datacenter_tenant_id"])
3879 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(classification
["datacenter_id"], classification
["datacenter_tenant_id"]))
3880 myvims
[datacenter_key
] = None
3882 myvims
[datacenter_key
] = vims
.values()[0]
3883 myvim
= myvims
[datacenter_key
]
3884 myvim_thread
= myvim_threads
[datacenter_key
]
3887 error_msg
+= "\n vim_classification_id={} cannot be deleted because datacenter={} not found".format(classification
['vim_classification_id'], classification
["datacenter_id"])
3889 extra
= {"params": (classification
['vim_classification_id'])}
3891 "instance_action_id": instance_action_id
,
3892 "task_index": task_index
,
3893 "datacenter_vim_id": classification
["datacenter_tenant_id"],
3895 "status": "SCHEDULED",
3896 "item": "instance_classifications",
3897 "item_id": classification
["uuid"],
3898 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
3901 db_vim_actions
.append(db_vim_action
)
3903 db_instance_action
["number_tasks"] = task_index
3905 {"instance_actions": db_instance_action
},
3906 {"vim_actions": db_vim_actions
}
3909 logger
.debug("delete_instance done DB tables: %s",
3910 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
3911 mydb
.new_rows(db_tables
, ())
3912 for myvim_thread_id
in vimthread_affected
.keys():
3913 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
3915 if len(error_msg
) > 0:
3916 return 'action_id={} instance {} deleted but some elements could not be deleted, or already deleted '\
3917 '(error: 404) from VIM: {}'.format(instance_action_id
, message
, error_msg
)
3919 return "action_id={} instance {} deleted".format(instance_action_id
, message
)
3922 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
3923 '''Refreshes a scenario instance. It modifies instanceDict'''
3925 - result: <0 if there is any unexpected error, n>=0 if no errors where n is the number of vms and nets that couldn't be updated in the database
3928 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
3929 # #print "nfvo.refresh_instance begins"
3930 # #print json.dumps(instanceDict, indent=4)
3932 # #print "Getting the VIM URL and the VIM tenant_id"
3935 # # 1. Getting VIM vm and net list
3936 # vms_updated = [] #List of VM instance uuids in openmano that were updated
3939 # for sce_vnf in instanceDict['vnfs']:
3940 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
3941 # if datacenter_key not in vm_list:
3942 # vm_list[datacenter_key] = []
3943 # if datacenter_key not in myvims:
3944 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
3945 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
3946 # if len(vims) == 0:
3947 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
3948 # myvims[datacenter_key] = None
3950 # myvims[datacenter_key] = vims.values()[0]
3951 # for vm in sce_vnf['vms']:
3952 # vm_list[datacenter_key].append(vm['vim_vm_id'])
3953 # vms_notupdated.append(vm["uuid"])
3955 # nets_updated = [] #List of VM instance uuids in openmano that were updated
3956 # nets_notupdated=[]
3958 # for net in instanceDict['nets']:
3959 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
3960 # if datacenter_key not in net_list:
3961 # net_list[datacenter_key] = []
3962 # if datacenter_key not in myvims:
3963 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
3964 # datacenter_tenant_id=net["datacenter_tenant_id"])
3965 # if len(vims) == 0:
3966 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
3967 # myvims[datacenter_key] = None
3969 # myvims[datacenter_key] = vims.values()[0]
3971 # net_list[datacenter_key].append(net['vim_net_id'])
3972 # nets_notupdated.append(net["uuid"])
3974 # # 1. Getting the status of all VMs
3976 # for datacenter_key in myvims:
3977 # if not vm_list.get(datacenter_key):
3981 # if not myvims[datacenter_key]:
3982 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
3985 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
3987 # except vimconn.vimconnException as e:
3988 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
3989 # failed_message = str(e)
3991 # for vm in vm_list[datacenter_key]:
3992 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
3994 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
3995 # for sce_vnf in instanceDict['vnfs']:
3996 # for vm in sce_vnf['vms']:
3997 # vm_id = vm['vim_vm_id']
3998 # interfaces = vm_dict[vm_id].pop('interfaces', [])
3999 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
4000 # has_mgmt_iface = False
4001 # for iface in vm["interfaces"]:
4002 # if iface["type"]=="mgmt":
4003 # has_mgmt_iface = True
4004 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
4005 # vm_dict[vm_id]['status'] = "ACTIVE"
4006 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
4007 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
4008 # 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'):
4009 # vm['status'] = vm_dict[vm_id]['status']
4010 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
4011 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
4012 # # 2.1. Update in openmano DB the VMs whose status changed
4014 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
4015 # vms_notupdated.remove(vm["uuid"])
4017 # vms_updated.append(vm["uuid"])
4018 # except db_base_Exception as e:
4019 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
4020 # # 2.2. Update in openmano DB the interface VMs
4021 # for interface in interfaces:
4022 # #translate from vim_net_id to instance_net_id
4023 # network_id_list=[]
4024 # for net in instanceDict['nets']:
4025 # if net["vim_net_id"] == interface["vim_net_id"]:
4026 # network_id_list.append(net["uuid"])
4027 # if not network_id_list:
4029 # del interface["vim_net_id"]
4031 # for network_id in network_id_list:
4032 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
4033 # except db_base_Exception as e:
4034 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
4036 # # 3. Getting the status of all nets
4038 # for datacenter_key in myvims:
4039 # if not net_list.get(datacenter_key):
4042 # failed_message = ""
4043 # if not myvims[datacenter_key]:
4044 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
4047 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
4049 # except vimconn.vimconnException as e:
4050 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
4051 # failed_message = str(e)
4053 # for net in net_list[datacenter_key]:
4054 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
4056 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
4057 # # TODO: update nets inside a vnf
4058 # for net in instanceDict['nets']:
4059 # net_id = net['vim_net_id']
4060 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
4061 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
4062 # 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'):
4063 # net['status'] = net_dict[net_id]['status']
4064 # net['error_msg'] = net_dict[net_id].get('error_msg')
4065 # net['vim_info'] = net_dict[net_id].get('vim_info')
4066 # # 5.1. Update in openmano DB the nets whose status changed
4068 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
4069 # nets_notupdated.remove(net["uuid"])
4071 # nets_updated.append(net["uuid"])
4072 # except db_base_Exception as e:
4073 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
4075 # # Returns appropriate output
4076 # #print "nfvo.refresh_instance finishes"
4077 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
4078 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
4079 instance_id
= instanceDict
['uuid']
4080 # if len(vms_notupdated)+len(nets_notupdated)>0:
4081 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
4082 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
4084 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
4086 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
4087 #print "Checking that the instance_id exists and getting the instance dictionary"
4088 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
4089 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
4091 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
4092 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
4094 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
4095 myvim
= vims
.values()[0]
4097 if action_dict
.get("create-vdu"):
4098 for vdu
in action_dict
["create-vdu"]:
4099 vdu_id
= vdu
.get("vdu-id")
4100 vdu_count
= vdu
.get("count", 1)
4101 # get from database TODO
4105 input_vnfs
= action_dict
.pop("vnfs", [])
4106 input_vms
= action_dict
.pop("vms", [])
4107 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
4111 for sce_vnf
in instanceDict
['vnfs']:
4112 for vm
in sce_vnf
['vms']:
4113 if not action_over_all
:
4114 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
4115 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
4118 if "add_public_key" in action_dict
:
4120 if sce_vnf
.get('mgmt_access'):
4121 mgmt_access
= yaml
.load(sce_vnf
['mgmt_access'])
4122 ssh_access
= mgmt_access
['config-access']['ssh-access']
4123 tenant
= mydb
.get_rows_by_id('nfvo_tenants', nfvo_tenant
)
4125 if ssh_access
['required'] and ssh_access
['default-user']:
4126 if 'ip_address' in vm
:
4127 mgmt_ip
= vm
['ip_address'].split(';')
4128 password
= mgmt_access
['config-access'].get('password')
4129 priv_RO_key
= decrypt_key(tenant
[0]['encrypted_RO_priv_key'], tenant
[0]['uuid'])
4130 myvim
.inject_user_key(mgmt_ip
[0], ssh_access
['default-user'],
4131 action_dict
['add_public_key'],
4132 password
=password
, ro_key
=priv_RO_key
)
4134 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4135 HTTP_Internal_Server_Error
)
4137 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4138 HTTP_Internal_Server_Error
)
4140 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4141 HTTP_Internal_Server_Error
)
4143 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
4144 if "console" in action_dict
:
4145 if not global_config
["http_console_proxy"]:
4146 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4147 "description": "{protocol}//{ip}:{port}/{suffix}".format(
4148 protocol
=data
["protocol"],
4149 ip
= data
["server"],
4150 port
= data
["port"],
4151 suffix
= data
["suffix"]),
4155 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
4156 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
4157 "description": "this console is only reachable by local interface",
4162 #print "console data", data
4164 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
4165 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4166 "description": "{protocol}//{ip}:{port}/{suffix}".format(
4167 protocol
=data
["protocol"],
4168 ip
= global_config
["http_console_host"],
4169 port
= console_thread
.port
,
4170 suffix
= data
["suffix"]),
4174 except NfvoException
as e
:
4175 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
4179 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
4181 except vimconn
.vimconnException
as e
:
4182 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
4185 if vm_ok
==0: #all goes wrong
4190 def instance_action_get(mydb
, nfvo_tenant
, instance_id
, action_id
):
4192 if nfvo_tenant
and nfvo_tenant
!= "any":
4193 filter["tenant_id"] = nfvo_tenant
4194 if instance_id
and instance_id
!= "any":
4195 filter["instance_id"] = instance_id
4197 filter["uuid"] = action_id
4198 rows
= mydb
.get_rows(FROM
="instance_actions", WHERE
=filter)
4199 if not rows
and action_id
:
4200 raise NfvoException("Not found any action with this criteria", HTTP_Not_Found
)
4201 return {"ations": rows
}
4204 def create_or_use_console_proxy_thread(console_server
, console_port
):
4205 #look for a non-used port
4206 console_thread_key
= console_server
+ ":" + str(console_port
)
4207 if console_thread_key
in global_config
["console_thread"]:
4208 #global_config["console_thread"][console_thread_key].start_timeout()
4209 return global_config
["console_thread"][console_thread_key
]
4211 for port
in global_config
["console_port_iterator"]():
4212 #print "create_or_use_console_proxy_thread() port:", port
4213 if port
in global_config
["console_ports"]:
4216 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
4218 global_config
["console_thread"][console_thread_key
] = clithread
4219 global_config
["console_ports"][port
] = console_thread_key
4221 except cli
.ConsoleProxyExceptionPortUsed
as e
:
4222 #port used, try with onoher
4224 except cli
.ConsoleProxyException
as e
:
4225 raise NfvoException(str(e
), HTTP_Bad_Request
)
4226 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
4229 def check_tenant(mydb
, tenant_id
):
4230 '''check that tenant exists at database'''
4231 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
4233 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
4236 def new_tenant(mydb
, tenant_dict
):
4238 tenant_uuid
= str(uuid4())
4239 tenant_dict
['uuid'] = tenant_uuid
4241 pub_key
, priv_key
= create_RO_keypair(tenant_uuid
)
4242 tenant_dict
['RO_pub_key'] = pub_key
4243 tenant_dict
['encrypted_RO_priv_key'] = priv_key
4244 mydb
.new_row("nfvo_tenants", tenant_dict
, confidential_data
=True)
4245 except db_base_Exception
as e
:
4246 raise NfvoException("Error creating the new tenant: {} ".format(tenant_dict
['name']) + str(e
), HTTP_Internal_Server_Error
)
4249 def delete_tenant(mydb
, tenant
):
4250 #get nfvo_tenant info
4252 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
4253 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
4254 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
4257 def new_datacenter(mydb
, datacenter_descriptor
):
4258 if "config" in datacenter_descriptor
:
4259 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
4260 #Check that datacenter-type is correct
4261 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
4264 module
= "vimconn_" + datacenter_type
4265 pkg
= __import__("osm_ro." + module
)
4266 vim_conn
= getattr(pkg
, module
)
4267 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
4268 except (IOError, ImportError):
4269 # if module_info and module_info[0]:
4270 # file.close(module_info[0])
4271 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}.py' not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
4273 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True, confidential_data
=True)
4274 return datacenter_id
4277 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
4278 # obtain data, check that only one exist
4279 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
4282 datacenter_id
= datacenter
['uuid']
4283 where
={'uuid': datacenter
['uuid']}
4284 remove_port_mapping
= False
4285 if "config" in datacenter_descriptor
:
4286 if datacenter_descriptor
['config'] != None:
4288 new_config_dict
= datacenter_descriptor
["config"]
4291 for k
in new_config_dict
:
4292 if new_config_dict
[k
] == None:
4294 if k
== 'sdn-controller':
4295 remove_port_mapping
= True
4297 config_text
= datacenter
.get("config")
4300 config_dict
= yaml
.load(config_text
)
4301 config_dict
.update(new_config_dict
)
4305 except Exception as e
:
4306 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
4308 datacenter_descriptor
["config"] = yaml
.safe_dump(config_dict
, default_flow_style
=True, width
=256)
4310 datacenter_descriptor
["config"] = None
4311 if remove_port_mapping
:
4313 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_id
)
4314 except ovimException
as e
:
4315 logger
.error("Error deleting datacenter-port-mapping " + str(e
))
4317 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
4318 return datacenter_id
4321 def delete_datacenter(mydb
, datacenter
):
4322 #get nfvo_tenant info
4323 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
4324 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
4326 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_dict
['uuid'])
4327 except ovimException
as e
:
4328 logger
.error("Error deleting datacenter-port-mapping " + str(e
))
4329 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
4332 def associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter
, vim_tenant_id
=None, vim_tenant_name
=None, vim_username
=None, vim_password
=None, config
=None):
4333 # get datacenter info
4335 datacenter_id
= get_datacenter_uuid(mydb
, None, datacenter
)
4337 create_vim_tenant
= True if not vim_tenant_id
and not vim_tenant_name
else False
4339 # get nfvo_tenant info
4340 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
4341 if vim_tenant_name
==None:
4342 vim_tenant_name
=tenant_dict
['name']
4344 #check that this association does not exist before
4345 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
4346 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
4347 if len(tenants_datacenters
)>0:
4348 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
4350 vim_tenant_id_exist_atdb
=False
4351 if not create_vim_tenant
:
4352 where_
={"datacenter_id": datacenter_id
}
4353 if vim_tenant_id
!=None:
4354 where_
["vim_tenant_id"] = vim_tenant_id
4355 if vim_tenant_name
!=None:
4356 where_
["vim_tenant_name"] = vim_tenant_name
4357 #check if vim_tenant_id is already at database
4358 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
4359 if len(datacenter_tenants_dict
)>=1:
4360 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
4361 vim_tenant_id_exist_atdb
=True
4362 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
4364 datacenter_tenants_dict
= {}
4365 #insert at table datacenter_tenants
4366 else: #if vim_tenant_id==None:
4367 #create tenant at VIM if not provided
4369 _
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
, vim_user
=vim_username
,
4370 vim_passwd
=vim_password
)
4371 datacenter_name
= myvim
["name"]
4372 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
4373 except vimconn
.vimconnException
as e
:
4374 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
4375 datacenter_tenants_dict
= {}
4376 datacenter_tenants_dict
["created"]="true"
4378 #fill datacenter_tenants table
4379 if not vim_tenant_id_exist_atdb
:
4380 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
4381 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
4382 datacenter_tenants_dict
["user"] = vim_username
4383 datacenter_tenants_dict
["passwd"] = vim_password
4384 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
4386 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
4387 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True, confidential_data
=True)
4388 datacenter_tenants_dict
["uuid"] = id_
4390 #fill tenants_datacenters table
4391 datacenter_tenant_id
= datacenter_tenants_dict
["uuid"]
4392 tenants_datacenter_dict
["datacenter_tenant_id"] = datacenter_tenant_id
4393 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
4395 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_dict
['uuid'], datacenter_id
) # reload data
4396 datacenter_name
= myvim
["name"]
4397 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
4398 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, datacenter_name
, datacenter_tenant_id
,
4399 db
=db
, db_lock
=db_lock
, ovim
=ovim
)
4401 thread_id
= datacenter_tenants_dict
["uuid"]
4402 vim_threads
["running"][thread_id
] = new_thread
4403 return datacenter_id
4404 except vimconn
.vimconnException
as e
:
4405 raise NfvoException(str(e
), HTTP_Bad_Request
)
4408 def edit_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=None, vim_tenant_name
=None,
4409 vim_username
=None, vim_password
=None, config
=None):
4410 #Obtain the data of this datacenter_tenant_id
4411 vim_data
= mydb
.get_rows(
4412 SELECT
=("datacenter_tenants.vim_tenant_name", "datacenter_tenants.vim_tenant_id", "datacenter_tenants.user",
4413 "datacenter_tenants.passwd", "datacenter_tenants.config"),
4414 FROM
="datacenter_tenants JOIN tenants_datacenters ON datacenter_tenants.uuid=tenants_datacenters.datacenter_tenant_id",
4415 WHERE
={"tenants_datacenters.nfvo_tenant_id": nfvo_tenant
,
4416 "tenants_datacenters.datacenter_id": datacenter_id
})
4418 logger
.debug(str(vim_data
))
4419 if len(vim_data
) < 1:
4420 raise NfvoException("Datacenter {} is not attached for tenant {}".format(datacenter_id
, nfvo_tenant
), HTTP_Conflict
)
4424 v
['config'] = yaml
.load(v
['config'])
4427 v
['vim_tenant_id'] = vim_tenant_id
4429 v
['vim_tenant_name'] = vim_tenant_name
4431 v
['user'] = vim_username
4433 v
['passwd'] = vim_password
4437 v
['config'].update(config
)
4439 logger
.debug(str(v
))
4440 deassociate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'])
4441 associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'], vim_tenant_name
=v
['vim_tenant_name'],
4442 vim_username
=v
['user'], vim_password
=v
['passwd'], config
=v
['config'])
4444 return datacenter_id
4446 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
4447 #get nfvo_tenant info
4448 if not tenant_id
or tenant_id
=="any":
4451 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
4452 tenant_uuid
= tenant_dict
['uuid']
4454 datacenter_id
= get_datacenter_uuid(mydb
, tenant_uuid
, datacenter
)
4455 #check that this association exist before
4456 tenants_datacenter_dict
={"datacenter_id": datacenter_id
}
4458 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
4459 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
4460 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
4461 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
4463 #delete this association
4464 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
4466 #get vim_tenant info and deletes
4468 for tenant_datacenter_item
in tenant_datacenter_list
:
4469 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
4470 #try to delete vim:tenant
4472 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
4473 if vim_tenant_dict
['created']=='true':
4474 #delete tenant at VIM if created by NFVO
4476 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4477 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
4478 except vimconn
.vimconnException
as e
:
4479 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
4480 logger
.warn(warning
)
4481 except db_base_Exception
as e
:
4482 logger
.error("Cannot delete datacenter_tenants " + str(e
))
4483 pass # the error will be caused because dependencies, vim_tenant can not be deleted
4484 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
4485 thread
= vim_threads
["running"][thread_id
]
4486 thread
.insert_task("exit")
4487 vim_threads
["deleting"][thread_id
] = thread
4488 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
4491 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
4493 #get datacenter info
4494 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4496 if 'net-update' in action_dict
:
4498 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
4500 except vimconn
.vimconnException
as e
:
4501 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
4502 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
4503 #update nets Change from VIM format to NFVO format
4506 net_nfvo
={'datacenter_id': datacenter_id
}
4507 net_nfvo
['name'] = net
['name']
4508 #net_nfvo['description']= net['name']
4509 net_nfvo
['vim_net_id'] = net
['id']
4510 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
4511 net_nfvo
['shared'] = net
['shared']
4512 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
4513 net_list
.append(net_nfvo
)
4514 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
4515 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
4517 elif 'net-edit' in action_dict
:
4518 net
= action_dict
['net-edit'].pop('net')
4519 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
4520 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
4521 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
4523 elif 'net-delete' in action_dict
:
4524 net
= action_dict
['net-deelte'].get('net')
4525 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
4526 result
= mydb
.delete_row(FROM
='datacenter_nets',
4527 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
4531 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
4534 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
4535 #get datacenter info
4536 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4538 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
4539 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
4540 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
4544 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
4545 #get datacenter info
4546 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4549 action_dict
= action_dict
["netmap"]
4550 if 'vim_id' in action_dict
:
4551 filter_dict
["id"] = action_dict
['vim_id']
4552 if 'vim_name' in action_dict
:
4553 filter_dict
["name"] = action_dict
['vim_name']
4555 filter_dict
["shared"] = True
4558 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
4559 except vimconn
.vimconnException
as e
:
4560 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
4561 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
4562 if len(vim_nets
)>1 and action_dict
:
4563 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
4564 elif len(vim_nets
)==0: # and action_dict:
4565 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
4567 for net
in vim_nets
:
4568 net_nfvo
={'datacenter_id': datacenter_id
}
4569 if action_dict
and "name" in action_dict
:
4570 net_nfvo
['name'] = action_dict
['name']
4572 net_nfvo
['name'] = net
['name']
4573 #net_nfvo['description']= net['name']
4574 net_nfvo
['vim_net_id'] = net
['id']
4575 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
4576 net_nfvo
['shared'] = net
['shared']
4577 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
4579 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
4580 net_nfvo
["status"] = "OK"
4581 net_nfvo
["uuid"] = net_id
4582 except db_base_Exception
as e
:
4586 net_nfvo
["status"] = "FAIL: " + str(e
)
4587 net_list
.append(net_nfvo
)
4590 def get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
):
4591 # obtain all network data
4593 if utils
.check_valid_uuid(network_id
):
4594 filter_dict
= {"id": network_id
}
4596 filter_dict
= {"name": network_id
}
4598 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4599 network
= myvim
.get_network_list(filter_dict
=filter_dict
)
4600 except vimconn
.vimconnException
as e
:
4601 raise NfvoException("Not possible to get_sdn_net_id from VIM: {}".format(str(e
)), e
.http_code
)
4603 # ensure the network is defined
4604 if len(network
) == 0:
4605 raise NfvoException("Network {} is not present in the system".format(network_id
),
4608 # ensure there is only one network with the provided name
4609 if len(network
) > 1:
4610 raise NfvoException("Multiple networks present in vim identified by {}".format(network_id
), HTTP_Bad_Request
)
4612 # ensure it is a dataplane network
4613 if network
[0]['type'] != 'data':
4616 # ensure we use the id
4617 network_id
= network
[0]['id']
4619 # search in dabase mano_db in table instance nets for the sdn_net_id that corresponds to the vim_net_id==network_id
4620 # and with instance_scenario_id==NULL
4621 #search_dict = {'vim_net_id': network_id, 'instance_scenario_id': None}
4622 search_dict
= {'vim_net_id': network_id
}
4625 #sdn_network_id = mydb.get_rows(SELECT=('sdn_net_id',), FROM='instance_nets', WHERE=search_dict)[0]['sdn_net_id']
4626 result
= mydb
.get_rows(SELECT
=('sdn_net_id',), FROM
='instance_nets', WHERE
=search_dict
)
4627 except db_base_Exception
as e
:
4628 raise NfvoException("db_base_Exception obtaining SDN network to associated to vim network {}".format(
4629 network_id
) + str(e
), HTTP_Internal_Server_Error
)
4633 if net
['sdn_net_id'] != None:
4635 sdn_net_id
= net
['sdn_net_id']
4637 if sdn_net_counter
== 0:
4639 elif sdn_net_counter
== 1:
4642 raise NfvoException("More than one SDN network is associated to vim network {}".format(
4643 network_id
), HTTP_Internal_Server_Error
)
4645 def get_sdn_controller_id(mydb
, datacenter
):
4646 # Obtain sdn controller id
4647 config
= mydb
.get_rows(SELECT
=('config',), FROM
='datacenters', WHERE
={'uuid': datacenter
})[0].get('config', '{}')
4651 return yaml
.load(config
).get('sdn-controller')
4653 def vim_net_sdn_attach(mydb
, tenant_id
, datacenter
, network_id
, descriptor
):
4655 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
4656 if not sdn_network_id
:
4657 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
), HTTP_Internal_Server_Error
)
4659 #Obtain sdn controller id
4660 controller_id
= get_sdn_controller_id(mydb
, datacenter
)
4661 if not controller_id
:
4662 raise NfvoException("No SDN controller is set for datacenter {}".format(datacenter
), HTTP_Internal_Server_Error
)
4664 #Obtain sdn controller info
4665 sdn_controller
= ovim
.show_of_controller(controller_id
)
4668 'name': 'external_port',
4669 'net_id': sdn_network_id
,
4670 'ofc_id': controller_id
,
4671 'switch_dpid': sdn_controller
['dpid'],
4672 'switch_port': descriptor
['port']
4675 if 'vlan' in descriptor
:
4676 port_data
['vlan'] = descriptor
['vlan']
4677 if 'mac' in descriptor
:
4678 port_data
['mac'] = descriptor
['mac']
4680 result
= ovim
.new_port(port_data
)
4681 except ovimException
as e
:
4682 raise NfvoException("ovimException attaching SDN network {} to vim network {}".format(
4683 sdn_network_id
, network_id
) + str(e
), HTTP_Internal_Server_Error
)
4684 except db_base_Exception
as e
:
4685 raise NfvoException("db_base_Exception attaching SDN network to vim network {}".format(
4686 network_id
) + str(e
), HTTP_Internal_Server_Error
)
4688 return 'Port uuid: '+ result
4690 def vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, network_id
, port_id
=None):
4692 filter = {'uuid': port_id
}
4694 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
4695 if not sdn_network_id
:
4696 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
),
4697 HTTP_Internal_Server_Error
)
4698 #in case no port_id is specified only ports marked as 'external_port' will be detached
4699 filter = {'name': 'external_port', 'net_id': sdn_network_id
}
4702 port_list
= ovim
.get_ports(columns
={'uuid'}, filter=filter)
4703 except ovimException
as e
:
4704 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
4705 HTTP_Internal_Server_Error
)
4707 if len(port_list
) == 0:
4708 raise NfvoException("No ports attached to the network {} were found with the requested criteria".format(network_id
),
4712 for port
in port_list
:
4714 port_uuid_list
.append(port
['uuid'])
4715 ovim
.delete_port(port
['uuid'])
4716 except ovimException
as e
:
4717 raise NfvoException("ovimException deleting port {} for net {}. ".format(port
['uuid'], network_id
) + str(e
), HTTP_Internal_Server_Error
)
4719 return 'Detached ports uuid: {}'.format(','.join(port_uuid_list
))
4721 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
4722 #get datacenter info
4723 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4726 if utils
.check_valid_uuid(name
):
4727 filter_dict
["id"] = name
4729 filter_dict
["name"] = name
4731 if item
=="networks":
4732 #filter_dict['tenant_id'] = myvim['tenant_id']
4733 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
4735 if len(content
) == 0:
4736 raise NfvoException("Network {} is not present in the system. ".format(name
),
4739 #Update the networks with the attached ports
4741 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, net
['id'])
4742 if sdn_network_id
!= None:
4744 #port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan'}, filter={'name': 'external_port', 'net_id': sdn_network_id})
4745 port_list
= ovim
.get_ports(columns
={'uuid', 'switch_port', 'vlan','name'}, filter={'net_id': sdn_network_id
})
4746 except ovimException
as e
:
4747 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
), HTTP_Internal_Server_Error
)
4748 #Remove field name and if port name is external_port save it as 'type'
4749 for port
in port_list
:
4750 if port
['name'] == 'external_port':
4751 port
['type'] = "External"
4753 net
['sdn_network_id'] = sdn_network_id
4754 net
['sdn_attached_ports'] = port_list
4756 elif item
=="tenants":
4757 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
4758 elif item
== "images":
4760 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
4762 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
4763 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
4764 if name
and len(content
)==1:
4765 return {item
[:-1]: content
[0]}
4766 elif name
and len(content
)==0:
4767 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
4770 return {item
: content
}
4771 except vimconn
.vimconnException
as e
:
4772 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
4773 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
4776 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
4777 #get datacenter info
4778 if tenant_id
== "any":
4781 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4783 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
4784 logger
.debug("vim_action_delete vim response: " + str(content
))
4785 items
= content
.values()[0]
4786 if type(items
)==list and len(items
)==0:
4787 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
4788 elif type(items
)==list and len(items
)>1:
4789 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
4790 else: # it is a dict
4791 item_id
= items
["id"]
4792 item_name
= str(items
.get("name"))
4795 if item
=="networks":
4796 # If there is a SDN network associated to the vim-network, proceed to clear the relationship and delete it
4797 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, item_id
)
4798 if sdn_network_id
!= None:
4799 #Delete any port attachment to this network
4801 port_list
= ovim
.get_ports(columns
={'uuid'}, filter={'net_id': sdn_network_id
})
4802 except ovimException
as e
:
4803 raise NfvoException(
4804 "ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
4805 HTTP_Internal_Server_Error
)
4807 # By calling one by one all ports to be detached we ensure that not only the external_ports get detached
4808 for port
in port_list
:
4809 vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, item_id
, port
['uuid'])
4811 #Delete from 'instance_nets' the correspondence between the vim-net-id and the sdn-net-id
4813 mydb
.delete_row(FROM
='instance_nets', WHERE
={'instance_scenario_id': None, 'sdn_net_id': sdn_network_id
, 'vim_net_id': item_id
})
4814 except db_base_Exception
as e
:
4815 raise NfvoException("Error deleting correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
4816 str(e
), HTTP_Internal_Server_Error
)
4818 #Delete the SDN network
4820 ovim
.delete_network(sdn_network_id
)
4821 except ovimException
as e
:
4822 logger
.error("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
), exc_info
=True)
4823 raise NfvoException("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
),
4824 HTTP_Internal_Server_Error
)
4826 content
= myvim
.delete_network(item_id
)
4827 elif item
=="tenants":
4828 content
= myvim
.delete_tenant(item_id
)
4829 elif item
== "images":
4830 content
= myvim
.delete_image(item_id
)
4832 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
4833 except vimconn
.vimconnException
as e
:
4834 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
4835 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
4837 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
4840 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
4841 #get datacenter info
4842 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
4843 if tenant_id
== "any":
4845 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4847 if item
=="networks":
4848 net
= descriptor
["network"]
4849 net_name
= net
.pop("name")
4850 net_type
= net
.pop("type", "bridge")
4851 net_public
= net
.pop("shared", False)
4852 net_ipprofile
= net
.pop("ip_profile", None)
4853 net_vlan
= net
.pop("vlan", None)
4854 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
4856 #If the datacenter has a SDN controller defined and the network is of dataplane type, then create the sdn network
4857 if get_sdn_controller_id(mydb
, datacenter
) != None and (net_type
== 'data' or net_type
== 'ptp'):
4858 #obtain datacenter_tenant_id
4859 datacenter_tenant_id
= mydb
.get_rows(SELECT
=('uuid',),
4860 FROM
='datacenter_tenants',
4861 WHERE
={'datacenter_id': datacenter
})[0]['uuid']
4864 sdn_network
['vlan'] = net_vlan
4865 sdn_network
['type'] = net_type
4866 sdn_network
['name'] = net_name
4867 sdn_network
['region'] = datacenter_tenant_id
4868 ovim_content
= ovim
.new_network(sdn_network
)
4869 except ovimException
as e
:
4870 logger
.error("ovimException creating SDN network={} ".format(
4871 sdn_network
) + str(e
), exc_info
=True)
4872 raise NfvoException("ovimException creating SDN network={} ".format(sdn_network
) + str(e
),
4873 HTTP_Internal_Server_Error
)
4875 # Save entry in in dabase mano_db in table instance_nets to stablish a dictionary vim_net_id <->sdn_net_id
4876 # use instance_scenario_id=None to distinguish from real instaces of nets
4877 correspondence
= {'instance_scenario_id': None,
4878 'sdn_net_id': ovim_content
,
4879 'vim_net_id': content
,
4880 'datacenter_tenant_id': datacenter_tenant_id
4883 mydb
.new_row('instance_nets', correspondence
, add_uuid
=True)
4884 except db_base_Exception
as e
:
4885 raise NfvoException("Error saving correspondence for VIM/SDN dataplane networks{}: {}".format(
4886 correspondence
, e
), HTTP_Internal_Server_Error
)
4887 elif item
=="tenants":
4888 tenant
= descriptor
["tenant"]
4889 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
4891 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
4892 except vimconn
.vimconnException
as e
:
4893 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
4895 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
4897 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
4898 data
= ovim
.new_of_controller(sdn_controller
)
4899 logger
.debug('New SDN controller created with uuid {}'.format(data
))
4902 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
4903 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
4904 msg
= 'SDN controller {} updated'.format(data
)
4908 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
4909 if controller_id
== None:
4910 data
= ovim
.get_of_controllers()
4912 data
= ovim
.show_of_controller(controller_id
)
4914 msg
= 'SDN controller list:\n {}'.format(data
)
4918 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
4919 select_
= ('uuid', 'config')
4920 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
4921 for datacenter
in datacenters
:
4922 if datacenter
['config']:
4923 config
= yaml
.load(datacenter
['config'])
4924 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
4925 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), HTTP_Conflict
)
4927 data
= ovim
.delete_of_controller(controller_id
)
4928 msg
= 'SDN controller {} deleted'.format(data
)
4932 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
4933 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
4934 if len(controller
) < 1:
4935 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), HTTP_Not_Found
)
4938 sdn_controller_id
= yaml
.load(controller
[0]["config"])["sdn-controller"]
4940 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), HTTP_Bad_Request
)
4942 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
4943 switch_dpid
= sdn_controller
["dpid"]
4946 for compute_node
in sdn_port_mapping
:
4947 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
4949 element
["compute_node"] = compute_node
["compute_node"]
4950 for port
in compute_node
["ports"]:
4951 element
["pci"] = port
.get("pci")
4952 element
["switch_port"] = port
.get("switch_port")
4953 element
["switch_mac"] = port
.get("switch_mac")
4954 if not element
["pci"] or not (element
["switch_port"] or element
["switch_mac"]):
4955 raise NfvoException ("The mapping must contain the 'pci' and at least one of the elements 'switch_port'"
4956 " or 'switch_mac'", HTTP_Bad_Request
)
4957 maps
.append(dict(element
))
4959 return ovim
.set_of_port_mapping(maps
, ofc_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, region
=datacenter_id
)
4961 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
4962 maps
= ovim
.get_of_port_mappings(db_filter
={"region": datacenter_id
})
4965 "sdn-controller": None,
4966 "datacenter-id": datacenter_id
,
4968 "ports_mapping": list()
4971 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
4972 if datacenter
['config']:
4973 config
= yaml
.load(datacenter
['config'])
4974 if 'sdn-controller' in config
:
4975 controller_id
= config
['sdn-controller']
4976 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
4977 result
["sdn-controller"] = controller_id
4978 result
["dpid"] = sdn_controller
["dpid"]
4980 if result
["sdn-controller"] == None:
4981 raise NfvoException("SDN controller is not defined for datacenter {}".format(datacenter_id
), HTTP_Bad_Request
)
4982 if result
["dpid"] == None:
4983 raise NfvoException("It was not possible to determine DPID for SDN controller {}".format(result
["sdn-controller"]),
4984 HTTP_Internal_Server_Error
)
4989 ports_correspondence_dict
= dict()
4991 if result
["sdn-controller"] != link
["ofc_id"]:
4992 raise NfvoException("The sdn-controller specified for different port mappings differ", HTTP_Internal_Server_Error
)
4993 if result
["dpid"] != link
["switch_dpid"]:
4994 raise NfvoException("The dpid specified for different port mappings differ", HTTP_Internal_Server_Error
)
4996 element
["pci"] = link
["pci"]
4997 if link
["switch_port"]:
4998 element
["switch_port"] = link
["switch_port"]
4999 if link
["switch_mac"]:
5000 element
["switch_mac"] = link
["switch_mac"]
5002 if not link
["compute_node"] in ports_correspondence_dict
:
5004 content
["compute_node"] = link
["compute_node"]
5005 content
["ports"] = list()
5006 ports_correspondence_dict
[link
["compute_node"]] = content
5008 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
5010 for key
in sorted(ports_correspondence_dict
):
5011 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
5015 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
5016 return ovim
.clear_of_port_mapping(db_filter
={"region":datacenter_id
})
5018 def create_RO_keypair(tenant_id
):
5020 Creates a public / private keys for a RO tenant and returns their values
5022 tenant_id: ID of the tenant
5024 public_key: Public key for the RO tenant
5025 private_key: Encrypted private key for RO tenant
5029 key
= RSA
.generate(bits
)
5031 public_key
= key
.publickey().exportKey('OpenSSH')
5032 if isinstance(public_key
, ValueError):
5033 raise NfvoException("Unable to create public key: {}".format(public_key
), HTTP_Internal_Server_Error
)
5034 private_key
= key
.exportKey(passphrase
=tenant_id
, pkcs
=8)
5035 except (ValueError, NameError) as e
:
5036 raise NfvoException("Unable to create private key: {}".format(e
), HTTP_Internal_Server_Error
)
5037 return public_key
, private_key
5039 def decrypt_key (key
, tenant_id
):
5041 Decrypts an encrypted RSA key
5043 key: Private key to be decrypted
5044 tenant_id: ID of the tenant
5046 unencrypted_key: Unencrypted private key for RO tenant
5049 key
= RSA
.importKey(key
,tenant_id
)
5050 unencrypted_key
= key
.exportKey('PEM')
5051 if isinstance(unencrypted_key
, ValueError):
5052 raise NfvoException("Unable to decrypt the private key: {}".format(unencrypted_key
), HTTP_Internal_Server_Error
)
5053 except ValueError as e
:
5054 raise NfvoException("Unable to decrypt the private key: {}".format(e
), HTTP_Internal_Server_Error
)
5055 return unencrypted_key