1 # -*- coding: utf-8 -*-
4 # Copyright 2015 Telefonica Investigacion y Desarrollo, S.A.U.
5 # This file is part of openmano
8 # Licensed under the Apache License, Version 2.0 (the "License"); you may
9 # not use this file except in compliance with the License. You may obtain
10 # a copy of the License at
12 # http://www.apache.org/licenses/LICENSE-2.0
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17 # License for the specific language governing permissions and limitations
20 # For those usages not covered by the Apache License, Version 2.0 please
21 # contact with: nfvlabs@tid.es
25 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$"
34 from utils
import deprecated
36 import console_proxy_thread
as cli
41 from uuid
import uuid4
42 from db_base
import db_base_Exception
45 from threading
import Lock
47 from lib_osm_openvim
import ovim
as ovim_module
48 from lib_osm_openvim
.ovim
import ovimException
49 from Crypto
.PublicKey
import RSA
51 import osm_im
.vnfd
as vnfd_catalog
52 import osm_im
.nsd
as nsd_catalog
53 from pyangbind
.lib
.serialise
import pybindJSONDecoder
54 from copy
import deepcopy
58 import wim
.wimconn
as wimconn
59 import wim
.wim_thread
as wim_thread
60 from .http_tools
import errors
as httperrors
61 from .wim
.engine
import WimEngine
62 from .wim
.persistence
import WimPersistence
63 from copy
import deepcopy
64 from pprint
import pformat
68 global vimconn_imported
72 global wimconn_imported
75 global default_volume_size
76 default_volume_size
= '5' #size in GB
81 vimconn_imported
= {} # dictionary with VIM type as key, loaded module as value
82 vim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-VIMs
83 vim_persistent_info
= {}
85 wimconn_imported
= {} # dictionary with WIM type as key, loaded module as value
86 wim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-WIMs
87 wim_persistent_info
= {}
90 logger
= logging
.getLogger('openmano.nfvo')
97 class NfvoException(httperrors
.HttpMappedError
):
98 """Common Class for NFVO errors"""
104 if task_id
<= last_task_id
:
105 task_id
= last_task_id
+ 0.000001
106 last_task_id
= task_id
107 return "ACTION-{:.6f}".format(task_id
)
108 # return (t.strftime("%Y%m%dT%H%M%S.{}%Z", t.localtime(task_id))).format(int((task_id % 1)*1e6))
111 def new_task(name
, params
, depends
=None):
113 task_id
= get_task_id()
114 task
= {"status": "enqueued", "id": task_id
, "name": name
, "params": params
}
116 task
["depends"] = depends
121 return True if id[:5] == "TASK-" else False
124 def get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_name
, tenant_id
):
125 name
= datacenter_name
[:16]
126 if name
not in vim_threads
["names"]:
127 vim_threads
["names"].append(name
)
130 name
= datacenter_name
[:16] + "." + tenant_name
[:16]
131 if name
not in vim_threads
["names"]:
132 vim_threads
["names"].append(name
)
135 vim_threads
["names"].append(name
)
139 def get_non_used_wim_name(wim_name
, wim_id
, tenant_name
, tenant_id
):
141 if name
not in wim_threads
["names"]:
142 wim_threads
["names"].append(name
)
144 name
= wim_name
[:16] + "." + tenant_name
[:16]
145 if name
not in wim_threads
["names"]:
146 wim_threads
["names"].append(name
)
148 name
= wim_id
+ "-" + tenant_id
149 wim_threads
["names"].append(name
)
153 def start_service(mydb
, persistence
=None, wim
=None):
154 global db
, global_config
155 db
= nfvo_db
.nfvo_db(lock
=db_lock
)
157 db
.connect(global_config
['db_host'], global_config
['db_user'], global_config
['db_passwd'], global_config
['db_name'])
160 persistence
= persistence
or WimPersistence(db
)
162 # Initialize openvim for SDN control
163 # TODO: Avoid static configuration by adding new parameters to openmanod.cfg
164 # TODO: review ovim.py to delete not needed configuration
165 ovim_configuration
= {
166 'logger_name': 'openmano.ovim',
167 'network_vlan_range_start': 1000,
168 'network_vlan_range_end': 4096,
169 'db_name': global_config
["db_ovim_name"],
170 'db_host': global_config
["db_ovim_host"],
171 'db_user': global_config
["db_ovim_user"],
172 'db_passwd': global_config
["db_ovim_passwd"],
175 'network_type': 'bridge',
176 #TODO: log_level_of should not be needed. To be modified in ovim
177 'log_level_of': 'DEBUG'
180 # starts ovim library
181 ovim
= ovim_module
.ovim(ovim_configuration
)
184 wim_engine
= wim
or WimEngine(persistence
)
185 wim_engine
.ovim
= ovim
189 #delete old unneeded vim_wim_actions
193 from_
= 'tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join '\
194 'datacenter_tenants as dt on td.datacenter_tenant_id=dt.uuid'
195 select_
= ('type', 'd.config as config', 'd.uuid as datacenter_id', 'vim_url', 'vim_url_admin',
196 'd.name as datacenter_name', 'dt.uuid as datacenter_tenant_id',
197 'dt.vim_tenant_name as vim_tenant_name', 'dt.vim_tenant_id as vim_tenant_id',
198 'user', 'passwd', 'dt.config as dt_config', 'nfvo_tenant_id')
199 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
)
201 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
202 'datacenter_id': vim
.get('datacenter_id')}
204 extra
.update(yaml
.load(vim
["config"]))
205 if vim
.get('dt_config'):
206 extra
.update(yaml
.load(vim
["dt_config"]))
207 if vim
["type"] not in vimconn_imported
:
210 module
= "vimconn_" + vim
["type"]
211 pkg
= __import__("osm_ro." + module
)
212 vim_conn
= getattr(pkg
, module
)
213 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
214 # vim_conn = imp.load_module(vim["type"], *module_info)
215 vimconn_imported
[vim
["type"]] = vim_conn
216 except (IOError, ImportError) as e
:
217 # if module_info and module_info[0]:
218 # file.close(module_info[0])
219 raise NfvoException("Unknown vim type '{}'. Cannot open file '{}.py'; {}: {}".format(
220 vim
["type"], module
, type(e
).__name
__, str(e
)), httperrors
.Bad_Request
)
222 thread_id
= vim
['datacenter_tenant_id']
223 vim_persistent_info
[thread_id
] = {}
226 # return -httperrors.Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
227 myvim
= vimconn_imported
[ vim
["type"] ].vimconnector(
228 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
229 tenant_id
=vim
['vim_tenant_id'], tenant_name
=vim
['vim_tenant_name'],
230 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
231 user
=vim
['user'], passwd
=vim
['passwd'],
232 config
=extra
, persistent_info
=vim_persistent_info
[thread_id
]
234 except vimconn
.vimconnException
as e
:
236 logger
.error("Cannot launch thread for VIM {} '{}': {}".format(vim
['datacenter_name'],
237 vim
['datacenter_id'], e
))
238 except Exception as e
:
239 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, e
),
240 httperrors
.Internal_Server_Error
)
241 thread_name
= get_non_used_vim_name(vim
['datacenter_name'], vim
['datacenter_id'], vim
['vim_tenant_name'],
242 vim
['vim_tenant_id'])
243 new_thread
= vim_thread
.vim_thread(task_lock
, thread_name
, vim
['datacenter_name'],
244 vim
['datacenter_tenant_id'], db
=db
, db_lock
=db_lock
, ovim
=ovim
)
246 vim_threads
["running"][thread_id
] = new_thread
248 wim_engine
.start_threads()
249 except db_base_Exception
as e
:
250 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
251 except ovim_module
.ovimException
as e
:
253 if message
[:22] == "DATABASE wrong version":
254 message
= "DATABASE wrong version of lib_osm_openvim {msg} -d{dbname} -u{dbuser} -p{dbpass} {ver}' "\
255 "at host {dbhost}".format(
256 msg
=message
[22:-3], dbname
=global_config
["db_ovim_name"],
257 dbuser
=global_config
["db_ovim_user"], dbpass
=global_config
["db_ovim_passwd"],
258 ver
=message
[-3:-1], dbhost
=global_config
["db_ovim_host"])
259 raise NfvoException(message
, httperrors
.Bad_Request
)
263 global ovim
, global_config
266 for thread_id
, thread
in vim_threads
["running"].items():
267 thread
.insert_task("exit")
268 vim_threads
["deleting"][thread_id
] = thread
269 vim_threads
["running"] = {}
272 wim_engine
.stop_threads()
274 if global_config
and global_config
.get("console_thread"):
275 for thread
in global_config
["console_thread"]:
276 thread
.terminate
= True
279 return ("openmanod version {} {}\n(c) Copyright Telefonica".format(global_config
["version"],
280 global_config
["version_date"] ))
284 Clean unused or old entries at database to avoid unlimited growing
285 :param mydb: database connector
288 # get and delete unused vim_wim_actions: all elements deleted, one week before, instance not present
289 now
= t
.time()-3600*24*7
290 instance_action_id
= None
293 actions_to_delete
= mydb
.get_rows(
294 SELECT
=("item", "item_id", "instance_action_id"),
295 FROM
="vim_wim_actions as va join instance_actions as ia on va.instance_action_id=ia.uuid "
296 "left join instance_scenarios as i on ia.instance_id=i.uuid",
297 WHERE
={"va.action": "DELETE", "va.modified_at<": now
, "i.uuid": None,
298 "va.status": ("DONE", "SUPERSEDED")},
301 for to_delete
in actions_to_delete
:
302 mydb
.delete_row(FROM
="vim_wim_actions", WHERE
=to_delete
)
303 if instance_action_id
!= to_delete
["instance_action_id"]:
304 instance_action_id
= to_delete
["instance_action_id"]
305 mydb
.delete_row(FROM
="instance_actions", WHERE
={"uuid": instance_action_id
})
306 nb_deleted
+= len(actions_to_delete
)
307 if len(actions_to_delete
) < 100:
310 mydb
.update_rows("vim_wim_actions", UPDATE
={"worker": None}, WHERE
={"worker<>": None})
313 logger
.debug("Removed {} unused vim_wim_actions".format(nb_deleted
))
316 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
318 return result, content:
319 <0, error_text upon error
320 nb_records, flavor_list on success
323 WHERE_dict
['vnf_id'] = vnf_id
324 if nfvo_tenant
is not None:
325 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
327 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
328 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
329 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
330 #print "get_flavor_list result:", result
331 #print "get_flavor_list content:", content
333 for flavor
in flavors
:
334 flavorList
.append(flavor
['flavor_id'])
338 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
340 Get used images of all vms belonging to this VNFD
341 :param mydb: database conector
342 :param vnf_id: vnfd uuid
343 :param nfvo_tenant: tenant, not used
344 :return: The list of image uuid used
347 vms
= mydb
.get_rows(SELECT
=('image_id','image_list'), FROM
='vms', WHERE
={'vnf_id': vnf_id
})
349 if vm
["image_id"] and vm
["image_id"] not in image_list
:
350 image_list
.append(vm
["image_id"])
352 vm_image_list
= yaml
.load(vm
["image_list"])
353 for image_dict
in vm_image_list
:
354 if image_dict
["image_id"] not in image_list
:
355 image_list
.append(image_dict
["image_id"])
359 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
360 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None, ignore_errors
=False):
361 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
362 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
363 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
364 raise exception upon error
367 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
368 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
369 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
370 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
371 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
372 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
373 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
374 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'
375 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
376 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
377 'user','passwd', 'dt.config as dt_config')
379 from_
= 'datacenters as d'
380 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
382 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
385 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
386 'datacenter_id': vim
.get('datacenter_id'),
387 '_vim_type_internal': vim
.get('type')}
389 extra
.update(yaml
.load(vim
["config"]))
390 if vim
.get('dt_config'):
391 extra
.update(yaml
.load(vim
["dt_config"]))
392 if vim
["type"] not in vimconn_imported
:
395 module
= "vimconn_" + vim
["type"]
396 pkg
= __import__("osm_ro." + module
)
397 vim_conn
= getattr(pkg
, module
)
398 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
399 # vim_conn = imp.load_module(vim["type"], *module_info)
400 vimconn_imported
[vim
["type"]] = vim_conn
401 except (IOError, ImportError) as e
:
402 # if module_info and module_info[0]:
403 # file.close(module_info[0])
405 logger
.error("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
406 vim
["type"], module
, type(e
).__name
__, str(e
)))
408 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
409 vim
["type"], module
, type(e
).__name
__, str(e
)), httperrors
.Bad_Request
)
412 if 'datacenter_tenant_id' in vim
:
413 thread_id
= vim
["datacenter_tenant_id"]
414 if thread_id
not in vim_persistent_info
:
415 vim_persistent_info
[thread_id
] = {}
416 persistent_info
= vim_persistent_info
[thread_id
]
420 # return -httperrors.Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
421 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
422 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
423 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
),
424 tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
425 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
426 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
427 config
=extra
, persistent_info
=persistent_info
429 except Exception as e
:
431 logger
.error("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)))
433 http_code
= httperrors
.Internal_Server_Error
434 if isinstance(e
, vimconn
.vimconnException
):
435 http_code
= e
.http_code
436 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), http_code
)
438 except db_base_Exception
as e
:
439 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
442 def rollback(mydb
, vims
, rollback_list
):
444 #delete things by reverse order
445 for i
in range(len(rollback_list
)-1, -1, -1):
446 item
= rollback_list
[i
]
447 if item
["where"]=="vim":
448 if item
["vim_id"] not in vims
:
450 if is_task_id(item
["uuid"]):
452 vim
= vims
[item
["vim_id"]]
454 if item
["what"]=="image":
455 vim
.delete_image(item
["uuid"])
456 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_vim_id": vim
["id"], "vim_id":item
["uuid"]})
457 elif item
["what"]=="flavor":
458 vim
.delete_flavor(item
["uuid"])
459 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_vim_id": vim
["id"], "vim_id":item
["uuid"]})
460 elif item
["what"]=="network":
461 vim
.delete_network(item
["uuid"])
462 elif item
["what"]=="vm":
463 vim
.delete_vminstance(item
["uuid"])
464 except vimconn
.vimconnException
as e
:
465 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
466 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
467 except db_base_Exception
as e
:
468 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
472 if item
["what"]=="image":
473 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
474 elif item
["what"]=="flavor":
475 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
476 except db_base_Exception
as e
:
477 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
478 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
479 if len(undeleted_items
)==0:
480 return True," Rollback successful."
482 return False," Rollback fails to delete: " + str(undeleted_items
)
485 def check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1):
487 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
489 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
491 #dataplane interfaces
492 for numa
in vnfc
.get("numas",() ):
493 for interface
in numa
.get("interfaces",()):
494 if interface
["name"] in name_dict
:
496 "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
497 vnfc
["name"], interface
["name"]),
498 httperrors
.Bad_Request
)
499 name_dict
[ interface
["name"] ] = "underlay"
501 for interface
in vnfc
.get("bridge-ifaces",() ):
502 if interface
["name"] in name_dict
:
504 "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
505 vnfc
["name"], interface
["name"]),
506 httperrors
.Bad_Request
)
507 name_dict
[ interface
["name"] ] = "overlay"
508 vnfc_interfaces
[ vnfc
["name"] ] = name_dict
509 # check bood-data info
510 # if "boot-data" in vnfc:
511 # # check that user-data is incompatible with users and config-files
512 # if (vnfc["boot-data"].get("users") or vnfc["boot-data"].get("config-files")) and vnfc["boot-data"].get("user-data"):
513 # raise NfvoException(
514 # "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
515 # httperrors.Bad_Request)
517 #check if the info in external_connections matches with the one in the vnfcs
519 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
520 if external_connection
["name"] in name_list
:
522 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
523 external_connection
["name"]),
524 httperrors
.Bad_Request
)
525 name_list
.append(external_connection
["name"])
526 if external_connection
["VNFC"] not in vnfc_interfaces
:
528 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
529 external_connection
["name"], external_connection
["VNFC"]),
530 httperrors
.Bad_Request
)
532 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
534 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
535 external_connection
["name"],
536 external_connection
["local_iface_name"]),
537 httperrors
.Bad_Request
)
539 #check if the info in internal_connections matches with the one in the vnfcs
541 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
542 if internal_connection
["name"] in name_list
:
544 "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection".format(
545 internal_connection
["name"]),
546 httperrors
.Bad_Request
)
547 name_list
.append(internal_connection
["name"])
548 #We should check that internal-connections of type "ptp" have only 2 elements
550 if len(internal_connection
["elements"])>2 and (internal_connection
.get("type") == "ptp" or internal_connection
.get("type") == "e-line"):
552 "Error at 'vnf:internal-connections[name:'{}']:elements', size must be 2 for a '{}' type. Consider change it to '{}' type".format(
553 internal_connection
["name"],
554 'ptp' if vnf_descriptor_version
==1 else 'e-line',
555 'data' if vnf_descriptor_version
==1 else "e-lan"),
556 httperrors
.Bad_Request
)
557 for port
in internal_connection
["elements"]:
559 iface
= port
["local_iface_name"]
560 if vnf
not in vnfc_interfaces
:
562 "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
563 internal_connection
["name"], vnf
),
564 httperrors
.Bad_Request
)
565 if iface
not in vnfc_interfaces
[ vnf
]:
567 "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
568 internal_connection
["name"], iface
),
569 httperrors
.Bad_Request
)
570 return -httperrors
.Bad_Request
,
571 if vnf_descriptor_version
==1 and "type" not in internal_connection
:
572 if vnfc_interfaces
[vnf
][iface
] == "overlay":
573 internal_connection
["type"] = "bridge"
575 internal_connection
["type"] = "data"
576 if vnf_descriptor_version
==2 and "implementation" not in internal_connection
:
577 if vnfc_interfaces
[vnf
][iface
] == "overlay":
578 internal_connection
["implementation"] = "overlay"
580 internal_connection
["implementation"] = "underlay"
581 if (internal_connection
.get("type") == "data" or internal_connection
.get("type") == "ptp" or \
582 internal_connection
.get("implementation") == "underlay") and vnfc_interfaces
[vnf
][iface
] == "overlay":
584 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
585 internal_connection
["name"],
586 iface
, 'bridge' if vnf_descriptor_version
==1 else 'overlay',
587 'data' if vnf_descriptor_version
==1 else 'underlay'),
588 httperrors
.Bad_Request
)
589 if (internal_connection
.get("type") == "bridge" or internal_connection
.get("implementation") == "overlay") and \
590 vnfc_interfaces
[vnf
][iface
] == "underlay":
592 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
593 internal_connection
["name"], iface
,
594 'data' if vnf_descriptor_version
==1 else 'underlay',
595 'bridge' if vnf_descriptor_version
==1 else 'overlay'),
596 httperrors
.Bad_Request
)
599 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=None):
601 if only_create_at_vim
:
602 image_mano_id
= image_dict
['uuid']
603 if return_on_error
== None:
604 return_on_error
= True
606 if image_dict
['location']:
607 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
609 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
611 image_mano_id
= images
[0]['uuid']
613 #create image in MANO DB
614 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
615 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
616 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
618 #temp_image_dict['location'] = image_dict.get('new_location') if image_dict['location'] is None
619 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
620 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
621 #create image at every vim
622 for vim_id
,vim
in vims
.iteritems():
623 datacenter_vim_id
= vim
["config"]["datacenter_tenant_id"]
624 image_created
="false"
626 image_db
= mydb
.get_rows(FROM
="datacenters_images",
627 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'image_id': image_mano_id
})
628 #look at VIM if this image exist
630 if image_dict
['location'] is not None:
631 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
634 filter_dict
['name'] = image_dict
['universal_name']
635 if image_dict
.get('checksum') != None:
636 filter_dict
['checksum'] = image_dict
['checksum']
637 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
638 vim_images
= vim
.get_image_list(filter_dict
)
639 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
640 if len(vim_images
) > 1:
641 raise vimconn
.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict
)), httperrors
.Conflict
)
642 elif len(vim_images
) == 0:
643 raise vimconn
.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict
)))
645 #logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
646 image_vim_id
= vim_images
[0]['id']
648 except vimconn
.vimconnNotFoundException
as e
:
649 #Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
651 #image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
652 if image_dict
['location']:
653 image_vim_id
= vim
.new_image(image_dict
)
654 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
657 #If we reach this point, then the image has image name, and optionally checksum, and could not be found
658 raise vimconn
.vimconnException(str(e
))
659 except vimconn
.vimconnException
as e
:
661 logger
.error("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
664 logger
.warn("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
666 except vimconn
.vimconnException
as e
:
668 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
670 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
673 #if we reach here, the image has been created or existed
675 #add new vim_id at datacenters_images
676 mydb
.new_row('datacenters_images', {'datacenter_vim_id': datacenter_vim_id
,
677 'image_id':image_mano_id
,
678 'vim_id': image_vim_id
,
679 'created':image_created
})
680 elif image_db
[0]["vim_id"]!=image_vim_id
:
681 #modify existing vim_id at datacenters_images
682 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_vim_id':vim_id
, 'image_id':image_mano_id
})
684 return image_vim_id
if only_create_at_vim
else image_mano_id
687 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
688 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',0),
689 'ram':flavor_dict
.get('ram'),
690 'vcpus':flavor_dict
.get('vcpus'),
692 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
693 del flavor_dict
['extended']
694 if 'extended' in flavor_dict
:
695 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
697 #look if flavor exist
698 if only_create_at_vim
:
699 flavor_mano_id
= flavor_dict
['uuid']
700 if return_on_error
== None:
701 return_on_error
= True
703 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
705 flavor_mano_id
= flavors
[0]['uuid']
708 #create one by one the images of aditional disks
709 dev_image_list
=[] #list of images
710 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
712 for device
in flavor_dict
['extended'].get('devices',[]):
713 if "image" not in device
and "image name" not in device
:
716 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
717 image_dict
['universal_name']=device
.get('image name')
718 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
719 image_dict
['location']=device
.get('image')
720 #image_dict['new_location']=vnfc.get('image location')
721 image_dict
['checksum']=device
.get('image checksum')
722 image_metadata_dict
= device
.get('image metadata', None)
723 image_metadata_str
= None
724 if image_metadata_dict
!= None:
725 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
726 image_dict
['metadata']=image_metadata_str
727 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
728 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
729 dev_image_list
.append(image_id
)
731 temp_flavor_dict
['name'] = flavor_dict
['name']
732 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
733 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
734 flavor_mano_id
= content
735 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
736 #create flavor at every vim
737 if 'uuid' in flavor_dict
:
738 del flavor_dict
['uuid']
740 for vim_id
,vim
in vims
.items():
741 datacenter_vim_id
= vim
["config"]["datacenter_tenant_id"]
742 flavor_created
="false"
744 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors",
745 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
})
746 #look at VIM if this flavor exist SKIPPED
747 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
749 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
753 # Create the flavor in VIM
754 # Translate images at devices from MANO id to VIM id
756 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
757 # make a copy of original devices
760 for device
in flavor_dict
["extended"].get("devices",[]):
763 devices_original
.append(dev
)
764 if 'image' in device
:
766 if 'image metadata' in device
:
767 del device
['image metadata']
768 if 'image checksum' in device
:
769 del device
['image checksum']
771 for index
in range(0,len(devices_original
)) :
772 device
=devices_original
[index
]
773 if "image" not in device
and "image name" not in device
:
774 # if 'size' in device:
775 disk_list
.append({'size': device
.get('size', default_volume_size
), 'name': device
.get('name')})
778 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
779 image_dict
['universal_name']=device
.get('image name')
780 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
781 image_dict
['location']=device
.get('image')
782 # image_dict['new_location']=device.get('image location')
783 image_dict
['checksum']=device
.get('image checksum')
784 image_metadata_dict
= device
.get('image metadata', None)
785 image_metadata_str
= None
786 if image_metadata_dict
!= None:
787 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
788 image_dict
['metadata']=image_metadata_str
789 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
790 image_dict
["uuid"]=image_mano_id
791 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
793 #save disk information (image must be based on and size
794 disk_list
.append({'image_id': image_vim_id
, 'size': device
.get('size', default_volume_size
)})
796 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
799 #check that this vim_id exist in VIM, if not create
800 flavor_vim_id
=flavor_db
[0]["vim_id"]
802 vim
.get_flavor(flavor_vim_id
)
803 continue #flavor exist
804 except vimconn
.vimconnException
:
806 #create flavor at vim
807 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
810 flavor_vim_id
=vim
.get_flavor_id_from_data(flavor_dict
)
811 flavor_created
="false"
812 except vimconn
.vimconnException
as e
:
815 if not flavor_vim_id
:
816 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
817 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
818 flavor_created
="true"
819 except vimconn
.vimconnException
as e
:
821 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
823 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
826 #if reach here the flavor has been create or exist
827 if len(flavor_db
)==0:
828 #add new vim_id at datacenters_flavors
829 extended_devices_yaml
= None
830 if len(disk_list
) > 0:
831 extended_devices
= dict()
832 extended_devices
['disks'] = disk_list
833 extended_devices_yaml
= yaml
.safe_dump(extended_devices
,default_flow_style
=True,width
=256)
834 mydb
.new_row('datacenters_flavors',
835 {'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
, 'vim_id': flavor_vim_id
,
836 'created': flavor_created
, 'extended': extended_devices_yaml
})
837 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
838 #modify existing vim_id at datacenters_flavors
839 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
},
840 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
})
842 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
845 def get_str(obj
, field
, length
):
847 Obtain the str value,
852 value
= obj
.get(field
)
853 if value
is not None:
854 value
= str(value
)[:length
]
857 def _lookfor_or_create_image(db_image
, mydb
, descriptor
):
859 fill image content at db_image dictionary. Check if the image with this image and checksum exist
860 :param db_image: dictionary to insert data
861 :param mydb: database connector
862 :param descriptor: yang descriptor
863 :return: uuid if the image exist at DB, or None if a new image must be created with the data filled at db_image
866 db_image
["name"] = get_str(descriptor
, "image", 255)
867 db_image
["checksum"] = get_str(descriptor
, "image-checksum", 32)
868 if not db_image
["checksum"]: # Ensure that if empty string, None is stored
869 db_image
["checksum"] = None
870 if db_image
["name"].startswith("/"):
871 db_image
["location"] = db_image
["name"]
872 existing_images
= mydb
.get_rows(FROM
="images", WHERE
={'location': db_image
["location"]})
874 db_image
["universal_name"] = db_image
["name"]
875 existing_images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name': db_image
['universal_name'],
876 'checksum': db_image
['checksum']})
878 return existing_images
[0]["uuid"]
880 image_uuid
= str(uuid4())
881 db_image
["uuid"] = image_uuid
884 def get_resource_allocation_params(quota_descriptor
):
886 read the quota_descriptor from vnfd and fetch the resource allocation properties from the descriptor object
887 :param quota_descriptor: cpu/mem/vif/disk-io quota descriptor
888 :return: quota params for limit, reserve, shares from the descriptor object
891 if quota_descriptor
.get("limit"):
892 quota
["limit"] = int(quota_descriptor
["limit"])
893 if quota_descriptor
.get("reserve"):
894 quota
["reserve"] = int(quota_descriptor
["reserve"])
895 if quota_descriptor
.get("shares"):
896 quota
["shares"] = int(quota_descriptor
["shares"])
899 def new_vnfd_v3(mydb
, tenant_id
, vnf_descriptor
):
901 Parses an OSM IM vnfd_catalog and insert at DB
904 :param vnf_descriptor:
905 :return: The list of cretated vnf ids
908 myvnfd
= vnfd_catalog
.vnfd()
910 pybindJSONDecoder
.load_ietf_json(vnf_descriptor
, None, None, obj
=myvnfd
, path_helper
=True,
912 except Exception as e
:
913 raise NfvoException("Error. Invalid VNF descriptor format " + str(e
), httperrors
.Bad_Request
)
921 db_ip_profiles_index
= 0
925 vnfd_catalog_descriptor
= vnf_descriptor
.get("vnfd:vnfd-catalog")
926 if not vnfd_catalog_descriptor
:
927 vnfd_catalog_descriptor
= vnf_descriptor
.get("vnfd-catalog")
928 vnfd_descriptor_list
= vnfd_catalog_descriptor
.get("vnfd")
929 if not vnfd_descriptor_list
:
930 vnfd_descriptor_list
= vnfd_catalog_descriptor
.get("vnfd:vnfd")
931 for vnfd_yang
in myvnfd
.vnfd_catalog
.vnfd
.itervalues():
932 vnfd
= vnfd_yang
.get()
935 vnf_uuid
= str(uuid4())
936 uuid_list
.append(vnf_uuid
)
937 vnfd_uuid_list
.append(vnf_uuid
)
938 vnfd_id
= get_str(vnfd
, "id", 255)
942 "name": get_str(vnfd
, "name", 255),
943 "description": get_str(vnfd
, "description", 255),
944 "tenant_id": tenant_id
,
945 "vendor": get_str(vnfd
, "vendor", 255),
946 "short_name": get_str(vnfd
, "short-name", 255),
947 "descriptor": str(vnf_descriptor
)[:60000]
950 for vnfd_descriptor
in vnfd_descriptor_list
:
951 if vnfd_descriptor
["id"] == str(vnfd
["id"]):
954 # table ip_profiles (ip-profiles)
955 ip_profile_name2db_table_index
= {}
956 for ip_profile
in vnfd
.get("ip-profiles").itervalues():
958 "ip_version": str(ip_profile
["ip-profile-params"].get("ip-version", "ipv4")),
959 "subnet_address": str(ip_profile
["ip-profile-params"].get("subnet-address")),
960 "gateway_address": str(ip_profile
["ip-profile-params"].get("gateway-address")),
961 "dhcp_enabled": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("enabled", True)),
962 "dhcp_start_address": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("start-address")),
963 "dhcp_count": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("count")),
966 for dns
in ip_profile
["ip-profile-params"]["dns-server"].itervalues():
967 dns_list
.append(str(dns
.get("address")))
968 db_ip_profile
["dns_address"] = ";".join(dns_list
)
969 if ip_profile
["ip-profile-params"].get('security-group'):
970 db_ip_profile
["security_group"] = ip_profile
["ip-profile-params"]['security-group']
971 ip_profile_name2db_table_index
[str(ip_profile
["name"])] = db_ip_profiles_index
972 db_ip_profiles_index
+= 1
973 db_ip_profiles
.append(db_ip_profile
)
975 # table nets (internal-vld)
976 net_id2uuid
= {} # for mapping interface with network
977 for vld
in vnfd
.get("internal-vld").itervalues():
978 net_uuid
= str(uuid4())
979 uuid_list
.append(net_uuid
)
981 "name": get_str(vld
, "name", 255),
984 "description": get_str(vld
, "description", 255),
985 "osm_id": get_str(vld
, "id", 255),
986 "type": "bridge", # TODO adjust depending on connection point type
988 net_id2uuid
[vld
.get("id")] = net_uuid
989 db_nets
.append(db_net
)
990 # ip-profile, link db_ip_profile with db_sce_net
991 if vld
.get("ip-profile-ref"):
992 ip_profile_name
= vld
.get("ip-profile-ref")
993 if ip_profile_name
not in ip_profile_name2db_table_index
:
994 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vld[{}]':'ip-profile-ref':"
995 "'{}'. Reference to a non-existing 'ip_profiles'".format(
996 str(vnfd
["id"]), str(vld
["id"]), str(vld
["ip-profile-ref"])),
997 httperrors
.Bad_Request
)
998 db_ip_profiles
[ip_profile_name2db_table_index
[ip_profile_name
]]["net_id"] = net_uuid
999 else: #check no ip-address has been defined
1000 for icp
in vld
.get("internal-connection-point").itervalues():
1001 if icp
.get("ip-address"):
1002 raise NfvoException("Error at 'vnfd[{}]':'vld[{}]':'internal-connection-point[{}]' "
1003 "contains an ip-address but no ip-profile has been defined at VLD".format(
1004 str(vnfd
["id"]), str(vld
["id"]), str(icp
["id"])),
1005 httperrors
.Bad_Request
)
1007 # connection points vaiable declaration
1008 cp_name2iface_uuid
= {}
1010 cp_name2vm_uuid
= {}
1011 cp_name2db_interface
= {}
1012 vdu_id2cp_name
= {} # stored only when one external connection point is presented at this VDU
1016 vdu_id2db_table_index
= {}
1018 for vdu
in vnfd
.get("vdu").itervalues():
1020 for vdu_descriptor
in vnfd_descriptor
["vdu"]:
1021 if vdu_descriptor
["id"] == str(vdu
["id"]):
1023 vm_uuid
= str(uuid4())
1024 uuid_list
.append(vm_uuid
)
1025 vdu_id
= get_str(vdu
, "id", 255)
1029 "name": get_str(vdu
, "name", 255),
1030 "description": get_str(vdu
, "description", 255),
1031 "pdu_type": get_str(vdu
, "pdu-type", 255),
1034 vdu_id2uuid
[db_vm
["osm_id"]] = vm_uuid
1035 vdu_id2db_table_index
[db_vm
["osm_id"]] = db_vms_index
1036 if vdu
.get("count"):
1037 db_vm
["count"] = int(vdu
["count"])
1040 image_present
= False
1041 if vdu
.get("image"):
1042 image_present
= True
1044 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, vdu
)
1046 image_uuid
= db_image
["uuid"]
1047 db_images
.append(db_image
)
1048 db_vm
["image_id"] = image_uuid
1049 if vdu
.get("alternative-images"):
1050 vm_alternative_images
= []
1051 for alt_image
in vdu
.get("alternative-images").itervalues():
1053 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, alt_image
)
1055 image_uuid
= db_image
["uuid"]
1056 db_images
.append(db_image
)
1057 vm_alternative_images
.append({
1058 "image_id": image_uuid
,
1059 "vim_type": str(alt_image
["vim-type"]),
1060 # "universal_name": str(alt_image["image"]),
1061 # "checksum": str(alt_image["image-checksum"]) if alt_image.get("image-checksum") else None
1064 db_vm
["image_list"] = yaml
.safe_dump(vm_alternative_images
, default_flow_style
=True, width
=256)
1068 if vdu
.get("volumes"):
1069 for volume_key
in vdu
["volumes"]:
1070 volume
= vdu
["volumes"][volume_key
]
1071 if not image_present
:
1072 # Convert the first volume to vnfc.image
1073 image_present
= True
1075 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, volume
)
1077 image_uuid
= db_image
["uuid"]
1078 db_images
.append(db_image
)
1079 db_vm
["image_id"] = image_uuid
1081 # Add Openmano devices
1082 device
= {"name": str(volume
.get("name"))}
1083 device
["type"] = str(volume
.get("device-type"))
1084 if volume
.get("size"):
1085 device
["size"] = int(volume
["size"])
1086 if volume
.get("image"):
1087 device
["image name"] = str(volume
["image"])
1088 if volume
.get("image-checksum"):
1089 device
["image checksum"] = str(volume
["image-checksum"])
1091 devices
.append(device
)
1093 if not db_vm
.get("image_id"):
1094 if not db_vm
["pdu_type"]:
1095 raise NfvoException("Not defined image for VDU")
1096 # create a fake image
1100 if vdu
.get("cloud-init"):
1101 boot_data
["user-data"] = str(vdu
["cloud-init"])
1102 elif vdu
.get("cloud-init-file"):
1103 # TODO Where this file content is present???
1104 # boot_data["user-data"] = vnfd_yang.files[vdu["cloud-init-file"]]
1105 boot_data
["user-data"] = str(vdu
["cloud-init-file"])
1107 if vdu
.get("supplemental-boot-data"):
1108 if vdu
["supplemental-boot-data"].get('boot-data-drive'):
1109 boot_data
['boot-data-drive'] = True
1110 if vdu
["supplemental-boot-data"].get('config-file'):
1111 om_cfgfile_list
= list()
1112 for custom_config_file
in vdu
["supplemental-boot-data"]['config-file'].itervalues():
1113 # TODO Where this file content is present???
1114 cfg_source
= str(custom_config_file
["source"])
1115 om_cfgfile_list
.append({"dest": custom_config_file
["dest"],
1116 "content": cfg_source
})
1117 boot_data
['config-files'] = om_cfgfile_list
1119 db_vm
["boot_data"] = yaml
.safe_dump(boot_data
, default_flow_style
=True, width
=256)
1121 db_vms
.append(db_vm
)
1124 # table interfaces (internal/external interfaces)
1125 flavor_epa_interfaces
= []
1126 # for iface in chain(vdu.get("internal-interface").itervalues(), vdu.get("external-interface").itervalues()):
1127 for iface
in vdu
.get("interface").itervalues():
1128 flavor_epa_interface
= {}
1129 iface_uuid
= str(uuid4())
1130 uuid_list
.append(iface_uuid
)
1133 "internal_name": get_str(iface
, "name", 255),
1136 flavor_epa_interface
["name"] = db_interface
["internal_name"]
1137 if iface
.get("virtual-interface").get("vpci"):
1138 db_interface
["vpci"] = get_str(iface
.get("virtual-interface"), "vpci", 12)
1139 flavor_epa_interface
["vpci"] = db_interface
["vpci"]
1141 if iface
.get("virtual-interface").get("bandwidth"):
1142 bps
= int(iface
.get("virtual-interface").get("bandwidth"))
1143 db_interface
["bw"] = int(math
.ceil(bps
/1000000.0))
1144 flavor_epa_interface
["bandwidth"] = "{} Mbps".format(db_interface
["bw"])
1146 if iface
.get("virtual-interface").get("type") == "OM-MGMT":
1147 db_interface
["type"] = "mgmt"
1148 elif iface
.get("virtual-interface").get("type") in ("VIRTIO", "E1000", "PARAVIRT"):
1149 db_interface
["type"] = "bridge"
1150 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1151 elif iface
.get("virtual-interface").get("type") in ("SR-IOV", "PCI-PASSTHROUGH"):
1152 db_interface
["type"] = "data"
1153 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1154 flavor_epa_interface
["dedicated"] = "no" if iface
["virtual-interface"]["type"] == "SR-IOV" \
1156 flavor_epa_interfaces
.append(flavor_epa_interface
)
1158 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vdu[{}]':'interface':'virtual"
1159 "-interface':'type':'{}'. Interface type is not supported".format(
1160 vnfd_id
, vdu_id
, iface
.get("virtual-interface").get("type")),
1161 httperrors
.Bad_Request
)
1163 if iface
.get("mgmt-interface"):
1164 db_interface
["type"] = "mgmt"
1166 if iface
.get("external-connection-point-ref"):
1168 cp
= vnfd
.get("connection-point")[iface
.get("external-connection-point-ref")]
1169 db_interface
["external_name"] = get_str(cp
, "name", 255)
1170 cp_name2iface_uuid
[db_interface
["external_name"]] = iface_uuid
1171 cp_name2vdu_id
[db_interface
["external_name"]] = vdu_id
1172 cp_name2vm_uuid
[db_interface
["external_name"]] = vm_uuid
1173 cp_name2db_interface
[db_interface
["external_name"]] = db_interface
1174 for cp_descriptor
in vnfd_descriptor
["connection-point"]:
1175 if cp_descriptor
["name"] == db_interface
["external_name"]:
1180 if vdu_id
in vdu_id2cp_name
:
1181 vdu_id2cp_name
[vdu_id
] = None # more than two connecdtion point for this VDU
1183 vdu_id2cp_name
[vdu_id
] = db_interface
["external_name"]
1186 if str(cp_descriptor
.get("port-security-enabled")).lower() == "false":
1187 db_interface
["port_security"] = 0
1188 elif str(cp_descriptor
.get("port-security-enabled")).lower() == "true":
1189 db_interface
["port_security"] = 1
1191 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1192 "'interface[{iface}]':'vnfd-connection-point-ref':'{cp}' is not present"
1193 " at connection-point".format(
1194 vnf
=vnfd_id
, vdu
=vdu_id
, iface
=iface
["name"],
1195 cp
=iface
.get("vnfd-connection-point-ref")),
1196 httperrors
.Bad_Request
)
1197 elif iface
.get("internal-connection-point-ref"):
1199 for icp_descriptor
in vdu_descriptor
["internal-connection-point"]:
1200 if icp_descriptor
["id"] == str(iface
.get("internal-connection-point-ref")):
1203 raise KeyError("does not exist at vdu:internal-connection-point")
1206 for vld
in vnfd
.get("internal-vld").itervalues():
1207 for cp
in vld
.get("internal-connection-point").itervalues():
1208 if cp
.get("id-ref") == iface
.get("internal-connection-point-ref"):
1210 raise KeyError("is referenced by more than one 'internal-vld'")
1214 raise KeyError("is not referenced by any 'internal-vld'")
1216 db_interface
["net_id"] = net_id2uuid
[icp_vld
.get("id")]
1217 if str(icp_descriptor
.get("port-security-enabled")).lower() == "false":
1218 db_interface
["port_security"] = 0
1219 elif str(icp_descriptor
.get("port-security-enabled")).lower() == "true":
1220 db_interface
["port_security"] = 1
1221 if icp
.get("ip-address"):
1222 if not icp_vld
.get("ip-profile-ref"):
1224 db_interface
["ip_address"] = str(icp
.get("ip-address"))
1225 except KeyError as e
:
1226 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1227 "'interface[{iface}]':'internal-connection-point-ref':'{cp}'"
1229 vnf
=vnfd_id
, vdu
=vdu_id
, iface
=iface
["name"],
1230 cp
=iface
.get("internal-connection-point-ref"), msg
=str(e
)),
1231 httperrors
.Bad_Request
)
1232 if iface
.get("position"):
1233 db_interface
["created_at"] = int(iface
.get("position")) * 50
1234 if iface
.get("mac-address"):
1235 db_interface
["mac"] = str(iface
.get("mac-address"))
1236 db_interfaces
.append(db_interface
)
1240 "name": get_str(vdu
, "name", 250) + "-flv",
1241 "vcpus": int(vdu
["vm-flavor"].get("vcpu-count", 1)),
1242 "ram": int(vdu
["vm-flavor"].get("memory-mb", 1)),
1243 "disk": int(vdu
["vm-flavor"].get("storage-gb", 0)),
1245 # TODO revise the case of several numa-node-policy node
1249 extended
["devices"] = devices
1250 if flavor_epa_interfaces
:
1251 numa
["interfaces"] = flavor_epa_interfaces
1252 if vdu
.get("guest-epa"): # TODO or dedicated_int:
1253 epa_vcpu_set
= False
1254 if vdu
["guest-epa"].get("numa-node-policy"): # TODO or dedicated_int:
1255 numa_node_policy
= vdu
["guest-epa"].get("numa-node-policy")
1256 if numa_node_policy
.get("node"):
1257 numa_node
= numa_node_policy
["node"].values()[0]
1258 if numa_node
.get("num-cores"):
1259 numa
["cores"] = numa_node
["num-cores"]
1261 if numa_node
.get("paired-threads"):
1262 if numa_node
["paired-threads"].get("num-paired-threads"):
1263 numa
["paired-threads"] = int(numa_node
["paired-threads"]["num-paired-threads"])
1265 if len(numa_node
["paired-threads"].get("paired-thread-ids")):
1266 numa
["paired-threads-id"] = []
1267 for pair
in numa_node
["paired-threads"]["paired-thread-ids"].itervalues():
1268 numa
["paired-threads-id"].append(
1269 (str(pair
["thread-a"]), str(pair
["thread-b"]))
1271 if numa_node
.get("num-threads"):
1272 numa
["threads"] = int(numa_node
["num-threads"])
1274 if numa_node
.get("memory-mb"):
1275 numa
["memory"] = max(int(numa_node
["memory-mb"] / 1024), 1)
1276 if vdu
["guest-epa"].get("mempage-size"):
1277 if vdu
["guest-epa"]["mempage-size"] != "SMALL":
1278 numa
["memory"] = max(int(db_flavor
["ram"] / 1024), 1)
1279 if vdu
["guest-epa"].get("cpu-pinning-policy") and not epa_vcpu_set
:
1280 if vdu
["guest-epa"]["cpu-pinning-policy"] == "DEDICATED":
1281 if vdu
["guest-epa"].get("cpu-thread-pinning-policy") and \
1282 vdu
["guest-epa"]["cpu-thread-pinning-policy"] != "PREFER":
1283 numa
["cores"] = max(db_flavor
["vcpus"], 1)
1285 numa
["threads"] = max(db_flavor
["vcpus"], 1)
1287 if vdu
["guest-epa"].get("cpu-quota") and not epa_vcpu_set
:
1288 cpuquota
= get_resource_allocation_params(vdu
["guest-epa"].get("cpu-quota"))
1290 extended
["cpu-quota"] = cpuquota
1291 if vdu
["guest-epa"].get("mem-quota"):
1292 vduquota
= get_resource_allocation_params(vdu
["guest-epa"].get("mem-quota"))
1294 extended
["mem-quota"] = vduquota
1295 if vdu
["guest-epa"].get("disk-io-quota"):
1296 diskioquota
= get_resource_allocation_params(vdu
["guest-epa"].get("disk-io-quota"))
1298 extended
["disk-io-quota"] = diskioquota
1299 if vdu
["guest-epa"].get("vif-quota"):
1300 vifquota
= get_resource_allocation_params(vdu
["guest-epa"].get("vif-quota"))
1302 extended
["vif-quota"] = vifquota
1304 extended
["numas"] = [numa
]
1306 extended_text
= yaml
.safe_dump(extended
, default_flow_style
=True, width
=256)
1307 db_flavor
["extended"] = extended_text
1308 # look if flavor exist
1309 temp_flavor_dict
= {'disk': db_flavor
.get('disk', 0),
1310 'ram': db_flavor
.get('ram'),
1311 'vcpus': db_flavor
.get('vcpus'),
1312 'extended': db_flavor
.get('extended')
1314 existing_flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
1315 if existing_flavors
:
1316 flavor_uuid
= existing_flavors
[0]["uuid"]
1318 flavor_uuid
= str(uuid4())
1319 uuid_list
.append(flavor_uuid
)
1320 db_flavor
["uuid"] = flavor_uuid
1321 db_flavors
.append(db_flavor
)
1322 db_vm
["flavor_id"] = flavor_uuid
1324 # VNF affinity and antiaffinity
1325 for pg
in vnfd
.get("placement-groups").itervalues():
1326 pg_name
= get_str(pg
, "name", 255)
1327 for vdu
in pg
.get("member-vdus").itervalues():
1328 vdu_id
= get_str(vdu
, "member-vdu-ref", 255)
1329 if vdu_id
not in vdu_id2db_table_index
:
1330 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'placement-groups[{pg}]':"
1331 "'member-vdus':'{vdu}'. Reference to a non-existing vdu".format(
1332 vnf
=vnfd_id
, pg
=pg_name
, vdu
=vdu_id
),
1333 httperrors
.Bad_Request
)
1334 db_vms
[vdu_id2db_table_index
[vdu_id
]]["availability_zone"] = pg_name
1335 # TODO consider the case of isolation and not colocation
1336 # if pg.get("strategy") == "ISOLATION":
1338 # VNF mgmt configuration
1339 if vnfd
["mgmt-interface"].get("vdu-id"):
1340 mgmt_vdu_id
= get_str(vnfd
["mgmt-interface"], "vdu-id", 255)
1341 if mgmt_vdu_id
not in vdu_id2uuid
:
1342 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'vdu-id':"
1343 "'{vdu}'. Reference to a non-existing vdu".format(
1344 vnf
=vnfd_id
, vdu
=mgmt_vdu_id
),
1345 httperrors
.Bad_Request
)
1346 mgmt_access
["vm_id"] = vdu_id2uuid
[vnfd
["mgmt-interface"]["vdu-id"]]
1347 mgmt_access
["vdu-id"] = vnfd
["mgmt-interface"]["vdu-id"]
1348 # if only one cp is defined by this VDU, mark this interface as of type "mgmt"
1349 if vdu_id2cp_name
.get(mgmt_vdu_id
):
1350 if cp_name2db_interface
[vdu_id2cp_name
[mgmt_vdu_id
]]:
1351 cp_name2db_interface
[vdu_id2cp_name
[mgmt_vdu_id
]]["type"] = "mgmt"
1353 if vnfd
["mgmt-interface"].get("ip-address"):
1354 mgmt_access
["ip-address"] = str(vnfd
["mgmt-interface"].get("ip-address"))
1355 if vnfd
["mgmt-interface"].get("cp"):
1356 if vnfd
["mgmt-interface"]["cp"] not in cp_name2iface_uuid
:
1357 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'cp'['{cp}']. "
1358 "Reference to a non-existing connection-point".format(
1359 vnf
=vnfd_id
, cp
=vnfd
["mgmt-interface"]["cp"]),
1360 httperrors
.Bad_Request
)
1361 mgmt_access
["vm_id"] = cp_name2vm_uuid
[vnfd
["mgmt-interface"]["cp"]]
1362 mgmt_access
["interface_id"] = cp_name2iface_uuid
[vnfd
["mgmt-interface"]["cp"]]
1363 mgmt_access
["vdu-id"] = cp_name2vdu_id
[vnfd
["mgmt-interface"]["cp"]]
1364 # mark this interface as of type mgmt
1365 if cp_name2db_interface
[vnfd
["mgmt-interface"]["cp"]]:
1366 cp_name2db_interface
[vnfd
["mgmt-interface"]["cp"]]["type"] = "mgmt"
1368 default_user
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1371 mgmt_access
["default_user"] = default_user
1373 required
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1376 mgmt_access
["required"] = required
1378 password_
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}),
1381 mgmt_access
["password"] = password_
1384 db_vnf
["mgmt_access"] = yaml
.safe_dump(mgmt_access
, default_flow_style
=True, width
=256)
1386 db_vnfs
.append(db_vnf
)
1390 {"images": db_images
},
1391 {"flavors": db_flavors
},
1392 {"ip_profiles": db_ip_profiles
},
1394 {"interfaces": db_interfaces
},
1397 logger
.debug("create_vnf Deployment done vnfDict: %s",
1398 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
1399 mydb
.new_rows(db_tables
, uuid_list
)
1400 return vnfd_uuid_list
1401 except NfvoException
:
1403 except Exception as e
:
1404 logger
.error("Exception {}".format(e
))
1405 raise # NfvoException("Exception {}".format(e), httperrors.Bad_Request)
1408 @deprecated("Use new_vnfd_v3")
1409 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
1410 global global_config
1412 # Step 1. Check the VNF descriptor
1413 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
1414 # Step 2. Check tenant exist
1416 if tenant_id
!= "any":
1417 check_tenant(mydb
, tenant_id
)
1418 if "tenant_id" in vnf_descriptor
["vnf"]:
1419 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1420 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1421 httperrors
.Unauthorized
)
1423 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1424 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1425 if global_config
["auto_push_VNF_to_VIMs"]:
1426 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1428 # Step 4. Review the descriptor and add missing fields
1429 #print vnf_descriptor
1430 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1431 vnf_name
= vnf_descriptor
['vnf']['name']
1432 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1433 if "physical" in vnf_descriptor
['vnf']:
1434 del vnf_descriptor
['vnf']['physical']
1435 #print vnf_descriptor
1437 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1438 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1439 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1441 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1442 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1443 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1445 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1446 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1448 VNFCitem
["name"] = vnfc
['name']
1449 VNFCitem
["availability_zone"] = vnfc
.get('availability_zone')
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 -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1481 # return -httperrors.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)
1525 # Step 7. Storing the VNF descriptor in the repository
1526 if "descriptor" not in vnf_descriptor
["vnf"]:
1527 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1529 # Step 8. Adding the VNF to the NFVO DB
1530 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1532 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1533 _
, message
= rollback(mydb
, vims
, rollback_list
)
1534 if isinstance(e
, db_base_Exception
):
1535 error_text
= "Exception at database"
1536 elif isinstance(e
, KeyError):
1537 error_text
= "KeyError exception "
1538 e
.http_code
= httperrors
.Internal_Server_Error
1540 error_text
= "Exception at VIM"
1541 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1542 #logger.error("start_scenario %s", error_text)
1543 raise NfvoException(error_text
, e
.http_code
)
1546 @deprecated("Use new_vnfd_v3")
1547 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
1548 global global_config
1550 # Step 1. Check the VNF descriptor
1551 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
1552 # Step 2. Check tenant exist
1554 if tenant_id
!= "any":
1555 check_tenant(mydb
, tenant_id
)
1556 if "tenant_id" in vnf_descriptor
["vnf"]:
1557 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1558 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1559 httperrors
.Unauthorized
)
1561 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1562 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1563 if global_config
["auto_push_VNF_to_VIMs"]:
1564 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1566 # Step 4. Review the descriptor and add missing fields
1567 #print vnf_descriptor
1568 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1569 vnf_name
= vnf_descriptor
['vnf']['name']
1570 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1571 if "physical" in vnf_descriptor
['vnf']:
1572 del vnf_descriptor
['vnf']['physical']
1573 #print vnf_descriptor
1575 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1576 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1577 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1579 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1580 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1581 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1583 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1584 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1586 VNFCitem
["name"] = vnfc
['name']
1587 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
1589 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1592 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1593 myflavorDict
["description"] = VNFCitem
["description"]
1594 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1595 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1596 myflavorDict
["disk"] = vnfc
.get("disk", 0)
1597 myflavorDict
["extended"] = {}
1599 devices
= vnfc
.get("devices")
1601 myflavorDict
["extended"]["devices"] = devices
1604 # 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
1605 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1607 # Previous code has been commented
1608 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1609 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1610 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1611 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1613 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1615 # print "Error creating flavor: unknown processor model. Rollback successful."
1616 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1618 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1619 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1621 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1622 myflavorDict
['extended']['numas'] = vnfc
['numas']
1626 # Step 6.2 New flavors are created in the VIM
1627 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1629 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1630 VNFCitem
["flavor_id"] = flavor_id
1631 VNFCDict
[vnfc
['name']] = VNFCitem
1633 logger
.debug("Creating new images in the VIM for each VNFC")
1634 # Step 6.3 New images are created in the VIM
1635 #For each VNFC, we must create the appropriate image.
1636 #This "for" loop might be integrated with the previous one
1637 #In case this integration is made, the VNFCDict might become a VNFClist.
1638 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1639 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1641 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1642 image_dict
['universal_name']=vnfc
.get('image name')
1643 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1644 image_dict
['location']=vnfc
.get('VNFC image')
1645 #image_dict['new_location']=vnfc.get('image location')
1646 image_dict
['checksum']=vnfc
.get('image checksum')
1647 image_metadata_dict
= vnfc
.get('image metadata', None)
1648 image_metadata_str
= None
1649 if image_metadata_dict
is not None:
1650 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1651 image_dict
['metadata']=image_metadata_str
1652 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1653 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1654 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1655 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1656 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1657 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1658 if vnfc
.get("boot-data"):
1659 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1661 # Step 7. Storing the VNF descriptor in the repository
1662 if "descriptor" not in vnf_descriptor
["vnf"]:
1663 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1665 # Step 8. Adding the VNF to the NFVO DB
1666 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1668 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1669 _
, message
= rollback(mydb
, vims
, rollback_list
)
1670 if isinstance(e
, db_base_Exception
):
1671 error_text
= "Exception at database"
1672 elif isinstance(e
, KeyError):
1673 error_text
= "KeyError exception "
1674 e
.http_code
= httperrors
.Internal_Server_Error
1676 error_text
= "Exception at VIM"
1677 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1678 #logger.error("start_scenario %s", error_text)
1679 raise NfvoException(error_text
, e
.http_code
)
1682 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
1683 #check valid tenant_id
1684 check_tenant(mydb
, tenant_id
)
1687 if tenant_id
!= "any":
1688 where_or
["tenant_id"] = tenant_id
1689 where_or
["public"] = True
1690 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1692 vnf_id
= vnf
["uuid"]
1693 filter_keys
= ('uuid', 'name', 'description', 'public', "tenant_id", "osm_id", "created_at")
1694 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
1695 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
1696 data
={'vnf' : filtered_content
}
1698 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
1699 SELECT
=('vms.uuid as uuid', 'vms.osm_id as osm_id', 'vms.name as name', 'vms.description as description',
1701 WHERE
={'vnfs.uuid': vnf_id
} )
1702 if len(content
) != 0:
1703 #raise NfvoException("vnf '{}' not found".format(vnf_id), httperrors.Not_Found)
1704 # change boot_data into boot-data
1706 if vm
.get("boot_data"):
1707 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
1710 data
['vnf']['VNFC'] = content
1711 #TODO: GET all the information from a VNFC and include it in the output.
1714 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
1715 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
1716 WHERE
={'vnfs.uuid': vnf_id
} )
1717 data
['vnf']['nets'] = content
1719 #GET ip-profile for each net
1720 for net
in data
['vnf']['nets']:
1721 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1722 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1723 WHERE
={'net_id': net
["uuid"]} )
1724 if len(ipprofiles
)==1:
1725 net
["ip_profile"] = ipprofiles
[0]
1726 elif len(ipprofiles
)>1:
1727 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), httperrors
.Bad_Request
)
1730 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1732 #GET External Interfaces
1733 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1734 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1735 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1736 WHERE
={'vnfs.uuid': vnf_id
, 'interfaces.external_name<>': None} )
1738 data
['vnf']['external-connections'] = content
1743 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1744 # Check tenant exist
1745 if tenant_id
!= "any":
1746 check_tenant(mydb
, tenant_id
)
1747 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1748 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1752 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1754 if tenant_id
!= "any":
1755 where_or
["tenant_id"] = tenant_id
1756 where_or
["public"] = True
1757 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1758 vnf_id
= vnf
["uuid"]
1760 # "Getting the list of flavors and tenants of the VNF"
1761 flavorList
= get_flavorlist(mydb
, vnf_id
)
1762 if len(flavorList
)==0:
1763 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1765 imageList
= get_imagelist(mydb
, vnf_id
)
1766 if len(imageList
)==0:
1767 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1769 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1771 raise NfvoException("vnf '{}' not found".format(vnf_id
), httperrors
.Not_Found
)
1774 for flavor
in flavorList
:
1775 #check if flavor is used by other vnf
1777 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1779 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1781 #flavor not used, must be deleted
1783 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id': flavor
})
1784 for flavor_vim
in c
:
1785 if not flavor_vim
['created']: # skip this flavor because not created by openmano
1789 for vim
in vims
.values():
1790 if vim
["config"]["datacenter_tenant_id"] == flavor_vim
["datacenter_vim_id"]:
1796 myvim
.delete_flavor(flavor_vim
["vim_id"])
1797 except vimconn
.vimconnNotFoundException
:
1798 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"],
1799 flavor_vim
["datacenter_vim_id"] )
1800 except vimconn
.vimconnException
as e
:
1801 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1802 flavor_vim
["vim_id"], flavor_vim
["datacenter_vim_id"], type(e
).__name
__, str(e
))
1803 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"],
1804 flavor_vim
["datacenter_vim_id"]))
1805 # delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1806 mydb
.delete_row_by_id('flavors', flavor
)
1807 except db_base_Exception
as e
:
1808 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1809 undeletedItems
.append("flavor {}".format(flavor
))
1812 for image
in imageList
:
1814 #check if image is used by other vnf
1815 c
= mydb
.get_rows(FROM
='vms', WHERE
=[{'image_id': image
}, {'image_list LIKE ': '%' + image
+ '%'}])
1817 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1819 #image not used, must be deleted
1821 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1823 if image_vim
["datacenter_vim_id"] not in vims
: # TODO change to datacenter_tenant_id
1825 if image_vim
['created']=='false': #skip this image because not created by openmano
1827 myvim
=vims
[ image_vim
["datacenter_id"] ]
1829 myvim
.delete_image(image_vim
["vim_id"])
1830 except vimconn
.vimconnNotFoundException
as e
:
1831 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1832 except vimconn
.vimconnException
as e
:
1833 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1834 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1835 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1836 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1837 mydb
.delete_row_by_id('images', image
)
1838 except db_base_Exception
as e
:
1839 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1840 undeletedItems
.append("image %s" % image
)
1842 return vnf_id
+ " " + vnf
["name"]
1844 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1847 @deprecated("Not used")
1848 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1849 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1853 return -httperrors
.Not_Found
, "datacenter '%s' not found" % datacenter_name
1854 myvim
= vims
.values()[0]
1855 result
,servers
= myvim
.get_hosts_info()
1857 return result
, servers
1858 topology
= {'name':myvim
['name'] , 'servers': servers
}
1859 return result
, topology
1862 def get_hosts(mydb
, nfvo_tenant_id
):
1863 vims
= get_vim(mydb
, nfvo_tenant_id
)
1865 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), httperrors
.Not_Found
)
1867 #print "nfvo.datacenter_action() error. Several datacenters found"
1868 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
1869 myvim
= vims
.values()[0]
1871 hosts
= myvim
.get_hosts()
1872 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1874 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1876 server
={'name':host
['name'], 'vms':[]}
1877 for vm
in host
['instances']:
1878 #get internal name and model
1880 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1881 WHERE
={'vim_vm_id':vm
['id']} )
1883 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1885 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1887 except db_base_Exception
as e
:
1888 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1889 datacenter
['Datacenters'][0]['servers'].append(server
)
1890 #return -400, "en construccion"
1892 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1894 except vimconn
.vimconnException
as e
:
1895 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1898 @deprecated("Use new_nsd_v3")
1899 def new_scenario(mydb
, tenant_id
, topo
):
1901 # result, vims = get_vim(mydb, tenant_id)
1903 # return result, vims
1905 if tenant_id
!= "any":
1906 check_tenant(mydb
, tenant_id
)
1907 if "tenant_id" in topo
:
1908 if topo
["tenant_id"] != tenant_id
:
1909 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1910 httperrors
.Unauthorized
)
1914 #1.1: get VNFs and external_networks (other_nets).
1916 other_nets
={} #external_networks, bridge_networks and data_networkds
1917 nodes
= topo
['topology']['nodes']
1918 for k
in nodes
.keys():
1919 if nodes
[k
]['type'] == 'VNF':
1921 vnfs
[k
]['ifaces'] = {}
1922 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1923 other_nets
[k
] = nodes
[k
]
1924 other_nets
[k
]['external']=True
1925 elif nodes
[k
]['type'] == 'network':
1926 other_nets
[k
] = nodes
[k
]
1927 other_nets
[k
]['external']=False
1930 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1931 for name
,vnf
in vnfs
.items():
1932 where
= {"OR": {"tenant_id": tenant_id
, 'public': "true"}}
1934 error_pos
= "'topology':'nodes':'" + name
+ "'"
1936 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1937 where
['uuid'] = vnf
['vnf_id']
1938 if 'VNF model' in vnf
:
1939 error_text
+= " 'VNF model' " + vnf
['VNF model']
1940 where
['name'] = vnf
['VNF model']
1942 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, httperrors
.Bad_Request
)
1944 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1948 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, httperrors
.Not_Found
)
1950 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", httperrors
.Conflict
)
1951 vnf
['uuid']=vnf_db
[0]['uuid']
1952 vnf
['description']=vnf_db
[0]['description']
1953 #get external interfaces
1954 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1955 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1956 WHERE
={'vnfs.uuid':vnf
['uuid'], 'external_name<>': None} )
1957 for ext_iface
in ext_ifaces
:
1958 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1960 #1.4 get list of connections
1961 conections
= topo
['topology']['connections']
1962 conections_list
= []
1963 conections_list_name
= []
1964 for k
in conections
.keys():
1965 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1966 ifaces_list
= conections
[k
]['nodes'].items()
1967 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1969 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1970 for k2
in conection_pair_list
:
1973 con_type
= conections
[k
].get("type", "link")
1974 if con_type
!= "link":
1976 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), httperrors
.Bad_Request
)
1977 other_nets
[k
] = {'external': False}
1978 if conections
[k
].get("graph"):
1979 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1980 ifaces_list
.append( (k
, None) )
1983 if con_type
== "external_network":
1984 other_nets
[k
]['external'] = True
1985 if conections
[k
].get("model"):
1986 other_nets
[k
]["model"] = conections
[k
]["model"]
1988 other_nets
[k
]["model"] = k
1989 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1990 other_nets
[k
]["model"] = con_type
1992 conections_list_name
.append(k
)
1993 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)
1994 #print set(ifaces_list)
1995 #check valid VNF and iface names
1996 for iface
in ifaces_list
:
1997 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1998 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1999 str(k
), iface
[0]), httperrors
.Not_Found
)
2000 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
2001 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
2002 str(k
), iface
[0], iface
[1]), httperrors
.Not_Found
)
2004 #1.5 unify connections from the pair list to a consolidated list
2006 while index
< len(conections_list
):
2008 while index2
< len(conections_list
):
2009 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
2010 conections_list
[index
] |
= conections_list
[index2
]
2011 del conections_list
[index2
]
2012 del conections_list_name
[index2
]
2015 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
2017 #for k in conections_list:
2022 #1.6 Delete non external nets
2023 # for k in other_nets.keys():
2024 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
2025 # for con in conections_list:
2027 # for index in range(0,len(con)):
2028 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
2029 # for index in delete_indexes:
2032 #1.7: Check external_ports are present at database table datacenter_nets
2033 for k
,net
in other_nets
.items():
2034 error_pos
= "'topology':'nodes':'" + k
+ "'"
2035 if net
['external']==False:
2036 if 'name' not in net
:
2038 if 'model' not in net
:
2039 raise NfvoException("needed a 'model' at " + error_pos
, httperrors
.Bad_Request
)
2040 if net
['model']=='bridge_net':
2041 net
['type']='bridge';
2042 elif net
['model']=='dataplane_net':
2045 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, httperrors
.Not_Found
)
2047 #IF we do not want to check that external network exist at datacenter
2052 # if 'net_id' in net:
2053 # error_text += " 'net_id' " + net['net_id']
2054 # WHERE_['uuid'] = net['net_id']
2055 # if 'model' in net:
2056 # error_text += " 'model' " + net['model']
2057 # WHERE_['name'] = net['model']
2058 # if len(WHERE_) == 0:
2059 # return -httperrors.Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
2060 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
2061 # FROM='datacenter_nets', WHERE=WHERE_ )
2063 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
2065 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
2066 # return -httperrors.Bad_Request, "unknown " +error_text+ " at " + error_pos
2068 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
2069 # return -httperrors.Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
2070 # other_nets[k].update(net_db[0])
2073 net_nb
=0 #Number of nets
2074 for con
in conections_list
:
2075 #check if this is connected to a external net
2079 for index
in range(0,len(con
)):
2080 #check if this is connected to a external net
2081 for net_key
in other_nets
.keys():
2082 if con
[index
][0]==net_key
:
2083 if other_net_index
>=0:
2084 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
2085 #print "nfvo.new_scenario " + error_text
2086 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2088 other_net_index
= index
2089 net_target
= net_key
2091 #print "other_net_index", other_net_index
2093 if other_net_index
>=0:
2094 del con
[other_net_index
]
2095 #IF we do not want to check that external network exist at datacenter
2096 if other_nets
[net_target
]['external'] :
2097 if "name" not in other_nets
[net_target
]:
2098 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
2099 if other_nets
[net_target
]["type"] == "external_network":
2100 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
2101 other_nets
[net_target
]["type"] = "data"
2103 other_nets
[net_target
]["type"] = "bridge"
2105 # if other_nets[net_target]['external'] :
2106 # 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
2107 # if type_=='data' and other_nets[net_target]['type']=="ptp":
2108 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
2109 # print "nfvo.new_scenario " + error_text
2110 # return -httperrors.Bad_Request, error_text
2113 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
2116 net_type_bridge
=False
2118 net_target
= "__-__net"+str(net_nb
)
2119 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
2120 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
2123 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
2124 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
2125 if iface_type
=='mgmt' or iface_type
=='bridge':
2126 net_type_bridge
= True
2128 net_type_data
= True
2129 if net_type_bridge
and net_type_data
:
2130 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
2131 #print "nfvo.new_scenario " + error_text
2132 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2133 elif net_type_bridge
:
2136 type_
='data' if len(con
)>2 else 'ptp'
2137 net_list
[net_target
]['type'] = type_
2140 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
2141 #print "nfvo.new_scenario " + error_text
2143 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2145 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
2146 #1.8.1 obtain management net
2147 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
2148 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
2149 #1.8.2 check all interfaces from all vnfs
2151 add_mgmt_net
= False
2152 for vnf
in vnfs
.values():
2153 for iface
in vnf
['ifaces'].values():
2154 if iface
['type']=='mgmt' and 'net_key' not in iface
:
2155 #iface not connected
2156 iface
['net_key'] = 'mgmt'
2158 if add_mgmt_net
and 'mgmt' not in net_list
:
2159 net_list
['mgmt']=mgmt_net
[0]
2160 net_list
['mgmt']['external']=True
2161 net_list
['mgmt']['graph']={'visible':False}
2163 net_list
.update(other_nets
)
2165 #print 'net_list', net_list
2170 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
2171 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
2172 'tenant_id':tenant_id
, 'name':topo
['name'],
2173 'description':topo
.get('description',topo
['name']),
2174 'public': topo
.get('public', False)
2180 @deprecated("Use new_nsd_v3")
2181 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
2182 """ This creates a new scenario for version 0.2 and 0.3"""
2183 scenario
= scenario_dict
["scenario"]
2184 if tenant_id
!= "any":
2185 check_tenant(mydb
, tenant_id
)
2186 if "tenant_id" in scenario
:
2187 if scenario
["tenant_id"] != tenant_id
:
2188 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
2189 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
2190 scenario
["tenant_id"], tenant_id
), httperrors
.Unauthorized
)
2194 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
2195 for name
,vnf
in scenario
["vnfs"].iteritems():
2196 where
= {"OR": {"tenant_id": tenant_id
, 'public': "true"}}
2198 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
2200 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
2201 where
['uuid'] = vnf
['vnf_id']
2202 if 'vnf_name' in vnf
:
2203 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
2204 where
['name'] = vnf
['vnf_name']
2206 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, httperrors
.Bad_Request
)
2207 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
2210 if len(vnf_db
) == 0:
2211 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, httperrors
.Not_Found
)
2212 elif len(vnf_db
) > 1:
2213 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", httperrors
.Conflict
)
2214 vnf
['uuid'] = vnf_db
[0]['uuid']
2215 vnf
['description'] = vnf_db
[0]['description']
2217 # get external interfaces
2218 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
2219 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
2220 WHERE
={'vnfs.uuid':vnf
['uuid'], 'external_name<>': None} )
2221 for ext_iface
in ext_ifaces
:
2222 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
2223 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
2225 # 2: Insert net_key and ip_address at every vnf interface
2226 for net_name
, net
in scenario
["networks"].items():
2227 net_type_bridge
= False
2228 net_type_data
= False
2229 for iface_dict
in net
["interfaces"]:
2230 if version
== "0.2":
2231 temp_dict
= iface_dict
2233 elif version
== "0.3":
2234 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
2235 ip_address
= iface_dict
.get('ip_address', None)
2236 for vnf
, iface
in temp_dict
.items():
2237 if vnf
not in scenario
["vnfs"]:
2238 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
2240 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2241 raise NfvoException(error_text
, httperrors
.Not_Found
)
2242 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
2243 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
2244 .format(net_name
, iface
)
2245 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2246 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2247 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
2248 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
2249 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
2250 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2251 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2252 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
2253 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
2254 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
2255 if iface_type
== 'mgmt' or iface_type
== 'bridge':
2256 net_type_bridge
= True
2258 net_type_data
= True
2260 if net_type_bridge
and net_type_data
:
2261 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
2263 # logger.debug("nfvo.new_scenario " + error_text)
2264 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2265 elif net_type_bridge
:
2268 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
2270 if net
.get("implementation"): # for v0.3
2271 if type_
== "bridge" and net
["implementation"] == "underlay":
2272 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
2273 "'network':'{}'".format(net_name
)
2274 # logger.debug(error_text)
2275 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2276 elif type_
!= "bridge" and net
["implementation"] == "overlay":
2277 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
2278 "'network':'{}'".format(net_name
)
2279 # logger.debug(error_text)
2280 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2281 net
.pop("implementation")
2282 if "type" in net
and version
== "0.3": # for v0.3
2283 if type_
== "data" and net
["type"] == "e-line":
2284 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
2285 "'e-line' at 'network':'{}'".format(net_name
)
2286 # logger.debug(error_text)
2287 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2288 elif type_
== "ptp" and net
["type"] == "e-lan":
2292 net
['name'] = net_name
2293 net
['external'] = net
.get('external', False)
2295 # 3: insert at database
2296 scenario
["nets"] = scenario
["networks"]
2297 scenario
['tenant_id'] = tenant_id
2298 scenario_id
= mydb
.new_scenario(scenario
)
2302 def new_nsd_v3(mydb
, tenant_id
, nsd_descriptor
):
2304 Parses an OSM IM nsd_catalog and insert at DB
2307 :param nsd_descriptor:
2308 :return: The list of created NSD ids
2311 mynsd
= nsd_catalog
.nsd()
2313 pybindJSONDecoder
.load_ietf_json(nsd_descriptor
, None, None, obj
=mynsd
, skip_unknown
=True)
2314 except Exception as e
:
2315 raise NfvoException("Error. Invalid NS descriptor format: " + str(e
), httperrors
.Bad_Request
)
2319 db_sce_interfaces
= []
2322 db_sce_rsp_hops
= []
2323 db_sce_classifiers
= []
2324 db_sce_classifier_matches
= []
2326 db_ip_profiles_index
= 0
2329 for nsd_yang
in mynsd
.nsd_catalog
.nsd
.itervalues():
2330 nsd
= nsd_yang
.get()
2333 scenario_uuid
= str(uuid4())
2334 uuid_list
.append(scenario_uuid
)
2335 nsd_uuid_list
.append(scenario_uuid
)
2337 "uuid": scenario_uuid
,
2338 "osm_id": get_str(nsd
, "id", 255),
2339 "name": get_str(nsd
, "name", 255),
2340 "description": get_str(nsd
, "description", 255),
2341 "tenant_id": tenant_id
,
2342 "vendor": get_str(nsd
, "vendor", 255),
2343 "short_name": get_str(nsd
, "short-name", 255),
2344 "descriptor": str(nsd_descriptor
)[:60000],
2346 db_scenarios
.append(db_scenario
)
2348 # table sce_vnfs (constituent-vnfd)
2349 vnf_index2scevnf_uuid
= {}
2350 vnf_index2vnf_uuid
= {}
2351 for vnf
in nsd
.get("constituent-vnfd").itervalues():
2352 existing_vnf
= mydb
.get_rows(FROM
="vnfs", WHERE
={'osm_id': str(vnf
["vnfd-id-ref"])[:255],
2353 'tenant_id': tenant_id
})
2354 if not existing_vnf
:
2355 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'constituent-vnfd':'vnfd-id-ref':"
2356 "'{}'. Reference to a non-existing VNFD in the catalog".format(
2357 str(nsd
["id"]), str(vnf
["vnfd-id-ref"])[:255]),
2358 httperrors
.Bad_Request
)
2359 sce_vnf_uuid
= str(uuid4())
2360 uuid_list
.append(sce_vnf_uuid
)
2362 "uuid": sce_vnf_uuid
,
2363 "scenario_id": scenario_uuid
,
2364 # "name": get_str(vnf, "member-vnf-index", 255),
2365 "name": existing_vnf
[0]["name"][:200] + "." + get_str(vnf
, "member-vnf-index", 50),
2366 "vnf_id": existing_vnf
[0]["uuid"],
2367 "member_vnf_index": str(vnf
["member-vnf-index"]),
2368 # TODO 'start-by-default': True
2370 vnf_index2scevnf_uuid
[str(vnf
['member-vnf-index'])] = sce_vnf_uuid
2371 vnf_index2vnf_uuid
[str(vnf
['member-vnf-index'])] = existing_vnf
[0]["uuid"]
2372 db_sce_vnfs
.append(db_sce_vnf
)
2374 # table ip_profiles (ip-profiles)
2375 ip_profile_name2db_table_index
= {}
2376 for ip_profile
in nsd
.get("ip-profiles").itervalues():
2378 "ip_version": str(ip_profile
["ip-profile-params"].get("ip-version", "ipv4")),
2379 "subnet_address": str(ip_profile
["ip-profile-params"].get("subnet-address")),
2380 "gateway_address": str(ip_profile
["ip-profile-params"].get("gateway-address")),
2381 "dhcp_enabled": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("enabled", True)),
2382 "dhcp_start_address": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("start-address")),
2383 "dhcp_count": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("count")),
2386 for dns
in ip_profile
["ip-profile-params"]["dns-server"].itervalues():
2387 dns_list
.append(str(dns
.get("address")))
2388 db_ip_profile
["dns_address"] = ";".join(dns_list
)
2389 if ip_profile
["ip-profile-params"].get('security-group'):
2390 db_ip_profile
["security_group"] = ip_profile
["ip-profile-params"]['security-group']
2391 ip_profile_name2db_table_index
[str(ip_profile
["name"])] = db_ip_profiles_index
2392 db_ip_profiles_index
+= 1
2393 db_ip_profiles
.append(db_ip_profile
)
2395 # table sce_nets (internal-vld)
2396 for vld
in nsd
.get("vld").itervalues():
2397 sce_net_uuid
= str(uuid4())
2398 uuid_list
.append(sce_net_uuid
)
2400 "uuid": sce_net_uuid
,
2401 "name": get_str(vld
, "name", 255),
2402 "scenario_id": scenario_uuid
,
2404 "multipoint": not vld
.get("type") == "ELINE",
2405 "osm_id": get_str(vld
, "id", 255),
2407 "description": get_str(vld
, "description", 255),
2409 # guess type of network
2410 if vld
.get("mgmt-network"):
2411 db_sce_net
["type"] = "bridge"
2412 db_sce_net
["external"] = True
2413 elif vld
.get("provider-network").get("overlay-type") == "VLAN":
2414 db_sce_net
["type"] = "data"
2416 # later on it will be fixed to bridge or data depending on the type of interfaces attached to it
2417 db_sce_net
["type"] = None
2418 db_sce_nets
.append(db_sce_net
)
2420 # ip-profile, link db_ip_profile with db_sce_net
2421 if vld
.get("ip-profile-ref"):
2422 ip_profile_name
= vld
.get("ip-profile-ref")
2423 if ip_profile_name
not in ip_profile_name2db_table_index
:
2424 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'ip-profile-ref':'{}'."
2425 " Reference to a non-existing 'ip_profiles'".format(
2426 str(nsd
["id"]), str(vld
["id"]), str(vld
["ip-profile-ref"])),
2427 httperrors
.Bad_Request
)
2428 db_ip_profiles
[ip_profile_name2db_table_index
[ip_profile_name
]]["sce_net_id"] = sce_net_uuid
2429 elif vld
.get("vim-network-name"):
2430 db_sce_net
["vim_network_name"] = get_str(vld
, "vim-network-name", 255)
2432 # table sce_interfaces (vld:vnfd-connection-point-ref)
2433 for iface
in vld
.get("vnfd-connection-point-ref").itervalues():
2434 vnf_index
= str(iface
['member-vnf-index-ref'])
2435 # check correct parameters
2436 if vnf_index
not in vnf_index2vnf_uuid
:
2437 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2438 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2439 "'nsd':'constituent-vnfd'".format(
2440 str(nsd
["id"]), str(vld
["id"]), str(iface
["member-vnf-index-ref"])),
2441 httperrors
.Bad_Request
)
2443 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid', 'i.type as iface_type'),
2444 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2445 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2446 'external_name': get_str(iface
, "vnfd-connection-point-ref",
2448 if not existing_ifaces
:
2449 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2450 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2451 "connection-point name at VNFD '{}'".format(
2452 str(nsd
["id"]), str(vld
["id"]), str(iface
["vnfd-connection-point-ref"]),
2453 str(iface
.get("vnfd-id-ref"))[:255]),
2454 httperrors
.Bad_Request
)
2455 interface_uuid
= existing_ifaces
[0]["uuid"]
2456 if existing_ifaces
[0]["iface_type"] == "data":
2457 db_sce_net
["type"] = "data"
2458 sce_interface_uuid
= str(uuid4())
2459 uuid_list
.append(sce_net_uuid
)
2460 iface_ip_address
= None
2461 if iface
.get("ip-address"):
2462 iface_ip_address
= str(iface
.get("ip-address"))
2463 db_sce_interface
= {
2464 "uuid": sce_interface_uuid
,
2465 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2466 "sce_net_id": sce_net_uuid
,
2467 "interface_id": interface_uuid
,
2468 "ip_address": iface_ip_address
,
2470 db_sce_interfaces
.append(db_sce_interface
)
2471 if not db_sce_net
["type"]:
2472 db_sce_net
["type"] = "bridge"
2474 # table sce_vnffgs (vnffgd)
2475 for vnffg
in nsd
.get("vnffgd").itervalues():
2476 sce_vnffg_uuid
= str(uuid4())
2477 uuid_list
.append(sce_vnffg_uuid
)
2479 "uuid": sce_vnffg_uuid
,
2480 "name": get_str(vnffg
, "name", 255),
2481 "scenario_id": scenario_uuid
,
2482 "vendor": get_str(vnffg
, "vendor", 255),
2483 "description": get_str(vld
, "description", 255),
2485 db_sce_vnffgs
.append(db_sce_vnffg
)
2488 for rsp
in vnffg
.get("rsp").itervalues():
2489 sce_rsp_uuid
= str(uuid4())
2490 uuid_list
.append(sce_rsp_uuid
)
2492 "uuid": sce_rsp_uuid
,
2493 "name": get_str(rsp
, "name", 255),
2494 "sce_vnffg_id": sce_vnffg_uuid
,
2495 "id": get_str(rsp
, "id", 255), # only useful to link with classifiers; will be removed later in the code
2497 db_sce_rsps
.append(db_sce_rsp
)
2498 for iface
in rsp
.get("vnfd-connection-point-ref").itervalues():
2499 vnf_index
= str(iface
['member-vnf-index-ref'])
2500 if_order
= int(iface
['order'])
2501 # check correct parameters
2502 if vnf_index
not in vnf_index2vnf_uuid
:
2503 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2504 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2505 "'nsd':'constituent-vnfd'".format(
2506 str(nsd
["id"]), str(rsp
["id"]), str(iface
["member-vnf-index-ref"])),
2507 httperrors
.Bad_Request
)
2509 ingress_existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2510 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2512 'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2513 'external_name': get_str(iface
, "vnfd-ingress-connection-point-ref",
2515 if not ingress_existing_ifaces
:
2516 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2517 "-ref':'vnfd-ingress-connection-point-ref':'{}'. Reference to a non-existing "
2518 "connection-point name at VNFD '{}'".format(
2519 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-ingress-connection-point-ref"]),
2520 str(iface
.get("vnfd-id-ref"))[:255]), httperrors
.Bad_Request
)
2522 egress_existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2523 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2525 'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2526 'external_name': get_str(iface
, "vnfd-egress-connection-point-ref",
2528 if not egress_existing_ifaces
:
2529 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2530 "-ref':'vnfd-egress-connection-point-ref':'{}'. Reference to a non-existing "
2531 "connection-point name at VNFD '{}'".format(
2532 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-egress-connection-point-ref"]),
2533 str(iface
.get("vnfd-id-ref"))[:255]), HTTP_Bad_Request
)
2535 ingress_interface_uuid
= ingress_existing_ifaces
[0]["uuid"]
2536 egress_interface_uuid
= egress_existing_ifaces
[0]["uuid"]
2537 sce_rsp_hop_uuid
= str(uuid4())
2538 uuid_list
.append(sce_rsp_hop_uuid
)
2540 "uuid": sce_rsp_hop_uuid
,
2541 "if_order": if_order
,
2542 "ingress_interface_id": ingress_interface_uuid
,
2543 "egress_interface_id": egress_interface_uuid
,
2544 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2545 "sce_rsp_id": sce_rsp_uuid
,
2547 db_sce_rsp_hops
.append(db_sce_rsp_hop
)
2549 # deal with classifiers
2550 for classifier
in vnffg
.get("classifier").itervalues():
2551 sce_classifier_uuid
= str(uuid4())
2552 uuid_list
.append(sce_classifier_uuid
)
2555 vnf_index
= str(classifier
['member-vnf-index-ref'])
2556 if vnf_index
not in vnf_index2vnf_uuid
:
2557 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'classifier[{}]':'vnfd-connection-point"
2558 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2559 "'nsd':'constituent-vnfd'".format(
2560 str(nsd
["id"]), str(classifier
["id"]), str(classifier
["member-vnf-index-ref"])),
2561 httperrors
.Bad_Request
)
2562 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2563 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2564 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2565 'external_name': get_str(classifier
, "vnfd-connection-point-ref",
2567 if not existing_ifaces
:
2568 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2569 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2570 "connection-point name at VNFD '{}'".format(
2571 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-connection-point-ref"]),
2572 str(iface
.get("vnfd-id-ref"))[:255]),
2573 httperrors
.Bad_Request
)
2574 interface_uuid
= existing_ifaces
[0]["uuid"]
2576 db_sce_classifier
= {
2577 "uuid": sce_classifier_uuid
,
2578 "name": get_str(classifier
, "name", 255),
2579 "sce_vnffg_id": sce_vnffg_uuid
,
2580 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2581 "interface_id": interface_uuid
,
2583 rsp_id
= get_str(classifier
, "rsp-id-ref", 255)
2584 rsp
= next((item
for item
in db_sce_rsps
if item
["id"] == rsp_id
), None)
2585 db_sce_classifier
["sce_rsp_id"] = rsp
["uuid"]
2586 db_sce_classifiers
.append(db_sce_classifier
)
2588 for match
in classifier
.get("match-attributes").itervalues():
2589 sce_classifier_match_uuid
= str(uuid4())
2590 uuid_list
.append(sce_classifier_match_uuid
)
2591 db_sce_classifier_match
= {
2592 "uuid": sce_classifier_match_uuid
,
2593 "ip_proto": get_str(match
, "ip-proto", 2),
2594 "source_ip": get_str(match
, "source-ip-address", 16),
2595 "destination_ip": get_str(match
, "destination-ip-address", 16),
2596 "source_port": get_str(match
, "source-port", 5),
2597 "destination_port": get_str(match
, "destination-port", 5),
2598 "sce_classifier_id": sce_classifier_uuid
,
2600 db_sce_classifier_matches
.append(db_sce_classifier_match
)
2603 # remove unneeded id's in sce_rsps
2604 for rsp
in db_sce_rsps
:
2608 {"scenarios": db_scenarios
},
2609 {"sce_nets": db_sce_nets
},
2610 {"ip_profiles": db_ip_profiles
},
2611 {"sce_vnfs": db_sce_vnfs
},
2612 {"sce_interfaces": db_sce_interfaces
},
2613 {"sce_vnffgs": db_sce_vnffgs
},
2614 {"sce_rsps": db_sce_rsps
},
2615 {"sce_rsp_hops": db_sce_rsp_hops
},
2616 {"sce_classifiers": db_sce_classifiers
},
2617 {"sce_classifier_matches": db_sce_classifier_matches
},
2620 logger
.debug("new_nsd_v3 done: %s",
2621 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
2622 mydb
.new_rows(db_tables
, uuid_list
)
2623 return nsd_uuid_list
2624 except NfvoException
:
2626 except Exception as e
:
2627 logger
.error("Exception {}".format(e
))
2628 raise # NfvoException("Exception {}".format(e), httperrors.Bad_Request)
2631 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
2632 data
["uuid"] = scenario_id
2633 data
["tenant_id"] = tenant_id
2634 c
= mydb
.edit_scenario( data
)
2638 @deprecated("Use create_instance")
2639 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
2640 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2641 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
2642 vims
= {datacenter_id
: myvim
}
2643 myvim_tenant
= myvim
['tenant_id']
2644 datacenter_name
= myvim
['name']
2648 #print "Checking that the scenario_id exists and getting the scenario dictionary"
2649 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
=datacenter_id
)
2650 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
2651 scenarioDict
['datacenter_id'] = datacenter_id
2652 #print '================scenarioDict======================='
2653 #print json.dumps(scenarioDict, indent=4)
2654 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
2656 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
2657 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2659 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
2660 auxNetDict
['scenario'] = {}
2662 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
2663 for sce_net
in scenarioDict
['nets']:
2664 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
2666 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
2667 myNetName
= myNetName
[0:255] #limit length
2668 myNetType
= sce_net
['type']
2670 myNetDict
["name"] = myNetName
2671 myNetDict
["type"] = myNetType
2672 myNetDict
["tenant_id"] = myvim_tenant
2673 myNetIPProfile
= sce_net
.get('ip_profile', None)
2675 #We should use the dictionary as input parameter for new_network
2677 if not sce_net
["external"]:
2678 network_id
, _
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2679 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
2680 sce_net
['vim_id'] = network_id
2681 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
2682 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2683 sce_net
["created"] = True
2685 if sce_net
['vim_id'] == None:
2686 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
2687 _
, message
= rollback(mydb
, vims
, rollbackList
)
2688 logger
.error("nfvo.start_scenario: %s", error_text
)
2689 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2690 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
2691 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
2693 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
2694 #For each vnf net, we create it and we add it to instanceNetlist.
2696 for sce_vnf
in scenarioDict
['vnfs']:
2697 for net
in sce_vnf
['nets']:
2698 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
2700 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
2701 myNetName
= myNetName
[0:255] #limit length
2702 myNetType
= net
['type']
2704 myNetDict
["name"] = myNetName
2705 myNetDict
["type"] = myNetType
2706 myNetDict
["tenant_id"] = myvim_tenant
2707 myNetIPProfile
= net
.get('ip_profile', None)
2710 #We should use the dictionary as input parameter for new_network
2711 network_id
, _
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2712 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
2713 net
['vim_id'] = network_id
2714 if sce_vnf
['uuid'] not in auxNetDict
:
2715 auxNetDict
[sce_vnf
['uuid']] = {}
2716 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
2717 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2718 net
["created"] = True
2720 #print "auxNetDict:"
2721 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2723 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
2724 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2726 for sce_vnf
in scenarioDict
['vnfs']:
2727 vnf_availability_zones
= []
2728 for vm
in sce_vnf
['vms']:
2729 vm_av
= vm
.get('availability_zone')
2730 if vm_av
and vm_av
not in vnf_availability_zones
:
2731 vnf_availability_zones
.append(vm_av
)
2733 # check if there is enough availability zones available at vim level.
2734 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
2735 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
2736 raise NfvoException('No enough availability zones at VIM for this deployment', httperrors
.Bad_Request
)
2738 for vm
in sce_vnf
['vms']:
2741 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
2742 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
2743 #myVMDict['description'] = vm['description']
2744 myVMDict
['description'] = myVMDict
['name'][0:99]
2746 myVMDict
['start'] = "no"
2747 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2748 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
2750 #create image at vim in case it not exist
2751 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2752 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
2753 vm
['vim_image_id'] = image_id
2755 #create flavor at vim in case it not exist
2756 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2757 if flavor_dict
['extended']!=None:
2758 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2759 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
2760 vm
['vim_flavor_id'] = flavor_id
2763 myVMDict
['imageRef'] = vm
['vim_image_id']
2764 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2765 myVMDict
['networks'] = []
2766 for iface
in vm
['interfaces']:
2768 if iface
['type']=="data":
2769 netDict
['type'] = iface
['model']
2770 elif "model" in iface
and iface
["model"]!=None:
2771 netDict
['model']=iface
['model']
2772 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2773 #discover type of interface looking at flavor
2774 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2775 for flavor_iface
in numa
.get('interfaces',[]):
2776 if flavor_iface
.get('name') == iface
['internal_name']:
2777 if flavor_iface
['dedicated'] == 'yes':
2778 netDict
['type']="PF" #passthrough
2779 elif flavor_iface
['dedicated'] == 'no':
2780 netDict
['type']="VF" #siov
2781 elif flavor_iface
['dedicated'] == 'yes:sriov':
2782 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2783 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2785 netDict
["use"]=iface
['type']
2786 if netDict
["use"]=="data" and not netDict
.get("type"):
2787 #print "netDict", netDict
2788 #print "iface", iface
2789 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'])
2790 if flavor_dict
.get('extended')==None:
2791 raise NfvoException(e_text
+ "After database migration some information is not available. \
2792 Try to delete and create the scenarios and VNFs again", httperrors
.Conflict
)
2794 raise NfvoException(e_text
, httperrors
.Internal_Server_Error
)
2795 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2796 netDict
["type"]="virtual"
2797 if "vpci" in iface
and iface
["vpci"] is not None:
2798 netDict
['vpci'] = iface
['vpci']
2799 if "mac" in iface
and iface
["mac"] is not None:
2800 netDict
['mac_address'] = iface
['mac']
2801 if "port-security" in iface
and iface
["port-security"] is not None:
2802 netDict
['port_security'] = iface
['port-security']
2803 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2804 netDict
['floating_ip'] = iface
['floating-ip']
2805 netDict
['name'] = iface
['internal_name']
2806 if iface
['net_id'] is None:
2807 for vnf_iface
in sce_vnf
["interfaces"]:
2810 if vnf_iface
['interface_id']==iface
['uuid']:
2811 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
2814 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2815 #skip bridge ifaces not connected to any net
2816 #if 'net_id' not in netDict or netDict['net_id']==None:
2818 myVMDict
['networks'].append(netDict
)
2819 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2820 #print myVMDict['name']
2821 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2822 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2823 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2825 if 'availability_zone' in myVMDict
:
2826 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
2830 vm_id
, _
= myvim
.new_vminstance(myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2831 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2832 availability_zone_index
=av_index
,
2833 availability_zone_list
=vnf_availability_zones
)
2834 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
2835 vm
['vim_id'] = vm_id
2836 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2837 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2838 for net
in myVMDict
['networks']:
2840 for iface
in vm
['interfaces']:
2841 if net
["name"]==iface
["internal_name"]:
2842 iface
["vim_id"]=net
["vim_id"]
2845 logger
.debug("start scenario Deployment done")
2846 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2847 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
2848 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
2849 return mydb
.get_instance_scenario(instance_id
)
2851 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
2852 _
, message
= rollback(mydb
, vims
, rollbackList
)
2853 if isinstance(e
, db_base_Exception
):
2854 error_text
= "Exception at database"
2856 error_text
= "Exception at VIM"
2857 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2858 #logger.error("start_scenario %s", error_text)
2859 raise NfvoException(error_text
, e
.http_code
)
2861 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
2862 """ join the cloud config information into cloud_config_preserve.
2863 In case of conflict cloud_config_preserve preserves
2866 if not cloud_config_preserve
and not cloud_config
:
2869 new_cloud_config
= {"key-pairs":[], "users":[]}
2871 if cloud_config_preserve
:
2872 for key
in cloud_config_preserve
.get("key-pairs", () ):
2873 if key
not in new_cloud_config
["key-pairs"]:
2874 new_cloud_config
["key-pairs"].append(key
)
2876 for key
in cloud_config
.get("key-pairs", () ):
2877 if key
not in new_cloud_config
["key-pairs"]:
2878 new_cloud_config
["key-pairs"].append(key
)
2879 if not new_cloud_config
["key-pairs"]:
2880 del new_cloud_config
["key-pairs"]
2884 new_cloud_config
["users"] += cloud_config
.get("users", () )
2885 if cloud_config_preserve
:
2886 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
2887 index_to_delete
= []
2888 users
= new_cloud_config
.get("users", [])
2889 for index0
in range(0,len(users
)):
2890 if index0
in index_to_delete
:
2892 for index1
in range(index0
+1,len(users
)):
2893 if index1
in index_to_delete
:
2895 if users
[index0
]["name"] == users
[index1
]["name"]:
2896 index_to_delete
.append(index1
)
2897 for key
in users
[index1
].get("key-pairs",()):
2898 if "key-pairs" not in users
[index0
]:
2899 users
[index0
]["key-pairs"] = [key
]
2900 elif key
not in users
[index0
]["key-pairs"]:
2901 users
[index0
]["key-pairs"].append(key
)
2902 index_to_delete
.sort(reverse
=True)
2903 for index
in index_to_delete
:
2905 if not new_cloud_config
["users"]:
2906 del new_cloud_config
["users"]
2909 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
2910 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
2911 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
2912 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
2915 new_cloud_config
["user-data"] = []
2916 if cloud_config
and cloud_config
.get("user-data"):
2917 if isinstance(cloud_config
["user-data"], list):
2918 new_cloud_config
["user-data"] += cloud_config
["user-data"]
2920 new_cloud_config
["user-data"].append(cloud_config
["user-data"])
2921 if cloud_config_preserve
and cloud_config_preserve
.get("user-data"):
2922 if isinstance(cloud_config_preserve
["user-data"], list):
2923 new_cloud_config
["user-data"] += cloud_config_preserve
["user-data"]
2925 new_cloud_config
["user-data"].append(cloud_config_preserve
["user-data"])
2926 if not new_cloud_config
["user-data"]:
2927 del new_cloud_config
["user-data"]
2930 new_cloud_config
["config-files"] = []
2931 if cloud_config
and cloud_config
.get("config-files") != None:
2932 new_cloud_config
["config-files"] += cloud_config
["config-files"]
2933 if cloud_config_preserve
:
2934 for file in cloud_config_preserve
.get("config-files", ()):
2935 for index
in range(0, len(new_cloud_config
["config-files"])):
2936 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
2937 new_cloud_config
["config-files"][index
] = file
2940 new_cloud_config
["config-files"].append(file)
2941 if not new_cloud_config
["config-files"]:
2942 del new_cloud_config
["config-files"]
2943 return new_cloud_config
2946 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
2947 datacenter_id
= None
2948 datacenter_name
= None
2951 if datacenter_tenant_id
:
2952 thread_id
= datacenter_tenant_id
2953 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
2955 where_
={"td.nfvo_tenant_id": tenant_id
}
2956 if datacenter_id_name
:
2957 if utils
.check_valid_uuid(datacenter_id_name
):
2958 datacenter_id
= datacenter_id_name
2959 where_
["dt.datacenter_id"] = datacenter_id
2961 datacenter_name
= datacenter_id_name
2962 where_
["d.name"] = datacenter_name
2963 if datacenter_tenant_id
:
2964 where_
["dt.uuid"] = datacenter_tenant_id
2965 datacenters
= mydb
.get_rows(
2966 SELECT
=("dt.uuid as datacenter_tenant_id",),
2967 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
2968 "join datacenters as d on d.uuid=dt.datacenter_id",
2970 if len(datacenters
) > 1:
2971 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
2973 thread_id
= datacenters
[0]["datacenter_tenant_id"]
2974 thread
= vim_threads
["running"].get(thread_id
)
2976 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
2977 return thread_id
, thread
2978 except db_base_Exception
as e
:
2979 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
2982 def get_datacenter_uuid(mydb
, tenant_id
, datacenter_id_name
):
2984 if utils
.check_valid_uuid(datacenter_id_name
):
2985 WHERE_dict
['d.uuid'] = datacenter_id_name
2987 WHERE_dict
['d.name'] = datacenter_id_name
2990 WHERE_dict
['nfvo_tenant_id'] = tenant_id
2991 from_
= "tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join datacenter_tenants as" \
2992 " dt on td.datacenter_tenant_id=dt.uuid"
2994 from_
= 'datacenters as d'
2995 vimaccounts
= mydb
.get_rows(FROM
=from_
, SELECT
=("d.uuid as uuid, d.name as name",), WHERE
=WHERE_dict
)
2996 if len(vimaccounts
) == 0:
2997 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
2998 elif len(vimaccounts
)>1:
2999 #print "nfvo.datacenter_action() error. Several datacenters found"
3000 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
3001 return vimaccounts
[0]["uuid"], vimaccounts
[0]["name"]
3004 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
3005 datacenter_id
= None
3006 datacenter_name
= None
3007 if datacenter_id_name
:
3008 if utils
.check_valid_uuid(datacenter_id_name
):
3009 datacenter_id
= datacenter_id_name
3011 datacenter_name
= datacenter_id_name
3012 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
3014 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
3016 #print "nfvo.datacenter_action() error. Several datacenters found"
3017 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
3018 return vims
.keys()[0], vims
.values()[0]
3022 """Takes dict d and updates it with the values in dict u.
3023 It merges all depth levels"""
3024 for k
, v
in u
.iteritems():
3025 if isinstance(v
, collections
.Mapping
):
3026 r
= update(d
.get(k
, {}), v
)
3033 def create_instance(mydb
, tenant_id
, instance_dict
):
3034 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
3035 # logger.debug("Creating instance...")
3036 scenario
= instance_dict
["scenario"]
3038 # find main datacenter
3040 myvim_threads_id
= {}
3041 datacenter
= instance_dict
.get("datacenter")
3042 default_wim_account
= instance_dict
.get("wim_account")
3043 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3044 myvims
[default_datacenter_id
] = vim
3045 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
3046 tenant
= mydb
.get_rows_by_id('nfvo_tenants', tenant_id
)
3047 # myvim_tenant = myvim['tenant_id']
3050 # print "Checking that the scenario exists and getting the scenario dictionary"
3051 if isinstance(scenario
, str):
3052 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, datacenter_vim_id
=myvim_threads_id
[default_datacenter_id
],
3053 datacenter_id
=default_datacenter_id
)
3055 scenarioDict
= scenario
3056 scenarioDict
["uuid"] = None
3058 # logger.debug(">>>>>> Dictionaries before merging")
3059 # logger.debug(">>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
3060 # logger.debug(">>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
3062 db_instance_vnfs
= []
3063 db_instance_vms
= []
3064 db_instance_interfaces
= []
3065 db_instance_sfis
= []
3066 db_instance_sfs
= []
3067 db_instance_classifications
= []
3068 db_instance_sfps
= []
3073 instance_name
= instance_dict
["name"]
3074 instance_uuid
= str(uuid4())
3075 uuid_list
.append(instance_uuid
)
3076 db_instance_scenario
= {
3077 "uuid": instance_uuid
,
3078 "name": instance_name
,
3079 "tenant_id": tenant_id
,
3080 "scenario_id": scenarioDict
['uuid'],
3081 "datacenter_id": default_datacenter_id
,
3082 # filled bellow 'datacenter_tenant_id'
3083 "description": instance_dict
.get("description"),
3085 if scenarioDict
.get("cloud-config"):
3086 db_instance_scenario
["cloud_config"] = yaml
.safe_dump(scenarioDict
["cloud-config"],
3087 default_flow_style
=True, width
=256)
3088 instance_action_id
= get_task_id()
3089 db_instance_action
= {
3090 "uuid": instance_action_id
, # same uuid for the instance and the action on create
3091 "tenant_id": tenant_id
,
3092 "instance_id": instance_uuid
,
3093 "description": "CREATE",
3096 # Auxiliary dictionaries from x to y
3097 sce_net2instance
= {}
3098 net2task_id
= {'scenario': {}}
3099 # Mapping between local networks and WIMs
3102 def ip_profile_IM2RO(ip_profile_im
):
3103 # translate from input format to database format
3105 if 'subnet-address' in ip_profile_im
:
3106 ip_profile_ro
['subnet_address'] = ip_profile_im
['subnet-address']
3107 if 'ip-version' in ip_profile_im
:
3108 ip_profile_ro
['ip_version'] = ip_profile_im
['ip-version']
3109 if 'gateway-address' in ip_profile_im
:
3110 ip_profile_ro
['gateway_address'] = ip_profile_im
['gateway-address']
3111 if 'dns-address' in ip_profile_im
:
3112 ip_profile_ro
['dns_address'] = ip_profile_im
['dns-address']
3113 if isinstance(ip_profile_ro
['dns_address'], (list, tuple)):
3114 ip_profile_ro
['dns_address'] = ";".join(ip_profile_ro
['dns_address'])
3115 if 'dhcp' in ip_profile_im
:
3116 ip_profile_ro
['dhcp_start_address'] = ip_profile_im
['dhcp'].get('start-address')
3117 ip_profile_ro
['dhcp_enabled'] = ip_profile_im
['dhcp'].get('enabled', True)
3118 ip_profile_ro
['dhcp_count'] = ip_profile_im
['dhcp'].get('count')
3119 return ip_profile_ro
3121 # logger.debug("Creating instance from scenario-dict:\n%s",
3122 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
3124 # 0 check correct parameters
3125 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).iteritems():
3126 for scenario_net
in scenarioDict
['nets']:
3127 if net_name
== scenario_net
.get("name") or net_name
== scenario_net
.get("osm_id") or net_name
== scenario_net
.get("uuid"):
3130 raise NfvoException("Invalid scenario network name or id '{}' at instance:networks".format(net_name
),
3131 httperrors
.Bad_Request
)
3132 if "sites" not in net_instance_desc
:
3133 net_instance_desc
["sites"] = [ {} ]
3134 site_without_datacenter_field
= False
3135 for site
in net_instance_desc
["sites"]:
3136 if site
.get("datacenter"):
3137 site
["datacenter"], _
= get_datacenter_uuid(mydb
, tenant_id
, site
["datacenter"])
3138 if site
["datacenter"] not in myvims
:
3139 # Add this datacenter to myvims
3140 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
3142 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
3143 site
["datacenter"] = d
# change name to id
3145 if site_without_datacenter_field
:
3146 raise NfvoException("Found more than one entries without datacenter field at "
3147 "instance:networks:{}:sites".format(net_name
), httperrors
.Bad_Request
)
3148 site_without_datacenter_field
= True
3149 site
["datacenter"] = default_datacenter_id
# change name to id
3151 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
3152 for scenario_vnf
in scenarioDict
['vnfs']:
3153 if vnf_name
== scenario_vnf
['member_vnf_index'] or vnf_name
== scenario_vnf
['uuid'] or vnf_name
== scenario_vnf
['name']:
3156 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_name
), httperrors
.Bad_Request
)
3157 if "datacenter" in vnf_instance_desc
:
3158 # Add this datacenter to myvims
3159 vnf_instance_desc
["datacenter"], _
= get_datacenter_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3160 if vnf_instance_desc
["datacenter"] not in myvims
:
3161 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3163 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3164 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
3166 for net_id
, net_instance_desc
in vnf_instance_desc
.get("networks", {}).iteritems():
3167 for scenario_net
in scenario_vnf
['nets']:
3168 if net_id
== scenario_net
['osm_id'] or net_id
== scenario_net
['uuid'] or net_id
== scenario_net
["name"]:
3171 raise NfvoException("Invalid net id or name '{}' at instance:vnfs:networks".format(net_id
), httperrors
.Bad_Request
)
3172 if net_instance_desc
.get("vim-network-name"):
3173 scenario_net
["vim-network-name"] = net_instance_desc
["vim-network-name"]
3174 if net_instance_desc
.get("vim-network-id"):
3175 scenario_net
["vim-network-id"] = net_instance_desc
["vim-network-id"]
3176 if net_instance_desc
.get("name"):
3177 scenario_net
["name"] = net_instance_desc
["name"]
3178 if 'ip-profile' in net_instance_desc
:
3179 ipprofile_db
= ip_profile_IM2RO(net_instance_desc
['ip-profile'])
3180 if 'ip_profile' not in scenario_net
:
3181 scenario_net
['ip_profile'] = ipprofile_db
3183 update(scenario_net
['ip_profile'], ipprofile_db
)
3185 for vdu_id
, vdu_instance_desc
in vnf_instance_desc
.get("vdus", {}).iteritems():
3186 for scenario_vm
in scenario_vnf
['vms']:
3187 if vdu_id
== scenario_vm
['osm_id'] or vdu_id
== scenario_vm
["name"]:
3190 raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id
), httperrors
.Bad_Request
)
3191 scenario_vm
["instance_parameters"] = vdu_instance_desc
3192 for iface_id
, iface_instance_desc
in vdu_instance_desc
.get("interfaces", {}).iteritems():
3193 for scenario_interface
in scenario_vm
['interfaces']:
3194 if iface_id
== scenario_interface
['internal_name'] or iface_id
== scenario_interface
["external_name"]:
3195 scenario_interface
.update(iface_instance_desc
)
3198 raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id
), httperrors
.Bad_Request
)
3200 # 0.1 parse cloud-config parameters
3201 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
3203 # 0.2 merge instance information into scenario
3204 # Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
3205 # However, this is not possible yet.
3206 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).iteritems():
3207 for scenario_net
in scenarioDict
['nets']:
3208 if net_name
== scenario_net
.get("name") or net_name
== scenario_net
.get("osm_id") or net_name
== scenario_net
.get("uuid"):
3209 if "wim_account" in net_instance_desc
and net_instance_desc
["wim_account"] is not None:
3210 scenario_net
["wim_account"] = net_instance_desc
["wim_account"]
3211 if 'ip-profile' in net_instance_desc
:
3212 ipprofile_db
= ip_profile_IM2RO(net_instance_desc
['ip-profile'])
3213 if 'ip_profile' not in scenario_net
:
3214 scenario_net
['ip_profile'] = ipprofile_db
3216 update(scenario_net
['ip_profile'], ipprofile_db
)
3217 for interface
in net_instance_desc
.get('interfaces', ()):
3218 if 'ip_address' in interface
:
3219 for vnf
in scenarioDict
['vnfs']:
3220 if interface
['vnf'] == vnf
['name']:
3221 for vnf_interface
in vnf
['interfaces']:
3222 if interface
['vnf_interface'] == vnf_interface
['external_name']:
3223 vnf_interface
['ip_address'] = interface
['ip_address']
3225 # logger.debug(">>>>>>>> Merged dictionary")
3226 # logger.debug("Creating instance scenario-dict MERGED:\n%s",
3227 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
3229 # 1. Creating new nets (sce_nets) in the VIM"
3230 number_mgmt_networks
= 0
3231 db_instance_nets
= []
3232 for sce_net
in scenarioDict
['nets']:
3233 sce_net_uuid
= sce_net
.get('uuid', sce_net
["name"])
3234 # get involved datacenters where this network need to be created
3235 involved_datacenters
= []
3236 for sce_vnf
in scenarioDict
.get("vnfs", ()):
3237 vnf_datacenter
= sce_vnf
.get("datacenter", default_datacenter_id
)
3238 if vnf_datacenter
in involved_datacenters
:
3240 if sce_vnf
.get("interfaces"):
3241 for sce_vnf_ifaces
in sce_vnf
["interfaces"]:
3242 if sce_vnf_ifaces
.get("sce_net_id") == sce_net
["uuid"]:
3243 involved_datacenters
.append(vnf_datacenter
)
3245 if not involved_datacenters
:
3246 involved_datacenters
.append(default_datacenter_id
)
3247 target_wim_account
= sce_net
.get("wim_account", default_wim_account
)
3250 # TODO: use this information during network creation
3251 wim_account_id
= wim_account_name
= None
3252 if len(involved_datacenters
) > 1 and 'uuid' in sce_net
:
3253 if target_wim_account
is None or target_wim_account
is True: # automatic selection of WIM
3254 # OBS: sce_net without uuid are used internally to VNFs
3255 # and the assumption is that VNFs will not be split among
3256 # different datacenters
3257 wim_account
= wim_engine
.find_suitable_wim_account(
3258 involved_datacenters
, tenant_id
)
3259 wim_account_id
= wim_account
['uuid']
3260 wim_account_name
= wim_account
['name']
3261 wim_usage
[sce_net
['uuid']] = wim_account_id
3262 elif isinstance(target_wim_account
, str): # manual selection of WIM
3263 wim_account
.persist
.get_wim_account_by(target_wim_account
, tenant_id
)
3264 wim_account_id
= wim_account
['uuid']
3265 wim_account_name
= wim_account
['name']
3266 wim_usage
[sce_net
['uuid']] = wim_account_id
3267 else: # not WIM usage
3268 wim_usage
[sce_net
['uuid']] = False
3272 if instance_dict
.get("networks"):
3273 if sce_net
.get("uuid") in instance_dict
["networks"]:
3274 descriptor_net
= instance_dict
["networks"][sce_net
["uuid"]]
3275 descriptor_net_name
= sce_net
["uuid"]
3276 elif sce_net
.get("osm_id") in instance_dict
["networks"]:
3277 descriptor_net
= instance_dict
["networks"][sce_net
["osm_id"]]
3278 descriptor_net_name
= sce_net
["osm_id"]
3279 elif sce_net
["name"] in instance_dict
["networks"]:
3280 descriptor_net
= instance_dict
["networks"][sce_net
["name"]]
3281 descriptor_net_name
= sce_net
["name"]
3282 net_name
= descriptor_net
.get("vim-network-name")
3283 # add datacenters from instantiation parameters
3284 if descriptor_net
.get("sites"):
3285 for site
in descriptor_net
["sites"]:
3286 if site
.get("datacenter") and site
["datacenter"] not in involved_datacenters
:
3287 involved_datacenters
.append(site
["datacenter"])
3288 sce_net2instance
[sce_net_uuid
] = {}
3289 net2task_id
['scenario'][sce_net_uuid
] = {}
3292 related_network
= None
3293 if descriptor_net
.get("use-network"):
3294 target_instance_nets
= mydb
.get_rows(
3296 FROM
="instance_nets",
3297 WHERE
={"instance_scenario_id": descriptor_net
["use-network"]["instance_scenario_id"],
3298 "osm_id": descriptor_net
["use-network"]["osm_id"]},
3300 if not target_instance_nets
:
3301 raise NfvoException(
3302 "Cannot find the target network at instance:networks[{}]:use-network".format(descriptor_net_name
),
3303 httperrors
.Bad_Request
)
3305 use_network
= target_instance_nets
[0]["related"]
3307 if sce_net
["external"]:
3308 number_mgmt_networks
+= 1
3310 for datacenter_id
in involved_datacenters
:
3312 netmap_create
= None
3313 if descriptor_net
.get("sites"):
3314 for site
in descriptor_net
["sites"]:
3315 if site
.get("datacenter") == datacenter_id
:
3316 netmap_use
= site
.get("netmap-use")
3317 netmap_create
= site
.get("netmap-create")
3320 vim
= myvims
[datacenter_id
]
3321 myvim_thread_id
= myvim_threads_id
[datacenter_id
]
3323 net_type
= sce_net
['type']
3325 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} # 'shared': True
3328 if sce_net
["external"]:
3329 net_name
= sce_net
["name"]
3331 net_name
= "{}-{}".format(instance_name
, sce_net
["name"])
3332 net_name
= net_name
[:255] # limit length
3334 if netmap_use
or netmap_create
:
3335 create_network
= False
3336 lookfor_network
= False
3338 lookfor_network
= True
3339 if utils
.check_valid_uuid(netmap_use
):
3340 lookfor_filter
["id"] = netmap_use
3342 lookfor_filter
["name"] = netmap_use
3344 create_network
= True
3345 net_vim_name
= net_name
3346 if isinstance(netmap_create
, str):
3347 net_vim_name
= netmap_create
3348 elif sce_net
.get("vim_network_name"):
3349 create_network
= False
3350 lookfor_network
= True
3351 lookfor_filter
["name"] = sce_net
.get("vim_network_name")
3352 elif sce_net
["external"]:
3353 if sce_net
.get('vim_id'):
3354 # there is a netmap at datacenter_nets database # TODO REVISE!!!!
3355 create_network
= False
3356 lookfor_network
= True
3357 lookfor_filter
["id"] = sce_net
['vim_id']
3358 elif vim
["config"].get("management_network_id") or vim
["config"].get("management_network_name"):
3359 if number_mgmt_networks
> 1:
3360 raise NfvoException("Found several VLD of type mgmt. "
3361 "You must concrete what vim-network must be use for each one",
3362 httperrors
.Bad_Request
)
3363 create_network
= False
3364 lookfor_network
= True
3365 if vim
["config"].get("management_network_id"):
3366 lookfor_filter
["id"] = vim
["config"]["management_network_id"]
3368 lookfor_filter
["name"] = vim
["config"]["management_network_name"]
3370 # There is not a netmap, look at datacenter for a net with this name and create if not found
3371 create_network
= True
3372 lookfor_network
= True
3373 lookfor_filter
["name"] = sce_net
["name"]
3374 net_vim_name
= sce_net
["name"]
3376 net_vim_name
= net_name
3377 create_network
= True
3378 lookfor_network
= False
3382 task_action
= "CREATE"
3383 task_extra
["params"] = (net_vim_name
, net_type
, sce_net
.get('ip_profile', None), wim_account_name
)
3385 task_extra
["find"] = (lookfor_filter
,)
3386 elif lookfor_network
:
3387 task_action
= "FIND"
3388 task_extra
["params"] = (lookfor_filter
,)
3390 # fill database content
3391 net_uuid
= str(uuid4())
3392 uuid_list
.append(net_uuid
)
3393 sce_net2instance
[sce_net_uuid
][datacenter_id
] = net_uuid
3394 if not related_network
: # all db_instance_nets will have same related
3395 related_network
= use_network
or net_uuid
3398 "osm_id": sce_net
.get("osm_id") or sce_net
["name"],
3399 "related": related_network
,
3401 "vim_name": net_vim_name
,
3402 "instance_scenario_id": instance_uuid
,
3403 "sce_net_id": sce_net
.get("uuid"),
3404 "created": create_network
,
3405 'datacenter_id': datacenter_id
,
3406 'datacenter_tenant_id': myvim_thread_id
,
3407 'status': 'BUILD' # if create_network else "ACTIVE"
3409 db_instance_nets
.append(db_net
)
3411 "instance_action_id": instance_action_id
,
3412 "status": "SCHEDULED",
3413 "task_index": task_index
,
3414 "datacenter_vim_id": myvim_thread_id
,
3415 "action": task_action
,
3416 "item": "instance_nets",
3417 "item_id": net_uuid
,
3418 "related": related_network
,
3419 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
3421 net2task_id
['scenario'][sce_net_uuid
][datacenter_id
] = task_index
3423 db_vim_actions
.append(db_vim_action
)
3425 if 'ip_profile' in sce_net
:
3427 'instance_net_id': net_uuid
,
3428 'ip_version': sce_net
['ip_profile']['ip_version'],
3429 'subnet_address': sce_net
['ip_profile']['subnet_address'],
3430 'gateway_address': sce_net
['ip_profile']['gateway_address'],
3431 'dns_address': sce_net
['ip_profile']['dns_address'],
3432 'dhcp_enabled': sce_net
['ip_profile']['dhcp_enabled'],
3433 'dhcp_start_address': sce_net
['ip_profile']['dhcp_start_address'],
3434 'dhcp_count': sce_net
['ip_profile']['dhcp_count'],
3436 db_ip_profiles
.append(db_ip_profile
)
3440 "default_datacenter_id": default_datacenter_id
,
3441 "myvim_threads_id": myvim_threads_id
,
3442 "instance_uuid": instance_uuid
,
3443 "instance_name": instance_name
,
3444 "instance_action_id": instance_action_id
,
3446 "cloud_config": cloud_config
,
3447 "RO_pub_key": tenant
[0].get('RO_pub_key'),
3448 "instance_parameters": instance_dict
,
3451 "task_index": task_index
,
3452 "uuid_list": uuid_list
,
3453 "db_instance_nets": db_instance_nets
,
3454 "db_vim_actions": db_vim_actions
,
3455 "db_ip_profiles": db_ip_profiles
,
3456 "db_instance_vnfs": db_instance_vnfs
,
3457 "db_instance_vms": db_instance_vms
,
3458 "db_instance_interfaces": db_instance_interfaces
,
3459 "net2task_id": net2task_id
,
3460 "sce_net2instance": sce_net2instance
,
3462 # sce_vnf_list = sorted(scenarioDict['vnfs'], key=lambda k: k['name'])
3463 for sce_vnf
in scenarioDict
.get('vnfs', ()): # sce_vnf_list:
3464 instantiate_vnf(mydb
, sce_vnf
, vnf_params
, vnf_params_out
, rollbackList
)
3465 task_index
= vnf_params_out
["task_index"]
3466 uuid_list
= vnf_params_out
["uuid_list"]
3469 # task_depends_on = []
3470 for vnffg
in scenarioDict
.get('vnffgs', ()):
3471 for rsp
in vnffg
['rsps']:
3473 for cp
in rsp
['connection_points']:
3474 count
= mydb
.get_rows(
3476 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_rsp_hops as h "
3477 "on interfaces.uuid=h.ingress_interface_id",
3478 WHERE
={'h.uuid': cp
['uuid']})[0]['count']
3479 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == cp
['sce_vnf_id']), None)
3480 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3482 for instance_vm
in instance_vms
:
3483 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3485 dependencies
.append(action
['task_index'])
3486 # TODO: throw exception if count != len(instance_vms)
3487 # TODO: and action shouldn't ever be None
3489 for i
in range(count
):
3491 sfi_uuid
= str(uuid4())
3493 "ingress_interface_id": cp
["ingress_interface_id"],
3494 "egress_interface_id": cp
["egress_interface_id"]
3496 uuid_list
.append(sfi_uuid
)
3499 "related": sfi_uuid
,
3500 "instance_scenario_id": instance_uuid
,
3501 'sce_rsp_hop_id': cp
['uuid'],
3502 'datacenter_id': datacenter_id
,
3503 'datacenter_tenant_id': myvim_thread_id
,
3504 "vim_sfi_id": None, # vim thread will populate
3506 db_instance_sfis
.append(db_sfi
)
3508 "instance_action_id": instance_action_id
,
3509 "task_index": task_index
,
3510 "datacenter_vim_id": myvim_thread_id
,
3512 "status": "SCHEDULED",
3513 "item": "instance_sfis",
3514 "item_id": sfi_uuid
,
3515 "related": sfi_uuid
,
3516 "extra": yaml
.safe_dump({"params": extra_params
, "depends_on": [dependencies
[i
]]},
3517 default_flow_style
=True, width
=256)
3519 sfis_created
.append(task_index
)
3521 db_vim_actions
.append(db_vim_action
)
3523 sf_uuid
= str(uuid4())
3524 uuid_list
.append(sf_uuid
)
3528 "instance_scenario_id": instance_uuid
,
3529 'sce_rsp_hop_id': cp
['uuid'],
3530 'datacenter_id': datacenter_id
,
3531 'datacenter_tenant_id': myvim_thread_id
,
3532 "vim_sf_id": None, # vim thread will populate
3534 db_instance_sfs
.append(db_sf
)
3536 "instance_action_id": instance_action_id
,
3537 "task_index": task_index
,
3538 "datacenter_vim_id": myvim_thread_id
,
3540 "status": "SCHEDULED",
3541 "item": "instance_sfs",
3544 "extra": yaml
.safe_dump({"params": "", "depends_on": sfis_created
},
3545 default_flow_style
=True, width
=256)
3547 sfs_created
.append(task_index
)
3549 db_vim_actions
.append(db_vim_action
)
3550 classifier
= rsp
['classifier']
3552 # TODO the following ~13 lines can be reused for the sfi case
3553 count
= mydb
.get_rows(
3554 SELECT
=('vms.count'),
3555 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_classifiers as c on interfaces.uuid=c.interface_id",
3556 WHERE
={'c.uuid': classifier
['uuid']})[0]['count']
3557 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == classifier
['sce_vnf_id']), None)
3558 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3560 for instance_vm
in instance_vms
:
3561 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3563 dependencies
.append(action
['task_index'])
3564 # TODO: throw exception if count != len(instance_vms)
3565 # TODO: and action shouldn't ever be None
3566 classifications_created
= []
3567 for i
in range(count
):
3568 for match
in classifier
['matches']:
3569 # create classifications
3570 classification_uuid
= str(uuid4())
3571 uuid_list
.append(classification_uuid
)
3572 db_classification
= {
3573 "uuid": classification_uuid
,
3574 "related": classification_uuid
,
3575 "instance_scenario_id": instance_uuid
,
3576 'sce_classifier_match_id': match
['uuid'],
3577 'datacenter_id': datacenter_id
,
3578 'datacenter_tenant_id': myvim_thread_id
,
3579 "vim_classification_id": None, # vim thread will populate
3581 db_instance_classifications
.append(db_classification
)
3582 classification_params
= {
3583 "ip_proto": match
["ip_proto"],
3584 "source_ip": match
["source_ip"],
3585 "destination_ip": match
["destination_ip"],
3586 "source_port": match
["source_port"],
3587 "destination_port": match
["destination_port"]
3590 "instance_action_id": instance_action_id
,
3591 "task_index": task_index
,
3592 "datacenter_vim_id": myvim_thread_id
,
3594 "status": "SCHEDULED",
3595 "item": "instance_classifications",
3596 "item_id": classification_uuid
,
3597 "related": classification_uuid
,
3598 "extra": yaml
.safe_dump({"params": classification_params
, "depends_on": [dependencies
[i
]]},
3599 default_flow_style
=True, width
=256)
3601 classifications_created
.append(task_index
)
3603 db_vim_actions
.append(db_vim_action
)
3606 sfp_uuid
= str(uuid4())
3607 uuid_list
.append(sfp_uuid
)
3610 "related": sfp_uuid
,
3611 "instance_scenario_id": instance_uuid
,
3612 'sce_rsp_id': rsp
['uuid'],
3613 'datacenter_id': datacenter_id
,
3614 'datacenter_tenant_id': myvim_thread_id
,
3615 "vim_sfp_id": None, # vim thread will populate
3617 db_instance_sfps
.append(db_sfp
)
3619 "instance_action_id": instance_action_id
,
3620 "task_index": task_index
,
3621 "datacenter_vim_id": myvim_thread_id
,
3623 "status": "SCHEDULED",
3624 "item": "instance_sfps",
3625 "item_id": sfp_uuid
,
3626 "related": sfp_uuid
,
3627 "extra": yaml
.safe_dump({"params": "", "depends_on": sfs_created
+ classifications_created
},
3628 default_flow_style
=True, width
=256)
3631 db_vim_actions
.append(db_vim_action
)
3632 db_instance_action
["number_tasks"] = task_index
3635 logger
.debug('wim_usage:\n%s\n\n', pformat(wim_usage
))
3636 wan_links
= wim_engine
.derive_wan_links(wim_usage
, db_instance_nets
, tenant_id
)
3637 wim_actions
= wim_engine
.create_actions(wan_links
)
3638 wim_actions
, db_instance_action
= (
3639 wim_engine
.incorporate_actions(wim_actions
, db_instance_action
))
3642 scenarioDict
["datacenter2tenant"] = myvim_threads_id
3644 db_instance_scenario
['datacenter_tenant_id'] = myvim_threads_id
[default_datacenter_id
]
3645 db_instance_scenario
['datacenter_id'] = default_datacenter_id
3647 {"instance_scenarios": db_instance_scenario
},
3648 {"instance_vnfs": db_instance_vnfs
},
3649 {"instance_nets": db_instance_nets
},
3650 {"ip_profiles": db_ip_profiles
},
3651 {"instance_vms": db_instance_vms
},
3652 {"instance_interfaces": db_instance_interfaces
},
3653 {"instance_actions": db_instance_action
},
3654 {"instance_sfis": db_instance_sfis
},
3655 {"instance_sfs": db_instance_sfs
},
3656 {"instance_classifications": db_instance_classifications
},
3657 {"instance_sfps": db_instance_sfps
},
3658 {"instance_wim_nets": wan_links
},
3659 {"vim_wim_actions": db_vim_actions
+ wim_actions
}
3662 logger
.debug("create_instance done DB tables: %s",
3663 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
3664 mydb
.new_rows(db_tables
, uuid_list
)
3665 for myvim_thread_id
in myvim_threads_id
.values():
3666 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
3668 wim_engine
.dispatch(wim_actions
)
3670 returned_instance
= mydb
.get_instance_scenario(instance_uuid
)
3671 returned_instance
["action_id"] = instance_action_id
3672 return returned_instance
3673 except (NfvoException
, vimconn
.vimconnException
, wimconn
.WimConnectorError
, db_base_Exception
) as e
:
3674 message
= rollback(mydb
, myvims
, rollbackList
)
3675 if isinstance(e
, db_base_Exception
):
3676 error_text
= "database Exception"
3677 elif isinstance(e
, vimconn
.vimconnException
):
3678 error_text
= "VIM Exception"
3679 elif isinstance(e
, wimconn
.WimConnectorError
):
3680 error_text
= "WIM Exception"
3682 error_text
= "Exception"
3683 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
3684 # logger.error("create_instance: %s", error_text)
3686 raise NfvoException(error_text
, e
.http_code
)
3689 def instantiate_vnf(mydb
, sce_vnf
, params
, params_out
, rollbackList
):
3690 default_datacenter_id
= params
["default_datacenter_id"]
3691 myvim_threads_id
= params
["myvim_threads_id"]
3692 instance_uuid
= params
["instance_uuid"]
3693 instance_name
= params
["instance_name"]
3694 instance_action_id
= params
["instance_action_id"]
3695 myvims
= params
["myvims"]
3696 cloud_config
= params
["cloud_config"]
3697 RO_pub_key
= params
["RO_pub_key"]
3699 task_index
= params_out
["task_index"]
3700 uuid_list
= params_out
["uuid_list"]
3701 db_instance_nets
= params_out
["db_instance_nets"]
3702 db_vim_actions
= params_out
["db_vim_actions"]
3703 db_ip_profiles
= params_out
["db_ip_profiles"]
3704 db_instance_vnfs
= params_out
["db_instance_vnfs"]
3705 db_instance_vms
= params_out
["db_instance_vms"]
3706 db_instance_interfaces
= params_out
["db_instance_interfaces"]
3707 net2task_id
= params_out
["net2task_id"]
3708 sce_net2instance
= params_out
["sce_net2instance"]
3710 vnf_net2instance
= {}
3712 # 2. Creating new nets (vnf internal nets) in the VIM"
3713 # For each vnf net, we create it and we add it to instanceNetlist.
3714 if sce_vnf
.get("datacenter"):
3715 datacenter_id
= sce_vnf
["datacenter"]
3716 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
3718 datacenter_id
= default_datacenter_id
3719 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
3720 for net
in sce_vnf
['nets']:
3722 # descriptor_net = instance_dict.get("vnfs", {}).get(sce_vnf["name"], {})
3723 # net_name = descriptor_net.get("name")
3726 net_name
= "{}-{}".format(instance_name
, net
["name"])
3727 net_name
= net_name
[:255] # limit length
3728 net_type
= net
['type']
3730 if sce_vnf
['uuid'] not in vnf_net2instance
:
3731 vnf_net2instance
[sce_vnf
['uuid']] = {}
3732 if sce_vnf
['uuid'] not in net2task_id
:
3733 net2task_id
[sce_vnf
['uuid']] = {}
3734 net2task_id
[sce_vnf
['uuid']][net
['uuid']] = task_index
3736 # fill database content
3737 net_uuid
= str(uuid4())
3738 uuid_list
.append(net_uuid
)
3739 vnf_net2instance
[sce_vnf
['uuid']][net
['uuid']] = net_uuid
3742 "related": net_uuid
,
3744 "vim_name": net_name
,
3745 "instance_scenario_id": instance_uuid
,
3746 "net_id": net
["uuid"],
3748 'datacenter_id': datacenter_id
,
3749 'datacenter_tenant_id': myvim_thread_id
,
3751 db_instance_nets
.append(db_net
)
3754 if net
.get("vim-network-name"):
3755 lookfor_filter
["name"] = net
["vim-network-name"]
3756 if net
.get("vim-network-id"):
3757 lookfor_filter
["id"] = net
["vim-network-id"]
3759 task_action
= "FIND"
3760 task_extra
= {"params": (lookfor_filter
,)}
3762 task_action
= "CREATE"
3763 task_extra
= {"params": (net_name
, net_type
, net
.get('ip_profile', None))}
3766 "instance_action_id": instance_action_id
,
3767 "task_index": task_index
,
3768 "datacenter_vim_id": myvim_thread_id
,
3769 "status": "SCHEDULED",
3770 "action": task_action
,
3771 "item": "instance_nets",
3772 "item_id": net_uuid
,
3773 "related": net_uuid
,
3774 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
3777 db_vim_actions
.append(db_vim_action
)
3779 if 'ip_profile' in net
:
3781 'instance_net_id': net_uuid
,
3782 'ip_version': net
['ip_profile']['ip_version'],
3783 'subnet_address': net
['ip_profile']['subnet_address'],
3784 'gateway_address': net
['ip_profile']['gateway_address'],
3785 'dns_address': net
['ip_profile']['dns_address'],
3786 'dhcp_enabled': net
['ip_profile']['dhcp_enabled'],
3787 'dhcp_start_address': net
['ip_profile']['dhcp_start_address'],
3788 'dhcp_count': net
['ip_profile']['dhcp_count'],
3790 db_ip_profiles
.append(db_ip_profile
)
3792 # print "vnf_net2instance:"
3793 # print yaml.safe_dump(vnf_net2instance, indent=4, default_flow_style=False)
3795 # 3. Creating new vm instances in the VIM
3796 # myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
3798 if sce_vnf
.get('mgmt_access'):
3799 ssh_access
= sce_vnf
['mgmt_access'].get('config-access', {}).get('ssh-access')
3800 vnf_availability_zones
= []
3801 for vm
in sce_vnf
.get('vms'):
3802 vm_av
= vm
.get('availability_zone')
3803 if vm_av
and vm_av
not in vnf_availability_zones
:
3804 vnf_availability_zones
.append(vm_av
)
3806 # check if there is enough availability zones available at vim level.
3807 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
3808 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
3809 raise NfvoException('No enough availability zones at VIM for this deployment', httperrors
.Bad_Request
)
3811 if sce_vnf
.get("datacenter"):
3812 vim
= myvims
[sce_vnf
["datacenter"]]
3813 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
3814 datacenter_id
= sce_vnf
["datacenter"]
3816 vim
= myvims
[default_datacenter_id
]
3817 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
3818 datacenter_id
= default_datacenter_id
3819 sce_vnf
["datacenter_id"] = datacenter_id
3822 vnf_uuid
= str(uuid4())
3823 uuid_list
.append(vnf_uuid
)
3826 'instance_scenario_id': instance_uuid
,
3827 'vnf_id': sce_vnf
['vnf_id'],
3828 'sce_vnf_id': sce_vnf
['uuid'],
3829 'datacenter_id': datacenter_id
,
3830 'datacenter_tenant_id': myvim_thread_id
,
3832 db_instance_vnfs
.append(db_instance_vnf
)
3834 for vm
in sce_vnf
['vms']:
3836 if vm
.get("pdu_type"):
3840 sce_vnf_name
= sce_vnf
['member_vnf_index'] if sce_vnf
['member_vnf_index'] else sce_vnf
['name']
3841 myVMDict
['name'] = "{}-{}-{}".format(instance_name
[:64], sce_vnf_name
[:64], vm
["name"][:64])
3842 myVMDict
['description'] = myVMDict
['name'][0:99]
3844 # myVMDict['start'] = "no"
3845 if vm
.get("instance_parameters") and vm
["instance_parameters"].get("name"):
3846 myVMDict
['name'] = vm
["instance_parameters"].get("name")
3847 myVMDict
['name'] = myVMDict
['name'][0:255] # limit name length
3848 # create image at vim in case it not exist
3849 image_uuid
= vm
['image_id']
3850 if vm
.get("image_list"):
3851 for alternative_image
in vm
["image_list"]:
3852 if alternative_image
["vim_type"] == vim
["config"]["_vim_type_internal"]:
3853 image_uuid
= alternative_image
['image_id']
3855 image_dict
= mydb
.get_table_by_uuid_name("images", image_uuid
)
3856 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
3857 vm
['vim_image_id'] = image_id
3859 # create flavor at vim in case it not exist
3860 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
3861 if flavor_dict
['extended'] != None:
3862 flavor_dict
['extended'] = yaml
.load(flavor_dict
['extended'])
3863 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
3865 # Obtain information for additional disks
3866 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',),
3867 WHERE
={'vim_id': flavor_id
})
3868 if not extended_flavor_dict
:
3869 raise NfvoException("flavor '{}' not found".format(flavor_id
), httperrors
.Not_Found
)
3871 # extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
3872 myVMDict
['disks'] = None
3873 extended_info
= extended_flavor_dict
[0]['extended']
3874 if extended_info
!= None:
3875 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
3876 if 'disks' in extended_flavor_dict_yaml
:
3877 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
3878 if vm
.get("instance_parameters") and vm
["instance_parameters"].get("devices"):
3879 for disk
in myVMDict
['disks']:
3880 if disk
.get("name") in vm
["instance_parameters"]["devices"]:
3881 disk
.update(vm
["instance_parameters"]["devices"][disk
.get("name")])
3883 vm
['vim_flavor_id'] = flavor_id
3884 myVMDict
['imageRef'] = vm
['vim_image_id']
3885 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
3886 myVMDict
['availability_zone'] = vm
.get('availability_zone')
3887 myVMDict
['networks'] = []
3888 task_depends_on
= []
3889 # TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
3890 is_management_vm
= False
3892 for iface
in vm
['interfaces']:
3894 if iface
['type'] == "data":
3895 netDict
['type'] = iface
['model']
3896 elif "model" in iface
and iface
["model"] != None:
3897 netDict
['model'] = iface
['model']
3898 # TODO in future, remove this because mac_address will not be set, and the type of PV,VF
3899 # is obtained from iterface table model
3900 # discover type of interface looking at flavor
3901 for numa
in flavor_dict
.get('extended', {}).get('numas', []):
3902 for flavor_iface
in numa
.get('interfaces', []):
3903 if flavor_iface
.get('name') == iface
['internal_name']:
3904 if flavor_iface
['dedicated'] == 'yes':
3905 netDict
['type'] = "PF" # passthrough
3906 elif flavor_iface
['dedicated'] == 'no':
3907 netDict
['type'] = "VF" # siov
3908 elif flavor_iface
['dedicated'] == 'yes:sriov':
3909 netDict
['type'] = "VFnotShared" # sriov but only one sriov on the PF
3910 netDict
["mac_address"] = flavor_iface
.get("mac_address")
3912 netDict
["use"] = iface
['type']
3913 if netDict
["use"] == "data" and not netDict
.get("type"):
3914 # print "netDict", netDict
3915 # print "iface", iface
3916 e_text
= "Cannot determine the interface type PF or VF of VNF '{}' VM '{}' iface '{}'".fromat(
3917 sce_vnf
['name'], vm
['name'], iface
['internal_name'])
3918 if flavor_dict
.get('extended') == None:
3919 raise NfvoException(e_text
+ "After database migration some information is not available. \
3920 Try to delete and create the scenarios and VNFs again", httperrors
.Conflict
)
3922 raise NfvoException(e_text
, httperrors
.Internal_Server_Error
)
3923 if netDict
["use"] == "mgmt":
3924 is_management_vm
= True
3925 netDict
["type"] = "virtual"
3926 if netDict
["use"] == "bridge":
3927 netDict
["type"] = "virtual"
3928 if iface
.get("vpci"):
3929 netDict
['vpci'] = iface
['vpci']
3930 if iface
.get("mac"):
3931 netDict
['mac_address'] = iface
['mac']
3932 if iface
.get("mac_address"):
3933 netDict
['mac_address'] = iface
['mac_address']
3934 if iface
.get("ip_address"):
3935 netDict
['ip_address'] = iface
['ip_address']
3936 if iface
.get("port-security") is not None:
3937 netDict
['port_security'] = iface
['port-security']
3938 if iface
.get("floating-ip") is not None:
3939 netDict
['floating_ip'] = iface
['floating-ip']
3940 netDict
['name'] = iface
['internal_name']
3941 if iface
['net_id'] is None:
3942 for vnf_iface
in sce_vnf
["interfaces"]:
3945 if vnf_iface
['interface_id'] == iface
['uuid']:
3946 netDict
['net_id'] = "TASK-{}".format(
3947 net2task_id
['scenario'][vnf_iface
['sce_net_id']][datacenter_id
])
3948 instance_net_id
= sce_net2instance
[vnf_iface
['sce_net_id']][datacenter_id
]
3949 task_depends_on
.append(net2task_id
['scenario'][vnf_iface
['sce_net_id']][datacenter_id
])
3952 netDict
['net_id'] = "TASK-{}".format(net2task_id
[sce_vnf
['uuid']][iface
['net_id']])
3953 instance_net_id
= vnf_net2instance
[sce_vnf
['uuid']][iface
['net_id']]
3954 task_depends_on
.append(net2task_id
[sce_vnf
['uuid']][iface
['net_id']])
3955 # skip bridge ifaces not connected to any net
3956 if 'net_id' not in netDict
or netDict
['net_id'] == None:
3958 myVMDict
['networks'].append(netDict
)
3961 # 'instance_vm_id': instance_vm_uuid,
3962 "instance_net_id": instance_net_id
,
3963 'interface_id': iface
['uuid'],
3964 # 'vim_interface_id': ,
3965 'type': 'external' if iface
['external_name'] is not None else 'internal',
3966 'ip_address': iface
.get('ip_address'),
3967 'mac_address': iface
.get('mac'),
3968 'floating_ip': int(iface
.get('floating-ip', False)),
3969 'port_security': int(iface
.get('port-security', True))
3971 db_vm_ifaces
.append(db_vm_iface
)
3972 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3973 # print myVMDict['name']
3974 # print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
3975 # print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
3976 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3978 # We add the RO key to cloud_config if vnf will need ssh access
3979 cloud_config_vm
= cloud_config
3980 if is_management_vm
and params
["instance_parameters"].get("mgmt_keys"):
3981 cloud_config_vm
= unify_cloud_config({"key-pairs": params
["instance_parameters"]["mgmt_keys"]},
3984 if vm
.get("instance_parameters") and "mgmt_keys" in vm
["instance_parameters"]:
3985 if vm
["instance_parameters"]["mgmt_keys"]:
3986 cloud_config_vm
= unify_cloud_config({"key-pairs": vm
["instance_parameters"]["mgmt_keys"]},
3989 cloud_config_vm
= unify_cloud_config(cloud_config_vm
, {"key-pairs": RO_pub_key
})
3990 if vm
.get("boot_data"):
3991 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config_vm
)
3993 if myVMDict
.get('availability_zone'):
3994 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
3997 for vm_index
in range(0, vm
.get('count', 1)):
3998 vm_name
= myVMDict
['name'] + "-" + str(vm_index
+1)
3999 task_params
= (vm_name
, myVMDict
['description'], myVMDict
.get('start', None),
4000 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'], cloud_config_vm
,
4001 myVMDict
['disks'], av_index
, vnf_availability_zones
)
4002 # put interface uuid back to scenario[vnfs][vms[[interfaces]
4003 for net
in myVMDict
['networks']:
4005 for iface
in vm
['interfaces']:
4006 if net
["name"] == iface
["internal_name"]:
4007 iface
["vim_id"] = net
["vim_id"]
4009 vm_uuid
= str(uuid4())
4010 uuid_list
.append(vm_uuid
)
4014 'instance_vnf_id': vnf_uuid
,
4015 # TODO delete "vim_vm_id": vm_id,
4016 "vm_id": vm
["uuid"],
4017 "vim_name": vm_name
,
4020 db_instance_vms
.append(db_vm
)
4023 for db_vm_iface
in db_vm_ifaces
:
4024 iface_uuid
= str(uuid4())
4025 uuid_list
.append(iface_uuid
)
4026 db_vm_iface_instance
= {
4028 "instance_vm_id": vm_uuid
4030 db_vm_iface_instance
.update(db_vm_iface
)
4031 if db_vm_iface_instance
.get("ip_address"): # increment ip_address
4032 ip
= db_vm_iface_instance
.get("ip_address")
4037 ip
= ip
[i
:] + str(int(ip
[:i
]) + 1)
4038 db_vm_iface_instance
["ip_address"] = ip
4040 db_vm_iface_instance
["ip_address"] = None
4041 db_instance_interfaces
.append(db_vm_iface_instance
)
4042 myVMDict
['networks'][iface_index
]["uuid"] = iface_uuid
4046 "instance_action_id": instance_action_id
,
4047 "task_index": task_index
,
4048 "datacenter_vim_id": myvim_thread_id
,
4050 "status": "SCHEDULED",
4051 "item": "instance_vms",
4054 "extra": yaml
.safe_dump({"params": task_params
, "depends_on": task_depends_on
},
4055 default_flow_style
=True, width
=256)
4058 db_vim_actions
.append(db_vim_action
)
4059 params_out
["task_index"] = task_index
4060 params_out
["uuid_list"] = uuid_list
4063 def delete_instance(mydb
, tenant_id
, instance_id
):
4064 # print "Checking that the instance_id exists and getting the instance dictionary"
4065 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
4066 # print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
4067 tenant_id
= instanceDict
["tenant_id"]
4070 # We need to retrieve the WIM Actions now, before the instance_scenario is
4071 # deleted. The reason for that is that: ON CASCADE rules will delete the
4072 # instance_wim_nets record in the database
4073 wim_actions
= wim_engine
.delete_actions(instance_scenario_id
=instance_id
)
4076 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
4077 # 1. Delete from Database
4078 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
4080 # 2. delete from VIM
4084 vimthread_affected
= {}
4085 net2vm_dependencies
= {}
4088 instance_action_id
= get_task_id()
4090 db_instance_action
= {
4091 "uuid": instance_action_id
, # same uuid for the instance and the action on create
4092 "tenant_id": tenant_id
,
4093 "instance_id": instance_id
,
4094 "description": "DELETE",
4095 # "number_tasks": 0 # filled bellow
4098 # 2.1 deleting VNFFGs
4099 for sfp
in instanceDict
.get('sfps', ()):
4100 vimthread_affected
[sfp
["datacenter_tenant_id"]] = None
4101 datacenter_key
= (sfp
["datacenter_id"], sfp
["datacenter_tenant_id"])
4102 if datacenter_key
not in myvims
:
4104 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sfp
["datacenter_id"], sfp
["datacenter_tenant_id"])
4105 except NfvoException
as e
:
4106 logger
.error(str(e
))
4108 myvim_threads
[datacenter_key
] = myvim_thread
4109 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sfp
["datacenter_id"],
4110 datacenter_tenant_id
=sfp
["datacenter_tenant_id"])
4112 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfp
["datacenter_id"], sfp
["datacenter_tenant_id"]))
4113 myvims
[datacenter_key
] = None
4115 myvims
[datacenter_key
] = vims
.values()[0]
4116 myvim
= myvims
[datacenter_key
]
4117 myvim_thread
= myvim_threads
[datacenter_key
]
4120 error_msg
+= "\n vim_sfp_id={} cannot be deleted because datacenter={} not found".format(sfp
['vim_sfp_id'], sfp
["datacenter_id"])
4122 extra
= {"params": (sfp
['vim_sfp_id'])}
4124 "instance_action_id": instance_action_id
,
4125 "task_index": task_index
,
4126 "datacenter_vim_id": sfp
["datacenter_tenant_id"],
4128 "status": "SCHEDULED",
4129 "item": "instance_sfps",
4130 "item_id": sfp
["uuid"],
4131 "related": sfp
["related"],
4132 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4135 db_vim_actions
.append(db_vim_action
)
4137 for classification
in instanceDict
['classifications']:
4138 vimthread_affected
[classification
["datacenter_tenant_id"]] = None
4139 datacenter_key
= (classification
["datacenter_id"], classification
["datacenter_tenant_id"])
4140 if datacenter_key
not in myvims
:
4142 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, classification
["datacenter_id"], classification
["datacenter_tenant_id"])
4143 except NfvoException
as e
:
4144 logger
.error(str(e
))
4146 myvim_threads
[datacenter_key
] = myvim_thread
4147 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=classification
["datacenter_id"],
4148 datacenter_tenant_id
=classification
["datacenter_tenant_id"])
4150 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(classification
["datacenter_id"],
4151 classification
["datacenter_tenant_id"]))
4152 myvims
[datacenter_key
] = None
4154 myvims
[datacenter_key
] = vims
.values()[0]
4155 myvim
= myvims
[datacenter_key
]
4156 myvim_thread
= myvim_threads
[datacenter_key
]
4159 error_msg
+= "\n vim_classification_id={} cannot be deleted because datacenter={} not found".format(classification
['vim_classification_id'],
4160 classification
["datacenter_id"])
4162 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfps"]
4163 extra
= {"params": (classification
['vim_classification_id']), "depends_on": depends_on
}
4165 "instance_action_id": instance_action_id
,
4166 "task_index": task_index
,
4167 "datacenter_vim_id": classification
["datacenter_tenant_id"],
4169 "status": "SCHEDULED",
4170 "item": "instance_classifications",
4171 "item_id": classification
["uuid"],
4172 "related": classification
["related"],
4173 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4176 db_vim_actions
.append(db_vim_action
)
4178 for sf
in instanceDict
.get('sfs', ()):
4179 vimthread_affected
[sf
["datacenter_tenant_id"]] = None
4180 datacenter_key
= (sf
["datacenter_id"], sf
["datacenter_tenant_id"])
4181 if datacenter_key
not in myvims
:
4183 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sf
["datacenter_id"], sf
["datacenter_tenant_id"])
4184 except NfvoException
as e
:
4185 logger
.error(str(e
))
4187 myvim_threads
[datacenter_key
] = myvim_thread
4188 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sf
["datacenter_id"],
4189 datacenter_tenant_id
=sf
["datacenter_tenant_id"])
4191 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sf
["datacenter_id"], sf
["datacenter_tenant_id"]))
4192 myvims
[datacenter_key
] = None
4194 myvims
[datacenter_key
] = vims
.values()[0]
4195 myvim
= myvims
[datacenter_key
]
4196 myvim_thread
= myvim_threads
[datacenter_key
]
4199 error_msg
+= "\n vim_sf_id={} cannot be deleted because datacenter={} not found".format(sf
['vim_sf_id'], sf
["datacenter_id"])
4201 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfps"]
4202 extra
= {"params": (sf
['vim_sf_id']), "depends_on": depends_on
}
4204 "instance_action_id": instance_action_id
,
4205 "task_index": task_index
,
4206 "datacenter_vim_id": sf
["datacenter_tenant_id"],
4208 "status": "SCHEDULED",
4209 "item": "instance_sfs",
4210 "item_id": sf
["uuid"],
4211 "related": sf
["related"],
4212 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4215 db_vim_actions
.append(db_vim_action
)
4217 for sfi
in instanceDict
.get('sfis', ()):
4218 vimthread_affected
[sfi
["datacenter_tenant_id"]] = None
4219 datacenter_key
= (sfi
["datacenter_id"], sfi
["datacenter_tenant_id"])
4220 if datacenter_key
not in myvims
:
4222 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sfi
["datacenter_id"], sfi
["datacenter_tenant_id"])
4223 except NfvoException
as e
:
4224 logger
.error(str(e
))
4226 myvim_threads
[datacenter_key
] = myvim_thread
4227 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sfi
["datacenter_id"],
4228 datacenter_tenant_id
=sfi
["datacenter_tenant_id"])
4230 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfi
["datacenter_id"], sfi
["datacenter_tenant_id"]))
4231 myvims
[datacenter_key
] = None
4233 myvims
[datacenter_key
] = vims
.values()[0]
4234 myvim
= myvims
[datacenter_key
]
4235 myvim_thread
= myvim_threads
[datacenter_key
]
4238 error_msg
+= "\n vim_sfi_id={} cannot be deleted because datacenter={} not found".format(sfi
['vim_sfi_id'], sfi
["datacenter_id"])
4240 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfs"]
4241 extra
= {"params": (sfi
['vim_sfi_id']), "depends_on": depends_on
}
4243 "instance_action_id": instance_action_id
,
4244 "task_index": task_index
,
4245 "datacenter_vim_id": sfi
["datacenter_tenant_id"],
4247 "status": "SCHEDULED",
4248 "item": "instance_sfis",
4249 "item_id": sfi
["uuid"],
4250 "related": sfi
["related"],
4251 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4254 db_vim_actions
.append(db_vim_action
)
4258 for sce_vnf
in instanceDict
.get('vnfs', ()):
4259 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
4260 vimthread_affected
[sce_vnf
["datacenter_tenant_id"]] = None
4261 if datacenter_key
not in myvims
:
4263 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
4264 except NfvoException
as e
:
4265 logger
.error(str(e
))
4267 myvim_threads
[datacenter_key
] = myvim_thread
4268 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
4269 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
4271 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
4272 sce_vnf
["datacenter_tenant_id"]))
4273 myvims
[datacenter_key
] = None
4275 myvims
[datacenter_key
] = vims
.values()[0]
4276 myvim
= myvims
[datacenter_key
]
4277 myvim_thread
= myvim_threads
[datacenter_key
]
4279 for vm
in sce_vnf
['vms']:
4281 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
4283 sfi_dependencies
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfis"]
4285 "instance_action_id": instance_action_id
,
4286 "task_index": task_index
,
4287 "datacenter_vim_id": sce_vnf
["datacenter_tenant_id"],
4289 "status": "SCHEDULED",
4290 "item": "instance_vms",
4291 "item_id": vm
["uuid"],
4292 "related": vm
["related"],
4293 "extra": yaml
.safe_dump({"params": vm
["interfaces"], "depends_on": sfi_dependencies
},
4294 default_flow_style
=True, width
=256)
4296 db_vim_actions
.append(db_vim_action
)
4297 for interface
in vm
["interfaces"]:
4298 if not interface
.get("instance_net_id"):
4300 if interface
["instance_net_id"] not in net2vm_dependencies
:
4301 net2vm_dependencies
[interface
["instance_net_id"]] = []
4302 net2vm_dependencies
[interface
["instance_net_id"]].append(task_index
)
4307 for net
in instanceDict
['nets']:
4308 vimthread_affected
[net
["datacenter_tenant_id"]] = None
4309 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
4310 if datacenter_key
not in myvims
:
4312 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, net
["datacenter_id"], net
["datacenter_tenant_id"])
4313 except NfvoException
as e
:
4314 logger
.error(str(e
))
4316 myvim_threads
[datacenter_key
] = myvim_thread
4317 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
4318 datacenter_tenant_id
=net
["datacenter_tenant_id"])
4320 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
4321 myvims
[datacenter_key
] = None
4323 myvims
[datacenter_key
] = vims
.values()[0]
4324 myvim
= myvims
[datacenter_key
]
4325 myvim_thread
= myvim_threads
[datacenter_key
]
4328 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
4330 extra
= {"params": (net
['vim_net_id'], net
['sdn_net_id'])}
4331 if net2vm_dependencies
.get(net
["uuid"]):
4332 extra
["depends_on"] = net2vm_dependencies
[net
["uuid"]]
4333 sfi_dependencies
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfis"]
4334 if len(sfi_dependencies
) > 0:
4335 if "depends_on" in extra
:
4336 extra
["depends_on"] += sfi_dependencies
4338 extra
["depends_on"] = sfi_dependencies
4340 "instance_action_id": instance_action_id
,
4341 "task_index": task_index
,
4342 "datacenter_vim_id": net
["datacenter_tenant_id"],
4344 "status": "SCHEDULED",
4345 "item": "instance_nets",
4346 "item_id": net
["uuid"],
4347 "related": net
["related"],
4348 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4351 db_vim_actions
.append(db_vim_action
)
4353 db_instance_action
["number_tasks"] = task_index
4356 wim_actions
, db_instance_action
= (
4357 wim_engine
.incorporate_actions(wim_actions
, db_instance_action
))
4361 {"instance_actions": db_instance_action
},
4362 {"vim_wim_actions": db_vim_actions
+ wim_actions
}
4365 logger
.debug("delete_instance done DB tables: %s",
4366 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
4367 mydb
.new_rows(db_tables
, ())
4368 for myvim_thread_id
in vimthread_affected
.keys():
4369 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
4371 wim_engine
.dispatch(wim_actions
)
4373 if len(error_msg
) > 0:
4374 return 'action_id={} instance {} deleted but some elements could not be deleted, or already deleted '\
4375 '(error: 404) from VIM: {}'.format(instance_action_id
, message
, error_msg
)
4377 return "action_id={} instance {} deleted".format(instance_action_id
, message
)
4379 def get_instance_id(mydb
, tenant_id
, instance_id
):
4381 #check valid tenant_id
4382 check_tenant(mydb
, tenant_id
)
4385 instance_dict
= mydb
.get_instance_scenario(instance_id
, tenant_id
, verbose
=True)
4386 for net
in instance_dict
["nets"]:
4387 if net
.get("sdn_net_id"):
4388 net_sdn
= ovim
.show_network(net
["sdn_net_id"])
4390 "admin_state_up": net_sdn
.get("admin_state_up"),
4391 "flows": net_sdn
.get("flows"),
4392 "last_error": net_sdn
.get("last_error"),
4393 "ports": net_sdn
.get("ports"),
4394 "type": net_sdn
.get("type"),
4395 "status": net_sdn
.get("status"),
4396 "vlan": net_sdn
.get("vlan"),
4398 return instance_dict
4400 @deprecated("Instance is automatically refreshed by vim_threads")
4401 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
4402 '''Refreshes a scenario instance. It modifies instanceDict'''
4404 - 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
4407 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
4408 # #print "nfvo.refresh_instance begins"
4409 # #print json.dumps(instanceDict, indent=4)
4411 # #print "Getting the VIM URL and the VIM tenant_id"
4414 # # 1. Getting VIM vm and net list
4415 # vms_updated = [] #List of VM instance uuids in openmano that were updated
4418 # for sce_vnf in instanceDict['vnfs']:
4419 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
4420 # if datacenter_key not in vm_list:
4421 # vm_list[datacenter_key] = []
4422 # if datacenter_key not in myvims:
4423 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
4424 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
4425 # if len(vims) == 0:
4426 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
4427 # myvims[datacenter_key] = None
4429 # myvims[datacenter_key] = vims.values()[0]
4430 # for vm in sce_vnf['vms']:
4431 # vm_list[datacenter_key].append(vm['vim_vm_id'])
4432 # vms_notupdated.append(vm["uuid"])
4434 # nets_updated = [] #List of VM instance uuids in openmano that were updated
4435 # nets_notupdated=[]
4437 # for net in instanceDict['nets']:
4438 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
4439 # if datacenter_key not in net_list:
4440 # net_list[datacenter_key] = []
4441 # if datacenter_key not in myvims:
4442 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
4443 # datacenter_tenant_id=net["datacenter_tenant_id"])
4444 # if len(vims) == 0:
4445 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
4446 # myvims[datacenter_key] = None
4448 # myvims[datacenter_key] = vims.values()[0]
4450 # net_list[datacenter_key].append(net['vim_net_id'])
4451 # nets_notupdated.append(net["uuid"])
4453 # # 1. Getting the status of all VMs
4455 # for datacenter_key in myvims:
4456 # if not vm_list.get(datacenter_key):
4460 # if not myvims[datacenter_key]:
4461 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
4464 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
4466 # except vimconn.vimconnException as e:
4467 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
4468 # failed_message = str(e)
4470 # for vm in vm_list[datacenter_key]:
4471 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
4473 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
4474 # for sce_vnf in instanceDict['vnfs']:
4475 # for vm in sce_vnf['vms']:
4476 # vm_id = vm['vim_vm_id']
4477 # interfaces = vm_dict[vm_id].pop('interfaces', [])
4478 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
4479 # has_mgmt_iface = False
4480 # for iface in vm["interfaces"]:
4481 # if iface["type"]=="mgmt":
4482 # has_mgmt_iface = True
4483 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
4484 # vm_dict[vm_id]['status'] = "ACTIVE"
4485 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
4486 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
4487 # 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'):
4488 # vm['status'] = vm_dict[vm_id]['status']
4489 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
4490 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
4491 # # 2.1. Update in openmano DB the VMs whose status changed
4493 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
4494 # vms_notupdated.remove(vm["uuid"])
4496 # vms_updated.append(vm["uuid"])
4497 # except db_base_Exception as e:
4498 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
4499 # # 2.2. Update in openmano DB the interface VMs
4500 # for interface in interfaces:
4501 # #translate from vim_net_id to instance_net_id
4502 # network_id_list=[]
4503 # for net in instanceDict['nets']:
4504 # if net["vim_net_id"] == interface["vim_net_id"]:
4505 # network_id_list.append(net["uuid"])
4506 # if not network_id_list:
4508 # del interface["vim_net_id"]
4510 # for network_id in network_id_list:
4511 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
4512 # except db_base_Exception as e:
4513 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
4515 # # 3. Getting the status of all nets
4517 # for datacenter_key in myvims:
4518 # if not net_list.get(datacenter_key):
4521 # failed_message = ""
4522 # if not myvims[datacenter_key]:
4523 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
4526 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
4528 # except vimconn.vimconnException as e:
4529 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
4530 # failed_message = str(e)
4532 # for net in net_list[datacenter_key]:
4533 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
4535 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
4536 # # TODO: update nets inside a vnf
4537 # for net in instanceDict['nets']:
4538 # net_id = net['vim_net_id']
4539 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
4540 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
4541 # 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'):
4542 # net['status'] = net_dict[net_id]['status']
4543 # net['error_msg'] = net_dict[net_id].get('error_msg')
4544 # net['vim_info'] = net_dict[net_id].get('vim_info')
4545 # # 5.1. Update in openmano DB the nets whose status changed
4547 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
4548 # nets_notupdated.remove(net["uuid"])
4550 # nets_updated.append(net["uuid"])
4551 # except db_base_Exception as e:
4552 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
4554 # # Returns appropriate output
4555 # #print "nfvo.refresh_instance finishes"
4556 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
4557 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
4558 instance_id
= instanceDict
['uuid']
4559 # if len(vms_notupdated)+len(nets_notupdated)>0:
4560 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
4561 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
4563 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
4565 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
4566 #print "Checking that the instance_id exists and getting the instance dictionary"
4567 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
4568 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
4570 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
4571 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
4573 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), httperrors
.Not_Found
)
4574 myvim
= vims
.values()[0]
4579 myvim_threads_id
= {}
4580 if action_dict
.get("vdu-scaling"):
4581 db_instance_vms
= []
4583 db_instance_interfaces
= []
4584 instance_action_id
= get_task_id()
4585 db_instance_action
= {
4586 "uuid": instance_action_id
, # same uuid for the instance and the action on create
4587 "tenant_id": nfvo_tenant
,
4588 "instance_id": instance_id
,
4589 "description": "SCALE",
4591 vm_result
["instance_action_id"] = instance_action_id
4592 vm_result
["created"] = []
4593 vm_result
["deleted"] = []
4595 for vdu
in action_dict
["vdu-scaling"]:
4596 vdu_id
= vdu
.get("vdu-id")
4597 osm_vdu_id
= vdu
.get("osm_vdu_id")
4598 member_vnf_index
= vdu
.get("member-vnf-index")
4599 vdu_count
= vdu
.get("count", 1)
4601 target_vms
= mydb
.get_rows(
4602 FROM
="instance_vms as vms join instance_vnfs as vnfs on vms.instance_vnf_id=vnfs.uuid",
4603 WHERE
={"vms.uuid": vdu_id
},
4604 ORDER_BY
="vms.created_at"
4607 raise NfvoException("Cannot find the vdu with id {}".format(vdu_id
), httperrors
.Not_Found
)
4609 if not osm_vdu_id
and not member_vnf_index
:
4610 raise NfvoException("Invalid input vdu parameters. Must supply either 'vdu-id' of 'osm_vdu_id','member-vnf-index'")
4611 target_vms
= mydb
.get_rows(
4612 # SELECT=("ivms.uuid", "ivnfs.datacenter_id", "ivnfs.datacenter_tenant_id"),
4613 FROM
="instance_vms as ivms join instance_vnfs as ivnfs on ivms.instance_vnf_id=ivnfs.uuid"\
4614 " join sce_vnfs as svnfs on ivnfs.sce_vnf_id=svnfs.uuid"\
4615 " join vms on ivms.vm_id=vms.uuid",
4616 WHERE
={"vms.osm_id": osm_vdu_id
, "svnfs.member_vnf_index": member_vnf_index
,
4617 "ivnfs.instance_scenario_id": instance_id
},
4618 ORDER_BY
="ivms.created_at"
4621 raise NfvoException("Cannot find the vdu with osm_vdu_id {} and member-vnf-index {}".format(osm_vdu_id
, member_vnf_index
), httperrors
.Not_Found
)
4622 vdu_id
= target_vms
[-1]["uuid"]
4623 target_vm
= target_vms
[-1]
4624 datacenter
= target_vm
["datacenter_id"]
4625 myvim_threads_id
[datacenter
], _
= get_vim_thread(mydb
, nfvo_tenant
, datacenter
)
4627 if vdu
["type"] == "delete":
4628 for index
in range(0, vdu_count
):
4629 target_vm
= target_vms
[-1-index
]
4630 vdu_id
= target_vm
["uuid"]
4632 vm_interfaces
= None
4633 for sce_vnf
in instanceDict
['vnfs']:
4634 for vm
in sce_vnf
['vms']:
4635 if vm
["uuid"] == vdu_id
:
4636 # TODO revise this should not be vm["uuid"] instance_vms["vm_id"]
4637 vm_interfaces
= vm
["interfaces"]
4641 "instance_action_id": instance_action_id
,
4642 "task_index": task_index
,
4643 "datacenter_vim_id": target_vm
["datacenter_tenant_id"],
4645 "status": "SCHEDULED",
4646 "item": "instance_vms",
4648 "related": target_vm
["related"],
4649 "extra": yaml
.safe_dump({"params": vm_interfaces
},
4650 default_flow_style
=True, width
=256)
4653 db_vim_actions
.append(db_vim_action
)
4654 vm_result
["deleted"].append(vdu_id
)
4655 # delete from database
4656 db_instance_vms
.append({"TO-DELETE": vdu_id
})
4658 else: # vdu["type"] == "create":
4660 where
= {"item": "instance_vms", "item_id": target_vm
["uuid"], "action": "CREATE"}
4662 vim_action_to_clone
= mydb
.get_rows(FROM
="vim_wim_actions", WHERE
=where
)
4663 if not vim_action_to_clone
:
4664 raise NfvoException("Cannot find the vim_action at database with {}".format(where
), httperrors
.Internal_Server_Error
)
4665 vim_action_to_clone
= vim_action_to_clone
[0]
4666 extra
= yaml
.safe_load(vim_action_to_clone
["extra"])
4668 # generate a new depends_on. Convert format TASK-Y into new format TASK-ACTION-XXXX.XXXX.Y
4669 # TODO do the same for flavor and image when available
4670 task_depends_on
= []
4671 task_params
= extra
["params"]
4672 task_params_networks
= deepcopy(task_params
[5])
4673 for iface
in task_params
[5]:
4674 if iface
["net_id"].startswith("TASK-"):
4675 if "." not in iface
["net_id"]:
4676 task_depends_on
.append("{}.{}".format(vim_action_to_clone
["instance_action_id"],
4677 iface
["net_id"][5:]))
4678 iface
["net_id"] = "TASK-{}.{}".format(vim_action_to_clone
["instance_action_id"],
4679 iface
["net_id"][5:])
4681 task_depends_on
.append(iface
["net_id"][5:])
4682 if "mac_address" in iface
:
4683 del iface
["mac_address"]
4685 vm_ifaces_to_clone
= mydb
.get_rows(FROM
="instance_interfaces", WHERE
={"instance_vm_id": target_vm
["uuid"]})
4686 for index
in range(0, vdu_count
):
4687 vm_uuid
= str(uuid4())
4688 vm_name
= target_vm
.get('vim_name')
4690 suffix
= vm_name
.rfind("-")
4691 vm_name
= vm_name
[:suffix
+1] + str(index
+ 1 + int(vm_name
[suffix
+1:]))
4697 'instance_vnf_id': target_vm
['instance_vnf_id'],
4698 'vm_id': target_vm
['vm_id'],
4699 'vim_name': vm_name
,
4701 db_instance_vms
.append(db_instance_vm
)
4703 for vm_iface
in vm_ifaces_to_clone
:
4704 iface_uuid
= str(uuid4())
4705 iface2iface
[vm_iface
["uuid"]] = iface_uuid
4708 'instance_vm_id': vm_uuid
,
4709 "instance_net_id": vm_iface
["instance_net_id"],
4710 'interface_id': vm_iface
['interface_id'],
4711 'type': vm_iface
['type'],
4712 'floating_ip': vm_iface
['floating_ip'],
4713 'port_security': vm_iface
['port_security']
4715 db_instance_interfaces
.append(db_vm_iface
)
4716 task_params_copy
= deepcopy(task_params
)
4717 for iface
in task_params_copy
[5]:
4718 iface
["uuid"] = iface2iface
[iface
["uuid"]]
4719 # increment ip_address
4720 if "ip_address" in iface
:
4721 ip
= iface
.get("ip_address")
4726 ip
= ip
[i
:] + str(int(ip
[:i
]) + 1)
4727 iface
["ip_address"] = ip
4729 iface
["ip_address"] = None
4731 task_params_copy
[0] = vm_name
4733 "instance_action_id": instance_action_id
,
4734 "task_index": task_index
,
4735 "datacenter_vim_id": vim_action_to_clone
["datacenter_vim_id"],
4737 "status": "SCHEDULED",
4738 "item": "instance_vms",
4743 # TODO examinar parametros, quitar MAC o incrementar. Incrementar IP y colocar las dependencias con ACTION-asdfasd.
4746 "extra": yaml
.safe_dump({"params": task_params_copy
, "depends_on": task_depends_on
}, default_flow_style
=True, width
=256)
4749 db_vim_actions
.append(db_vim_action
)
4750 vm_result
["created"].append(vm_uuid
)
4752 db_instance_action
["number_tasks"] = task_index
4754 {"instance_vms": db_instance_vms
},
4755 {"instance_interfaces": db_instance_interfaces
},
4756 {"instance_actions": db_instance_action
},
4758 # {"instance_sfis": db_instance_sfis},
4759 # {"instance_sfs": db_instance_sfs},
4760 # {"instance_classifications": db_instance_classifications},
4761 # {"instance_sfps": db_instance_sfps},
4762 {"vim_wim_actions": db_vim_actions
}
4764 logger
.debug("create_vdu done DB tables: %s",
4765 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
4766 mydb
.new_rows(db_tables
, [])
4767 for myvim_thread
in myvim_threads_id
.values():
4768 vim_threads
["running"][myvim_thread
].insert_task(db_vim_actions
)
4772 input_vnfs
= action_dict
.pop("vnfs", [])
4773 input_vms
= action_dict
.pop("vms", [])
4774 action_over_all
= True if not input_vnfs
and not input_vms
else False
4775 for sce_vnf
in instanceDict
['vnfs']:
4776 for vm
in sce_vnf
['vms']:
4777 if not action_over_all
and sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
4778 sce_vnf
['member_vnf_index'] not in input_vnfs
and \
4779 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
and \
4780 sce_vnf
['member_vnf_index'] + "-" + vm
['vdu_osm_id'] not in input_vms
: # TODO conside vm_count_index
4783 if "add_public_key" in action_dict
:
4784 if sce_vnf
.get('mgmt_access'):
4785 mgmt_access
= yaml
.load(sce_vnf
['mgmt_access'])
4786 if not input_vms
and mgmt_access
.get("vdu-id") != vm
['vdu_osm_id']:
4788 default_user
= mgmt_access
.get("default-user")
4789 password
= mgmt_access
.get("password")
4790 if mgmt_access
.get(vm
['vdu_osm_id']):
4791 default_user
= mgmt_access
[vm
['vdu_osm_id']].get("default-user", default_user
)
4792 password
= mgmt_access
[vm
['vdu_osm_id']].get("password", password
)
4794 tenant
= mydb
.get_rows_by_id('nfvo_tenants', nfvo_tenant
)
4796 if 'ip_address' in vm
:
4797 mgmt_ip
= vm
['ip_address'].split(';')
4798 priv_RO_key
= decrypt_key(tenant
[0]['encrypted_RO_priv_key'], tenant
[0]['uuid'])
4799 myvim
.inject_user_key(mgmt_ip
[0], action_dict
.get('user', default_user
),
4800 action_dict
['add_public_key'],
4801 password
=password
, ro_key
=priv_RO_key
)
4803 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4804 httperrors
.Internal_Server_Error
)
4806 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4807 httperrors
.Internal_Server_Error
)
4809 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
4810 if "console" in action_dict
:
4811 if not global_config
["http_console_proxy"]:
4812 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4813 "description": "{protocol}//{ip}:{port}/{suffix}".format(
4814 protocol
=data
["protocol"],
4815 ip
= data
["server"],
4816 port
= data
["port"],
4817 suffix
= data
["suffix"]),
4821 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
4822 vm_result
[ vm
['uuid'] ] = {"vim_result": -httperrors
.Unauthorized
,
4823 "description": "this console is only reachable by local interface",
4828 #print "console data", data
4830 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
4831 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4832 "description": "{protocol}//{ip}:{port}/{suffix}".format(
4833 protocol
=data
["protocol"],
4834 ip
= global_config
["http_console_host"],
4835 port
= console_thread
.port
,
4836 suffix
= data
["suffix"]),
4840 except NfvoException
as e
:
4841 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
4845 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
4847 except vimconn
.vimconnException
as e
:
4848 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
4851 if vm_ok
==0: #all goes wrong
4856 def instance_action_get(mydb
, nfvo_tenant
, instance_id
, action_id
):
4858 if nfvo_tenant
and nfvo_tenant
!= "any":
4859 filter["tenant_id"] = nfvo_tenant
4860 if instance_id
and instance_id
!= "any":
4861 filter["instance_id"] = instance_id
4863 filter["uuid"] = action_id
4864 rows
= mydb
.get_rows(FROM
="instance_actions", WHERE
=filter)
4867 raise NfvoException("Not found any action with this criteria", httperrors
.Not_Found
)
4868 vim_wim_actions
= mydb
.get_rows(FROM
="vim_wim_actions", WHERE
={"instance_action_id": action_id
})
4869 rows
[0]["vim_wim_actions"] = vim_wim_actions
4870 # for backward compatibility set vim_actions = vim_wim_actions
4871 rows
[0]["vim_actions"] = vim_wim_actions
4872 return {"actions": rows
}
4875 def create_or_use_console_proxy_thread(console_server
, console_port
):
4876 #look for a non-used port
4877 console_thread_key
= console_server
+ ":" + str(console_port
)
4878 if console_thread_key
in global_config
["console_thread"]:
4879 #global_config["console_thread"][console_thread_key].start_timeout()
4880 return global_config
["console_thread"][console_thread_key
]
4882 for port
in global_config
["console_port_iterator"]():
4883 #print "create_or_use_console_proxy_thread() port:", port
4884 if port
in global_config
["console_ports"]:
4887 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
4889 global_config
["console_thread"][console_thread_key
] = clithread
4890 global_config
["console_ports"][port
] = console_thread_key
4892 except cli
.ConsoleProxyExceptionPortUsed
as e
:
4893 #port used, try with onoher
4895 except cli
.ConsoleProxyException
as e
:
4896 raise NfvoException(str(e
), httperrors
.Bad_Request
)
4897 raise NfvoException("Not found any free 'http_console_ports'", httperrors
.Conflict
)
4900 def check_tenant(mydb
, tenant_id
):
4901 '''check that tenant exists at database'''
4902 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
4904 raise NfvoException("tenant '{}' not found".format(tenant_id
), httperrors
.Not_Found
)
4907 def new_tenant(mydb
, tenant_dict
):
4909 tenant_uuid
= str(uuid4())
4910 tenant_dict
['uuid'] = tenant_uuid
4912 pub_key
, priv_key
= create_RO_keypair(tenant_uuid
)
4913 tenant_dict
['RO_pub_key'] = pub_key
4914 tenant_dict
['encrypted_RO_priv_key'] = priv_key
4915 mydb
.new_row("nfvo_tenants", tenant_dict
, confidential_data
=True)
4916 except db_base_Exception
as e
:
4917 raise NfvoException("Error creating the new tenant: {} ".format(tenant_dict
['name']) + str(e
), e
.http_code
)
4920 def delete_tenant(mydb
, tenant
):
4921 #get nfvo_tenant info
4923 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
4924 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
4925 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
4928 def new_datacenter(mydb
, datacenter_descriptor
):
4929 sdn_port_mapping
= None
4930 if "config" in datacenter_descriptor
:
4931 sdn_port_mapping
= datacenter_descriptor
["config"].pop("sdn-port-mapping", None)
4932 datacenter_descriptor
["config"] = yaml
.safe_dump(datacenter_descriptor
["config"], default_flow_style
=True,
4934 # Check that datacenter-type is correct
4935 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
4936 # module_info = None
4938 module
= "vimconn_" + datacenter_type
4939 pkg
= __import__("osm_ro." + module
)
4940 # vim_conn = getattr(pkg, module)
4941 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
4942 except (IOError, ImportError):
4943 # if module_info and module_info[0]:
4944 # file.close(module_info[0])
4945 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}.py' not installed".format(datacenter_type
,
4947 httperrors
.Bad_Request
)
4949 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True, confidential_data
=True)
4950 if sdn_port_mapping
:
4952 datacenter_sdn_port_mapping_set(mydb
, None, datacenter_id
, sdn_port_mapping
)
4953 except Exception as e
:
4954 mydb
.delete_row_by_id("datacenters", datacenter_id
) # Rollback
4956 return datacenter_id
4959 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
4960 # obtain data, check that only one exist
4961 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
4964 datacenter_id
= datacenter
['uuid']
4965 where
= {'uuid': datacenter
['uuid']}
4966 remove_port_mapping
= False
4967 new_sdn_port_mapping
= None
4968 if "config" in datacenter_descriptor
:
4969 if datacenter_descriptor
['config'] != None:
4971 new_config_dict
= datacenter_descriptor
["config"]
4972 if "sdn-port-mapping" in new_config_dict
:
4973 remove_port_mapping
= True
4974 new_sdn_port_mapping
= new_config_dict
.pop("sdn-port-mapping")
4975 # delete null fields
4977 for k
in new_config_dict
:
4978 if new_config_dict
[k
] is None:
4980 if k
== 'sdn-controller':
4981 remove_port_mapping
= True
4983 config_text
= datacenter
.get("config")
4986 config_dict
= yaml
.load(config_text
)
4987 config_dict
.update(new_config_dict
)
4988 # delete null fields
4991 except Exception as e
:
4992 raise NfvoException("Bad format at datacenter:config " + str(e
), httperrors
.Bad_Request
)
4994 datacenter_descriptor
["config"] = yaml
.safe_dump(config_dict
, default_flow_style
=True, width
=256)
4996 datacenter_descriptor
["config"] = None
4997 if remove_port_mapping
:
4999 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_id
)
5000 except ovimException
as e
:
5001 raise NfvoException("Error deleting datacenter-port-mapping " + str(e
), httperrors
.Conflict
)
5003 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
5004 if new_sdn_port_mapping
:
5006 datacenter_sdn_port_mapping_set(mydb
, None, datacenter_id
, new_sdn_port_mapping
)
5007 except ovimException
as e
:
5009 mydb
.update_rows('datacenters', datacenter
, where
)
5010 raise NfvoException("Error adding datacenter-port-mapping " + str(e
), httperrors
.Conflict
)
5011 return datacenter_id
5014 def delete_datacenter(mydb
, datacenter
):
5015 #get nfvo_tenant info
5016 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
5017 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
5019 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_dict
['uuid'])
5020 except ovimException
as e
:
5021 raise NfvoException("Error deleting datacenter-port-mapping " + str(e
))
5022 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
5025 def create_vim_account(mydb
, nfvo_tenant
, datacenter_id
, name
=None, vim_id
=None, vim_tenant
=None, vim_tenant_name
=None,
5026 vim_username
=None, vim_password
=None, config
=None):
5027 # get datacenter info
5029 if not datacenter_id
:
5031 raise NfvoException("You must provide 'vim_id", http_code
=httperrors
.Bad_Request
)
5032 datacenter_id
= vim_id
5033 datacenter_id
, datacenter_name
= get_datacenter_uuid(mydb
, None, datacenter_id
)
5035 create_vim_tenant
= True if not vim_tenant
and not vim_tenant_name
else False
5037 # get nfvo_tenant info
5038 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
5039 if vim_tenant_name
==None:
5040 vim_tenant_name
=tenant_dict
['name']
5042 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
5043 # #check that this association does not exist before
5044 # tenants_datacenters = mydb.get_rows(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict)
5045 # if len(tenants_datacenters)>0:
5046 # raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id, tenant_dict['uuid']), httperrors.Conflict)
5048 vim_tenant_id_exist_atdb
=False
5049 if not create_vim_tenant
:
5050 where_
={"datacenter_id": datacenter_id
}
5051 if vim_tenant
!=None:
5052 where_
["vim_tenant_id"] = vim_tenant
5053 if vim_tenant_name
!=None:
5054 where_
["vim_tenant_name"] = vim_tenant_name
5055 #check if vim_tenant_id is already at database
5056 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
5057 if len(datacenter_tenants_dict
)>=1:
5058 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
5059 vim_tenant_id_exist_atdb
=True
5060 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
5062 datacenter_tenants_dict
= {}
5063 #insert at table datacenter_tenants
5064 else: #if vim_tenant==None:
5065 #create tenant at VIM if not provided
5067 _
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
, vim_user
=vim_username
,
5068 vim_passwd
=vim_password
)
5069 datacenter_name
= myvim
["name"]
5070 vim_tenant
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
5071 except vimconn
.vimconnException
as e
:
5072 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), httperrors
.Internal_Server_Error
)
5073 datacenter_tenants_dict
= {}
5074 datacenter_tenants_dict
["created"]="true"
5076 #fill datacenter_tenants table
5077 if not vim_tenant_id_exist_atdb
:
5078 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant
5079 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
5080 datacenter_tenants_dict
["user"] = vim_username
5081 datacenter_tenants_dict
["passwd"] = vim_password
5082 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
5084 datacenter_tenants_dict
["name"] = name
5086 datacenter_tenants_dict
["name"] = datacenter_name
5088 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
5089 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True, confidential_data
=True)
5090 datacenter_tenants_dict
["uuid"] = id_
5092 #fill tenants_datacenters table
5093 datacenter_tenant_id
= datacenter_tenants_dict
["uuid"]
5094 tenants_datacenter_dict
["datacenter_tenant_id"] = datacenter_tenant_id
5095 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
5098 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
5099 new_thread
= vim_thread
.vim_thread(task_lock
, thread_name
, datacenter_name
, datacenter_tenant_id
,
5100 db
=db
, db_lock
=db_lock
, ovim
=ovim
)
5102 thread_id
= datacenter_tenants_dict
["uuid"]
5103 vim_threads
["running"][thread_id
] = new_thread
5105 except vimconn
.vimconnException
as e
:
5106 raise NfvoException(str(e
), httperrors
.Bad_Request
)
5109 def edit_vim_account(mydb
, nfvo_tenant
, datacenter_tenant_id
, datacenter_id
=None, name
=None, vim_tenant
=None,
5110 vim_tenant_name
=None, vim_username
=None, vim_password
=None, config
=None):
5112 # get vim_account; check is valid for this tenant
5113 from_
= "datacenter_tenants as dt JOIN tenants_datacenters as td ON dt.uuid=td.datacenter_tenant_id"
5114 where_
= {"td.nfvo_tenant_id": nfvo_tenant
}
5115 if datacenter_tenant_id
:
5116 where_
["dt.uuid"] = datacenter_tenant_id
5118 where_
["dt.datacenter_id"] = datacenter_id
5119 vim_accounts
= mydb
.get_rows(SELECT
="dt.uuid as uuid, config", FROM
=from_
, WHERE
=where_
)
5120 if not vim_accounts
:
5121 raise NfvoException("vim_account not found for this tenant", http_code
=httperrors
.Not_Found
)
5122 elif len(vim_accounts
) > 1:
5123 raise NfvoException("found more than one vim_account for this tenant", http_code
=httperrors
.Conflict
)
5124 datacenter_tenant_id
= vim_accounts
[0]["uuid"]
5125 original_config
= vim_accounts
[0]["config"]
5129 original_config_dict
= yaml
.load(original_config
)
5130 original_config_dict
.update(config
)
5131 update
["config"] = yaml
.safe_dump(original_config_dict
, default_flow_style
=True, width
=256)
5133 update_
['name'] = name
5135 update_
['vim_tenant_id'] = vim_tenant
5137 update_
['vim_tenant_name'] = vim_tenant_name
5139 update_
['user'] = vim_username
5141 update_
['passwd'] = vim_password
5143 mydb
.update_rows("datacenter_tenants", UPDATE
=update_
, WHERE
={"uuid": datacenter_tenant_id
})
5145 vim_threads
["running"][datacenter_tenant_id
].insert_task("reload")
5146 return datacenter_tenant_id
5148 def delete_vim_account(mydb
, tenant_id
, vim_account_id
, datacenter
=None):
5149 #get nfvo_tenant info
5150 if not tenant_id
or tenant_id
=="any":
5153 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
5154 tenant_uuid
= tenant_dict
['uuid']
5156 #check that this association exist before
5157 tenants_datacenter_dict
= {}
5159 datacenter_id
, _
= get_datacenter_uuid(mydb
, tenant_uuid
, datacenter
)
5160 tenants_datacenter_dict
["datacenter_id"] = datacenter_id
5161 elif vim_account_id
:
5162 tenants_datacenter_dict
["datacenter_tenant_id"] = vim_account_id
5164 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
5165 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
5166 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
5167 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), httperrors
.Not_Found
)
5169 #delete this association
5170 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
5172 #get vim_tenant info and deletes
5174 for tenant_datacenter_item
in tenant_datacenter_list
:
5175 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
5176 #try to delete vim:tenant
5178 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
5179 if vim_tenant_dict
['created']=='true':
5180 #delete tenant at VIM if created by NFVO
5182 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5183 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
5184 except vimconn
.vimconnException
as e
:
5185 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
5186 logger
.warn(warning
)
5187 except db_base_Exception
as e
:
5188 logger
.error("Cannot delete datacenter_tenants " + str(e
))
5189 pass # the error will be caused because dependencies, vim_tenant can not be deleted
5190 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
5191 thread
= vim_threads
["running"].get(thread_id
)
5193 thread
.insert_task("exit")
5194 vim_threads
["deleting"][thread_id
] = thread
5195 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
5198 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
5200 #get datacenter info
5201 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5203 if 'check-connectivity' in action_dict
:
5205 myvim
.check_vim_connectivity()
5206 except vimconn
.vimconnException
as e
:
5207 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
5208 raise NfvoException(str(e
), e
.http_code
)
5209 elif 'net-update' in action_dict
:
5211 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
5213 except vimconn
.vimconnException
as e
:
5214 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
5215 raise NfvoException(str(e
), httperrors
.Internal_Server_Error
)
5216 #update nets Change from VIM format to NFVO format
5219 net_nfvo
={'datacenter_id': datacenter_id
}
5220 net_nfvo
['name'] = net
['name']
5221 #net_nfvo['description']= net['name']
5222 net_nfvo
['vim_net_id'] = net
['id']
5223 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
5224 net_nfvo
['shared'] = net
['shared']
5225 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
5226 net_list
.append(net_nfvo
)
5227 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
5228 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
5230 elif 'net-edit' in action_dict
:
5231 net
= action_dict
['net-edit'].pop('net')
5232 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
5233 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
5234 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
5236 elif 'net-delete' in action_dict
:
5237 net
= action_dict
['net-deelte'].get('net')
5238 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
5239 result
= mydb
.delete_row(FROM
='datacenter_nets',
5240 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
5244 raise NfvoException("Unknown action " + str(action_dict
), httperrors
.Bad_Request
)
5247 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
5248 #get datacenter info
5249 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5251 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
5252 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
5253 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
5257 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
5258 #get datacenter info
5259 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5262 action_dict
= action_dict
["netmap"]
5263 if 'vim_id' in action_dict
:
5264 filter_dict
["id"] = action_dict
['vim_id']
5265 if 'vim_name' in action_dict
:
5266 filter_dict
["name"] = action_dict
['vim_name']
5268 filter_dict
["shared"] = True
5271 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
5272 except vimconn
.vimconnException
as e
:
5273 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
5274 raise NfvoException(str(e
), httperrors
.Internal_Server_Error
)
5275 if len(vim_nets
)>1 and action_dict
:
5276 raise NfvoException("more than two networks found, specify with vim_id", httperrors
.Conflict
)
5277 elif len(vim_nets
)==0: # and action_dict:
5278 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), httperrors
.Not_Found
)
5280 for net
in vim_nets
:
5281 net_nfvo
={'datacenter_id': datacenter_id
}
5282 if action_dict
and "name" in action_dict
:
5283 net_nfvo
['name'] = action_dict
['name']
5285 net_nfvo
['name'] = net
['name']
5286 #net_nfvo['description']= net['name']
5287 net_nfvo
['vim_net_id'] = net
['id']
5288 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
5289 net_nfvo
['shared'] = net
['shared']
5290 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
5292 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
5293 net_nfvo
["status"] = "OK"
5294 net_nfvo
["uuid"] = net_id
5295 except db_base_Exception
as e
:
5299 net_nfvo
["status"] = "FAIL: " + str(e
)
5300 net_list
.append(net_nfvo
)
5303 def get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
):
5304 # obtain all network data
5306 if utils
.check_valid_uuid(network_id
):
5307 filter_dict
= {"id": network_id
}
5309 filter_dict
= {"name": network_id
}
5311 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5312 network
= myvim
.get_network_list(filter_dict
=filter_dict
)
5313 except vimconn
.vimconnException
as e
:
5314 raise NfvoException("Not possible to get_sdn_net_id from VIM: {}".format(str(e
)), e
.http_code
)
5316 # ensure the network is defined
5317 if len(network
) == 0:
5318 raise NfvoException("Network {} is not present in the system".format(network_id
),
5319 httperrors
.Bad_Request
)
5321 # ensure there is only one network with the provided name
5322 if len(network
) > 1:
5323 raise NfvoException("Multiple networks present in vim identified by {}".format(network_id
), httperrors
.Bad_Request
)
5325 # ensure it is a dataplane network
5326 if network
[0]['type'] != 'data':
5329 # ensure we use the id
5330 network_id
= network
[0]['id']
5332 # search in dabase mano_db in table instance nets for the sdn_net_id that corresponds to the vim_net_id==network_id
5333 # and with instance_scenario_id==NULL
5334 #search_dict = {'vim_net_id': network_id, 'instance_scenario_id': None}
5335 search_dict
= {'vim_net_id': network_id
}
5338 #sdn_network_id = mydb.get_rows(SELECT=('sdn_net_id',), FROM='instance_nets', WHERE=search_dict)[0]['sdn_net_id']
5339 result
= mydb
.get_rows(SELECT
=('sdn_net_id',), FROM
='instance_nets', WHERE
=search_dict
)
5340 except db_base_Exception
as e
:
5341 raise NfvoException("db_base_Exception obtaining SDN network to associated to vim network {}".format(
5342 network_id
) + str(e
), e
.http_code
)
5346 if net
['sdn_net_id'] != None:
5348 sdn_net_id
= net
['sdn_net_id']
5350 if sdn_net_counter
== 0:
5352 elif sdn_net_counter
== 1:
5355 raise NfvoException("More than one SDN network is associated to vim network {}".format(
5356 network_id
), httperrors
.Internal_Server_Error
)
5358 def get_sdn_controller_id(mydb
, datacenter
):
5359 # Obtain sdn controller id
5360 config
= mydb
.get_rows(SELECT
=('config',), FROM
='datacenters', WHERE
={'uuid': datacenter
})[0].get('config', '{}')
5364 return yaml
.load(config
).get('sdn-controller')
5366 def vim_net_sdn_attach(mydb
, tenant_id
, datacenter
, network_id
, descriptor
):
5368 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
5369 if not sdn_network_id
:
5370 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
), httperrors
.Internal_Server_Error
)
5372 #Obtain sdn controller id
5373 controller_id
= get_sdn_controller_id(mydb
, datacenter
)
5374 if not controller_id
:
5375 raise NfvoException("No SDN controller is set for datacenter {}".format(datacenter
), httperrors
.Internal_Server_Error
)
5377 #Obtain sdn controller info
5378 sdn_controller
= ovim
.show_of_controller(controller_id
)
5381 'name': 'external_port',
5382 'net_id': sdn_network_id
,
5383 'ofc_id': controller_id
,
5384 'switch_dpid': sdn_controller
['dpid'],
5385 'switch_port': descriptor
['port']
5388 if 'vlan' in descriptor
:
5389 port_data
['vlan'] = descriptor
['vlan']
5390 if 'mac' in descriptor
:
5391 port_data
['mac'] = descriptor
['mac']
5393 result
= ovim
.new_port(port_data
)
5394 except ovimException
as e
:
5395 raise NfvoException("ovimException attaching SDN network {} to vim network {}".format(
5396 sdn_network_id
, network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5397 except db_base_Exception
as e
:
5398 raise NfvoException("db_base_Exception attaching SDN network to vim network {}".format(
5399 network_id
) + str(e
), e
.http_code
)
5401 return 'Port uuid: '+ result
5403 def vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, network_id
, port_id
=None):
5405 filter = {'uuid': port_id
}
5407 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
5408 if not sdn_network_id
:
5409 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
),
5410 httperrors
.Internal_Server_Error
)
5411 #in case no port_id is specified only ports marked as 'external_port' will be detached
5412 filter = {'name': 'external_port', 'net_id': sdn_network_id
}
5415 port_list
= ovim
.get_ports(columns
={'uuid'}, filter=filter)
5416 except ovimException
as e
:
5417 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
5418 httperrors
.Internal_Server_Error
)
5420 if len(port_list
) == 0:
5421 raise NfvoException("No ports attached to the network {} were found with the requested criteria".format(network_id
),
5422 httperrors
.Bad_Request
)
5425 for port
in port_list
:
5427 port_uuid_list
.append(port
['uuid'])
5428 ovim
.delete_port(port
['uuid'])
5429 except ovimException
as e
:
5430 raise NfvoException("ovimException deleting port {} for net {}. ".format(port
['uuid'], network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5432 return 'Detached ports uuid: {}'.format(','.join(port_uuid_list
))
5434 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
5435 #get datacenter info
5436 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5439 if utils
.check_valid_uuid(name
):
5440 filter_dict
["id"] = name
5442 filter_dict
["name"] = name
5444 if item
=="networks":
5445 #filter_dict['tenant_id'] = myvim['tenant_id']
5446 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
5448 if len(content
) == 0:
5449 raise NfvoException("Network {} is not present in the system. ".format(name
),
5450 httperrors
.Bad_Request
)
5452 #Update the networks with the attached ports
5454 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, net
['id'])
5455 if sdn_network_id
!= None:
5457 #port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan'}, filter={'name': 'external_port', 'net_id': sdn_network_id})
5458 port_list
= ovim
.get_ports(columns
={'uuid', 'switch_port', 'vlan','name'}, filter={'net_id': sdn_network_id
})
5459 except ovimException
as e
:
5460 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5461 #Remove field name and if port name is external_port save it as 'type'
5462 for port
in port_list
:
5463 if port
['name'] == 'external_port':
5464 port
['type'] = "External"
5466 net
['sdn_network_id'] = sdn_network_id
5467 net
['sdn_attached_ports'] = port_list
5469 elif item
=="tenants":
5470 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
5471 elif item
== "images":
5473 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
5475 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5476 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
5477 if name
and len(content
)==1:
5478 return {item
[:-1]: content
[0]}
5479 elif name
and len(content
)==0:
5480 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
5483 return {item
: content
}
5484 except vimconn
.vimconnException
as e
:
5485 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
5486 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
5489 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
5490 #get datacenter info
5491 if tenant_id
== "any":
5494 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5496 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
5497 logger
.debug("vim_action_delete vim response: " + str(content
))
5498 items
= content
.values()[0]
5499 if type(items
)==list and len(items
)==0:
5500 raise NfvoException("Not found " + item
, httperrors
.Not_Found
)
5501 elif type(items
)==list and len(items
)>1:
5502 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), httperrors
.Not_Found
)
5503 else: # it is a dict
5504 item_id
= items
["id"]
5505 item_name
= str(items
.get("name"))
5508 if item
=="networks":
5509 # If there is a SDN network associated to the vim-network, proceed to clear the relationship and delete it
5510 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, item_id
)
5511 if sdn_network_id
!= None:
5512 #Delete any port attachment to this network
5514 port_list
= ovim
.get_ports(columns
={'uuid'}, filter={'net_id': sdn_network_id
})
5515 except ovimException
as e
:
5516 raise NfvoException(
5517 "ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
5518 httperrors
.Internal_Server_Error
)
5520 # By calling one by one all ports to be detached we ensure that not only the external_ports get detached
5521 for port
in port_list
:
5522 vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, item_id
, port
['uuid'])
5524 #Delete from 'instance_nets' the correspondence between the vim-net-id and the sdn-net-id
5526 mydb
.delete_row(FROM
='instance_nets', WHERE
={'instance_scenario_id': None, 'sdn_net_id': sdn_network_id
, 'vim_net_id': item_id
})
5527 except db_base_Exception
as e
:
5528 raise NfvoException("Error deleting correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
5529 str(e
), e
.http_code
)
5531 #Delete the SDN network
5533 ovim
.delete_network(sdn_network_id
)
5534 except ovimException
as e
:
5535 logger
.error("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
), exc_info
=True)
5536 raise NfvoException("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
),
5537 httperrors
.Internal_Server_Error
)
5539 content
= myvim
.delete_network(item_id
)
5540 elif item
=="tenants":
5541 content
= myvim
.delete_tenant(item_id
)
5542 elif item
== "images":
5543 content
= myvim
.delete_image(item_id
)
5545 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5546 except vimconn
.vimconnException
as e
:
5547 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
5548 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
5550 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
5553 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
5554 #get datacenter info
5555 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
5556 if tenant_id
== "any":
5558 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5560 if item
=="networks":
5561 net
= descriptor
["network"]
5562 net_name
= net
.pop("name")
5563 net_type
= net
.pop("type", "bridge")
5564 net_public
= net
.pop("shared", False)
5565 net_ipprofile
= net
.pop("ip_profile", None)
5566 net_vlan
= net
.pop("vlan", None)
5567 content
, _
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
5569 #If the datacenter has a SDN controller defined and the network is of dataplane type, then create the sdn network
5570 if get_sdn_controller_id(mydb
, datacenter
) != None and (net_type
== 'data' or net_type
== 'ptp'):
5571 #obtain datacenter_tenant_id
5572 datacenter_tenant_id
= mydb
.get_rows(SELECT
=('uuid',),
5573 FROM
='datacenter_tenants',
5574 WHERE
={'datacenter_id': datacenter
})[0]['uuid']
5577 sdn_network
['vlan'] = net_vlan
5578 sdn_network
['type'] = net_type
5579 sdn_network
['name'] = net_name
5580 sdn_network
['region'] = datacenter_tenant_id
5581 ovim_content
= ovim
.new_network(sdn_network
)
5582 except ovimException
as e
:
5583 logger
.error("ovimException creating SDN network={} ".format(
5584 sdn_network
) + str(e
), exc_info
=True)
5585 raise NfvoException("ovimException creating SDN network={} ".format(sdn_network
) + str(e
),
5586 httperrors
.Internal_Server_Error
)
5588 # Save entry in in dabase mano_db in table instance_nets to stablish a dictionary vim_net_id <->sdn_net_id
5589 # use instance_scenario_id=None to distinguish from real instaces of nets
5590 correspondence
= {'instance_scenario_id': None,
5591 'sdn_net_id': ovim_content
,
5592 'vim_net_id': content
,
5593 'datacenter_tenant_id': datacenter_tenant_id
5596 mydb
.new_row('instance_nets', correspondence
, add_uuid
=True)
5597 except db_base_Exception
as e
:
5598 raise NfvoException("Error saving correspondence for VIM/SDN dataplane networks{}: {}".format(
5599 correspondence
, e
), e
.http_code
)
5600 elif item
=="tenants":
5601 tenant
= descriptor
["tenant"]
5602 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
5604 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5605 except vimconn
.vimconnException
as e
:
5606 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
5608 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
5610 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
5611 data
= ovim
.new_of_controller(sdn_controller
)
5612 logger
.debug('New SDN controller created with uuid {}'.format(data
))
5615 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
5616 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
5617 msg
= 'SDN controller {} updated'.format(data
)
5621 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
5622 if controller_id
== None:
5623 data
= ovim
.get_of_controllers()
5625 data
= ovim
.show_of_controller(controller_id
)
5627 msg
= 'SDN controller list:\n {}'.format(data
)
5631 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
5632 select_
= ('uuid', 'config')
5633 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
5634 for datacenter
in datacenters
:
5635 if datacenter
['config']:
5636 config
= yaml
.load(datacenter
['config'])
5637 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
5638 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), httperrors
.Conflict
)
5640 data
= ovim
.delete_of_controller(controller_id
)
5641 msg
= 'SDN controller {} deleted'.format(data
)
5645 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
5646 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
5647 if len(controller
) < 1:
5648 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), httperrors
.Not_Found
)
5651 sdn_controller_id
= yaml
.load(controller
[0]["config"])["sdn-controller"]
5653 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), httperrors
.Bad_Request
)
5655 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
5656 switch_dpid
= sdn_controller
["dpid"]
5659 for compute_node
in sdn_port_mapping
:
5660 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
5662 element
["compute_node"] = compute_node
["compute_node"]
5663 for port
in compute_node
["ports"]:
5664 pci
= port
.get("pci")
5665 element
["switch_port"] = port
.get("switch_port")
5666 element
["switch_mac"] = port
.get("switch_mac")
5667 if not element
["switch_port"] and not element
["switch_mac"]:
5668 raise NfvoException ("The mapping must contain 'switch_port' or 'switch_mac'", httperrors
.Bad_Request
)
5669 for pci_expanded
in utils
.expand_brackets(pci
):
5670 element
["pci"] = pci_expanded
5671 maps
.append(dict(element
))
5673 return ovim
.set_of_port_mapping(maps
, ofc_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, region
=datacenter_id
)
5675 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
5676 maps
= ovim
.get_of_port_mappings(db_filter
={"region": datacenter_id
})
5679 "sdn-controller": None,
5680 "datacenter-id": datacenter_id
,
5682 "ports_mapping": list()
5685 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
5686 if datacenter
['config']:
5687 config
= yaml
.load(datacenter
['config'])
5688 if 'sdn-controller' in config
:
5689 controller_id
= config
['sdn-controller']
5690 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
5691 result
["sdn-controller"] = controller_id
5692 result
["dpid"] = sdn_controller
["dpid"]
5694 if result
["sdn-controller"] == None:
5695 raise NfvoException("SDN controller is not defined for datacenter {}".format(datacenter_id
), httperrors
.Bad_Request
)
5696 if result
["dpid"] == None:
5697 raise NfvoException("It was not possible to determine DPID for SDN controller {}".format(result
["sdn-controller"]),
5698 httperrors
.Internal_Server_Error
)
5703 ports_correspondence_dict
= dict()
5705 if result
["sdn-controller"] != link
["ofc_id"]:
5706 raise NfvoException("The sdn-controller specified for different port mappings differ", httperrors
.Internal_Server_Error
)
5707 if result
["dpid"] != link
["switch_dpid"]:
5708 raise NfvoException("The dpid specified for different port mappings differ", httperrors
.Internal_Server_Error
)
5710 element
["pci"] = link
["pci"]
5711 if link
["switch_port"]:
5712 element
["switch_port"] = link
["switch_port"]
5713 if link
["switch_mac"]:
5714 element
["switch_mac"] = link
["switch_mac"]
5716 if not link
["compute_node"] in ports_correspondence_dict
:
5718 content
["compute_node"] = link
["compute_node"]
5719 content
["ports"] = list()
5720 ports_correspondence_dict
[link
["compute_node"]] = content
5722 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
5724 for key
in sorted(ports_correspondence_dict
):
5725 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
5729 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
5730 return ovim
.clear_of_port_mapping(db_filter
={"region":datacenter_id
})
5732 def create_RO_keypair(tenant_id
):
5734 Creates a public / private keys for a RO tenant and returns their values
5736 tenant_id: ID of the tenant
5738 public_key: Public key for the RO tenant
5739 private_key: Encrypted private key for RO tenant
5743 key
= RSA
.generate(bits
)
5745 public_key
= key
.publickey().exportKey('OpenSSH')
5746 if isinstance(public_key
, ValueError):
5747 raise NfvoException("Unable to create public key: {}".format(public_key
), httperrors
.Internal_Server_Error
)
5748 private_key
= key
.exportKey(passphrase
=tenant_id
, pkcs
=8)
5749 except (ValueError, NameError) as e
:
5750 raise NfvoException("Unable to create private key: {}".format(e
), httperrors
.Internal_Server_Error
)
5751 return public_key
, private_key
5753 def decrypt_key (key
, tenant_id
):
5755 Decrypts an encrypted RSA key
5757 key: Private key to be decrypted
5758 tenant_id: ID of the tenant
5760 unencrypted_key: Unencrypted private key for RO tenant
5763 key
= RSA
.importKey(key
,tenant_id
)
5764 unencrypted_key
= key
.exportKey('PEM')
5765 if isinstance(unencrypted_key
, ValueError):
5766 raise NfvoException("Unable to decrypt the private key: {}".format(unencrypted_key
), httperrors
.Internal_Server_Error
)
5767 except ValueError as e
:
5768 raise NfvoException("Unable to decrypt the private key: {}".format(e
), httperrors
.Internal_Server_Error
)
5769 return unencrypted_key