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
= {}
1009 cp_name2vm_uuid
= {}
1010 cp_name2db_interface
= {}
1011 vdu_id2cp_name
= {} # stored only when one external connection point is presented at this VDU
1015 vdu_id2db_table_index
= {}
1016 for vdu
in vnfd
.get("vdu").itervalues():
1018 for vdu_descriptor
in vnfd_descriptor
["vdu"]:
1019 if vdu_descriptor
["id"] == str(vdu
["id"]):
1021 vm_uuid
= str(uuid4())
1022 uuid_list
.append(vm_uuid
)
1023 vdu_id
= get_str(vdu
, "id", 255)
1027 "name": get_str(vdu
, "name", 255),
1028 "description": get_str(vdu
, "description", 255),
1029 "pdu_type": get_str(vdu
, "pdu-type", 255),
1032 vdu_id2uuid
[db_vm
["osm_id"]] = vm_uuid
1033 vdu_id2db_table_index
[db_vm
["osm_id"]] = db_vms_index
1034 if vdu
.get("count"):
1035 db_vm
["count"] = int(vdu
["count"])
1038 image_present
= False
1039 if vdu
.get("image"):
1040 image_present
= True
1042 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, vdu
)
1044 image_uuid
= db_image
["uuid"]
1045 db_images
.append(db_image
)
1046 db_vm
["image_id"] = image_uuid
1047 if vdu
.get("alternative-images"):
1048 vm_alternative_images
= []
1049 for alt_image
in vdu
.get("alternative-images").itervalues():
1051 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, alt_image
)
1053 image_uuid
= db_image
["uuid"]
1054 db_images
.append(db_image
)
1055 vm_alternative_images
.append({
1056 "image_id": image_uuid
,
1057 "vim_type": str(alt_image
["vim-type"]),
1058 # "universal_name": str(alt_image["image"]),
1059 # "checksum": str(alt_image["image-checksum"]) if alt_image.get("image-checksum") else None
1062 db_vm
["image_list"] = yaml
.safe_dump(vm_alternative_images
, default_flow_style
=True, width
=256)
1066 if vdu
.get("volumes"):
1067 for volume_key
in vdu
["volumes"]:
1068 volume
= vdu
["volumes"][volume_key
]
1069 if not image_present
:
1070 # Convert the first volume to vnfc.image
1071 image_present
= True
1073 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, volume
)
1075 image_uuid
= db_image
["uuid"]
1076 db_images
.append(db_image
)
1077 db_vm
["image_id"] = image_uuid
1079 # Add Openmano devices
1080 device
= {"name": str(volume
.get("name"))}
1081 device
["type"] = str(volume
.get("device-type"))
1082 if volume
.get("size"):
1083 device
["size"] = int(volume
["size"])
1084 if volume
.get("image"):
1085 device
["image name"] = str(volume
["image"])
1086 if volume
.get("image-checksum"):
1087 device
["image checksum"] = str(volume
["image-checksum"])
1089 devices
.append(device
)
1091 if not db_vm
.get("image_id"):
1092 if not db_vm
["pdu_type"]:
1093 raise NfvoException("Not defined image for VDU")
1094 # create a fake image
1098 if vdu
.get("cloud-init"):
1099 boot_data
["user-data"] = str(vdu
["cloud-init"])
1100 elif vdu
.get("cloud-init-file"):
1101 # TODO Where this file content is present???
1102 # boot_data["user-data"] = vnfd_yang.files[vdu["cloud-init-file"]]
1103 boot_data
["user-data"] = str(vdu
["cloud-init-file"])
1105 if vdu
.get("supplemental-boot-data"):
1106 if vdu
["supplemental-boot-data"].get('boot-data-drive'):
1107 boot_data
['boot-data-drive'] = True
1108 if vdu
["supplemental-boot-data"].get('config-file'):
1109 om_cfgfile_list
= list()
1110 for custom_config_file
in vdu
["supplemental-boot-data"]['config-file'].itervalues():
1111 # TODO Where this file content is present???
1112 cfg_source
= str(custom_config_file
["source"])
1113 om_cfgfile_list
.append({"dest": custom_config_file
["dest"],
1114 "content": cfg_source
})
1115 boot_data
['config-files'] = om_cfgfile_list
1117 db_vm
["boot_data"] = yaml
.safe_dump(boot_data
, default_flow_style
=True, width
=256)
1119 db_vms
.append(db_vm
)
1122 # table interfaces (internal/external interfaces)
1123 flavor_epa_interfaces
= []
1124 # for iface in chain(vdu.get("internal-interface").itervalues(), vdu.get("external-interface").itervalues()):
1125 for iface
in vdu
.get("interface").itervalues():
1126 flavor_epa_interface
= {}
1127 iface_uuid
= str(uuid4())
1128 uuid_list
.append(iface_uuid
)
1131 "internal_name": get_str(iface
, "name", 255),
1134 flavor_epa_interface
["name"] = db_interface
["internal_name"]
1135 if iface
.get("virtual-interface").get("vpci"):
1136 db_interface
["vpci"] = get_str(iface
.get("virtual-interface"), "vpci", 12)
1137 flavor_epa_interface
["vpci"] = db_interface
["vpci"]
1139 if iface
.get("virtual-interface").get("bandwidth"):
1140 bps
= int(iface
.get("virtual-interface").get("bandwidth"))
1141 db_interface
["bw"] = int(math
.ceil(bps
/1000000.0))
1142 flavor_epa_interface
["bandwidth"] = "{} Mbps".format(db_interface
["bw"])
1144 if iface
.get("virtual-interface").get("type") == "OM-MGMT":
1145 db_interface
["type"] = "mgmt"
1146 elif iface
.get("virtual-interface").get("type") in ("VIRTIO", "E1000", "PARAVIRT"):
1147 db_interface
["type"] = "bridge"
1148 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1149 elif iface
.get("virtual-interface").get("type") in ("SR-IOV", "PCI-PASSTHROUGH"):
1150 db_interface
["type"] = "data"
1151 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1152 flavor_epa_interface
["dedicated"] = "no" if iface
["virtual-interface"]["type"] == "SR-IOV" \
1154 flavor_epa_interfaces
.append(flavor_epa_interface
)
1156 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vdu[{}]':'interface':'virtual"
1157 "-interface':'type':'{}'. Interface type is not supported".format(
1158 vnfd_id
, vdu_id
, iface
.get("virtual-interface").get("type")),
1159 httperrors
.Bad_Request
)
1161 if iface
.get("mgmt-interface"):
1162 db_interface
["type"] = "mgmt"
1164 if iface
.get("external-connection-point-ref"):
1166 cp
= vnfd
.get("connection-point")[iface
.get("external-connection-point-ref")]
1167 db_interface
["external_name"] = get_str(cp
, "name", 255)
1168 cp_name2iface_uuid
[db_interface
["external_name"]] = iface_uuid
1169 cp_name2vm_uuid
[db_interface
["external_name"]] = vm_uuid
1170 cp_name2db_interface
[db_interface
["external_name"]] = db_interface
1171 for cp_descriptor
in vnfd_descriptor
["connection-point"]:
1172 if cp_descriptor
["name"] == db_interface
["external_name"]:
1177 if vdu_id
in vdu_id2cp_name
:
1178 vdu_id2cp_name
[vdu_id
] = None # more than two connecdtion point for this VDU
1180 vdu_id2cp_name
[vdu_id
] = db_interface
["external_name"]
1183 if str(cp_descriptor
.get("port-security-enabled")).lower() == "false":
1184 db_interface
["port_security"] = 0
1185 elif str(cp_descriptor
.get("port-security-enabled")).lower() == "true":
1186 db_interface
["port_security"] = 1
1188 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1189 "'interface[{iface}]':'vnfd-connection-point-ref':'{cp}' is not present"
1190 " at connection-point".format(
1191 vnf
=vnfd_id
, vdu
=vdu_id
, iface
=iface
["name"],
1192 cp
=iface
.get("vnfd-connection-point-ref")),
1193 httperrors
.Bad_Request
)
1194 elif iface
.get("internal-connection-point-ref"):
1196 for icp_descriptor
in vdu_descriptor
["internal-connection-point"]:
1197 if icp_descriptor
["id"] == str(iface
.get("internal-connection-point-ref")):
1200 raise KeyError("does not exist at vdu:internal-connection-point")
1203 for vld
in vnfd
.get("internal-vld").itervalues():
1204 for cp
in vld
.get("internal-connection-point").itervalues():
1205 if cp
.get("id-ref") == iface
.get("internal-connection-point-ref"):
1207 raise KeyError("is referenced by more than one 'internal-vld'")
1211 raise KeyError("is not referenced by any 'internal-vld'")
1213 db_interface
["net_id"] = net_id2uuid
[icp_vld
.get("id")]
1214 if str(icp_descriptor
.get("port-security-enabled")).lower() == "false":
1215 db_interface
["port_security"] = 0
1216 elif str(icp_descriptor
.get("port-security-enabled")).lower() == "true":
1217 db_interface
["port_security"] = 1
1218 if icp
.get("ip-address"):
1219 if not icp_vld
.get("ip-profile-ref"):
1221 db_interface
["ip_address"] = str(icp
.get("ip-address"))
1222 except KeyError as e
:
1223 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1224 "'interface[{iface}]':'internal-connection-point-ref':'{cp}'"
1226 vnf
=vnfd_id
, vdu
=vdu_id
, iface
=iface
["name"],
1227 cp
=iface
.get("internal-connection-point-ref"), msg
=str(e
)),
1228 httperrors
.Bad_Request
)
1229 if iface
.get("position"):
1230 db_interface
["created_at"] = int(iface
.get("position")) * 50
1231 if iface
.get("mac-address"):
1232 db_interface
["mac"] = str(iface
.get("mac-address"))
1233 db_interfaces
.append(db_interface
)
1237 "name": get_str(vdu
, "name", 250) + "-flv",
1238 "vcpus": int(vdu
["vm-flavor"].get("vcpu-count", 1)),
1239 "ram": int(vdu
["vm-flavor"].get("memory-mb", 1)),
1240 "disk": int(vdu
["vm-flavor"].get("storage-gb", 0)),
1242 # TODO revise the case of several numa-node-policy node
1246 extended
["devices"] = devices
1247 if flavor_epa_interfaces
:
1248 numa
["interfaces"] = flavor_epa_interfaces
1249 if vdu
.get("guest-epa"): # TODO or dedicated_int:
1250 epa_vcpu_set
= False
1251 if vdu
["guest-epa"].get("numa-node-policy"): # TODO or dedicated_int:
1252 numa_node_policy
= vdu
["guest-epa"].get("numa-node-policy")
1253 if numa_node_policy
.get("node"):
1254 numa_node
= numa_node_policy
["node"].values()[0]
1255 if numa_node
.get("num-cores"):
1256 numa
["cores"] = numa_node
["num-cores"]
1258 if numa_node
.get("paired-threads"):
1259 if numa_node
["paired-threads"].get("num-paired-threads"):
1260 numa
["paired-threads"] = int(numa_node
["paired-threads"]["num-paired-threads"])
1262 if len(numa_node
["paired-threads"].get("paired-thread-ids")):
1263 numa
["paired-threads-id"] = []
1264 for pair
in numa_node
["paired-threads"]["paired-thread-ids"].itervalues():
1265 numa
["paired-threads-id"].append(
1266 (str(pair
["thread-a"]), str(pair
["thread-b"]))
1268 if numa_node
.get("num-threads"):
1269 numa
["threads"] = int(numa_node
["num-threads"])
1271 if numa_node
.get("memory-mb"):
1272 numa
["memory"] = max(int(numa_node
["memory-mb"] / 1024), 1)
1273 if vdu
["guest-epa"].get("mempage-size"):
1274 if vdu
["guest-epa"]["mempage-size"] != "SMALL":
1275 numa
["memory"] = max(int(db_flavor
["ram"] / 1024), 1)
1276 if vdu
["guest-epa"].get("cpu-pinning-policy") and not epa_vcpu_set
:
1277 if vdu
["guest-epa"]["cpu-pinning-policy"] == "DEDICATED":
1278 if vdu
["guest-epa"].get("cpu-thread-pinning-policy") and \
1279 vdu
["guest-epa"]["cpu-thread-pinning-policy"] != "PREFER":
1280 numa
["cores"] = max(db_flavor
["vcpus"], 1)
1282 numa
["threads"] = max(db_flavor
["vcpus"], 1)
1284 if vdu
["guest-epa"].get("cpu-quota") and not epa_vcpu_set
:
1285 extended
["cpu-quota"] = get_resource_allocation_params(vdu
["guest-epa"].get("cpu-quota"))
1286 if vdu
["guest-epa"].get("mem-quota"):
1287 extended
["mem-quota"] = get_resource_allocation_params(vdu
["guest-epa"].get("mem-quota"))
1288 if vdu
["guest-epa"].get("disk-io-quota"):
1289 extended
["disk-io-quota"] = get_resource_allocation_params(vdu
["guest-epa"].get("disk-io-quota"))
1290 if vdu
["guest-epa"].get("vif-quota"):
1291 extended
["vif-quota"] = get_resource_allocation_params(vdu
["guest-epa"].get("vif-quota"))
1293 extended
["numas"] = [numa
]
1295 extended_text
= yaml
.safe_dump(extended
, default_flow_style
=True, width
=256)
1296 db_flavor
["extended"] = extended_text
1297 # look if flavor exist
1298 temp_flavor_dict
= {'disk': db_flavor
.get('disk', 0),
1299 'ram': db_flavor
.get('ram'),
1300 'vcpus': db_flavor
.get('vcpus'),
1301 'extended': db_flavor
.get('extended')
1303 existing_flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
1304 if existing_flavors
:
1305 flavor_uuid
= existing_flavors
[0]["uuid"]
1307 flavor_uuid
= str(uuid4())
1308 uuid_list
.append(flavor_uuid
)
1309 db_flavor
["uuid"] = flavor_uuid
1310 db_flavors
.append(db_flavor
)
1311 db_vm
["flavor_id"] = flavor_uuid
1313 # VNF affinity and antiaffinity
1314 for pg
in vnfd
.get("placement-groups").itervalues():
1315 pg_name
= get_str(pg
, "name", 255)
1316 for vdu
in pg
.get("member-vdus").itervalues():
1317 vdu_id
= get_str(vdu
, "member-vdu-ref", 255)
1318 if vdu_id
not in vdu_id2db_table_index
:
1319 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'placement-groups[{pg}]':"
1320 "'member-vdus':'{vdu}'. Reference to a non-existing vdu".format(
1321 vnf
=vnfd_id
, pg
=pg_name
, vdu
=vdu_id
),
1322 httperrors
.Bad_Request
)
1323 db_vms
[vdu_id2db_table_index
[vdu_id
]]["availability_zone"] = pg_name
1324 # TODO consider the case of isolation and not colocation
1325 # if pg.get("strategy") == "ISOLATION":
1327 # VNF mgmt configuration
1329 if vnfd
["mgmt-interface"].get("vdu-id"):
1330 mgmt_vdu_id
= get_str(vnfd
["mgmt-interface"], "vdu-id", 255)
1331 if mgmt_vdu_id
not in vdu_id2uuid
:
1332 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'vdu-id':"
1333 "'{vdu}'. Reference to a non-existing vdu".format(
1334 vnf
=vnfd_id
, vdu
=mgmt_vdu_id
),
1335 httperrors
.Bad_Request
)
1336 mgmt_access
["vm_id"] = vdu_id2uuid
[vnfd
["mgmt-interface"]["vdu-id"]]
1337 # if only one cp is defined by this VDU, mark this interface as of type "mgmt"
1338 if vdu_id2cp_name
.get(mgmt_vdu_id
):
1339 if cp_name2db_interface
[vdu_id2cp_name
[mgmt_vdu_id
]]:
1340 cp_name2db_interface
[vdu_id2cp_name
[mgmt_vdu_id
]]["type"] = "mgmt"
1342 if vnfd
["mgmt-interface"].get("ip-address"):
1343 mgmt_access
["ip-address"] = str(vnfd
["mgmt-interface"].get("ip-address"))
1344 if vnfd
["mgmt-interface"].get("cp"):
1345 if vnfd
["mgmt-interface"]["cp"] not in cp_name2iface_uuid
:
1346 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'cp'['{cp}']. "
1347 "Reference to a non-existing connection-point".format(
1348 vnf
=vnfd_id
, cp
=vnfd
["mgmt-interface"]["cp"]),
1349 httperrors
.Bad_Request
)
1350 mgmt_access
["vm_id"] = cp_name2vm_uuid
[vnfd
["mgmt-interface"]["cp"]]
1351 mgmt_access
["interface_id"] = cp_name2iface_uuid
[vnfd
["mgmt-interface"]["cp"]]
1352 # mark this interface as of type mgmt
1353 if cp_name2db_interface
[vnfd
["mgmt-interface"]["cp"]]:
1354 cp_name2db_interface
[vnfd
["mgmt-interface"]["cp"]]["type"] = "mgmt"
1356 default_user
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1360 mgmt_access
["default_user"] = default_user
1361 required
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1364 mgmt_access
["required"] = required
1367 db_vnf
["mgmt_access"] = yaml
.safe_dump(mgmt_access
, default_flow_style
=True, width
=256)
1369 db_vnfs
.append(db_vnf
)
1373 {"images": db_images
},
1374 {"flavors": db_flavors
},
1375 {"ip_profiles": db_ip_profiles
},
1377 {"interfaces": db_interfaces
},
1380 logger
.debug("create_vnf Deployment done vnfDict: %s",
1381 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
1382 mydb
.new_rows(db_tables
, uuid_list
)
1383 return vnfd_uuid_list
1384 except NfvoException
:
1386 except Exception as e
:
1387 logger
.error("Exception {}".format(e
))
1388 raise # NfvoException("Exception {}".format(e), httperrors.Bad_Request)
1391 @deprecated("Use new_vnfd_v3")
1392 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
1393 global global_config
1395 # Step 1. Check the VNF descriptor
1396 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
1397 # Step 2. Check tenant exist
1399 if tenant_id
!= "any":
1400 check_tenant(mydb
, tenant_id
)
1401 if "tenant_id" in vnf_descriptor
["vnf"]:
1402 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1403 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1404 httperrors
.Unauthorized
)
1406 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1407 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1408 if global_config
["auto_push_VNF_to_VIMs"]:
1409 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1411 # Step 4. Review the descriptor and add missing fields
1412 #print vnf_descriptor
1413 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1414 vnf_name
= vnf_descriptor
['vnf']['name']
1415 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1416 if "physical" in vnf_descriptor
['vnf']:
1417 del vnf_descriptor
['vnf']['physical']
1418 #print vnf_descriptor
1420 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1421 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1422 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1424 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1425 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1426 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1428 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1429 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1431 VNFCitem
["name"] = vnfc
['name']
1432 VNFCitem
["availability_zone"] = vnfc
.get('availability_zone')
1433 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
1435 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1438 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1439 myflavorDict
["description"] = VNFCitem
["description"]
1440 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1441 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1442 myflavorDict
["disk"] = vnfc
.get("disk", 0)
1443 myflavorDict
["extended"] = {}
1445 devices
= vnfc
.get("devices")
1447 myflavorDict
["extended"]["devices"] = devices
1450 # 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
1451 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1453 # Previous code has been commented
1454 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1455 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1456 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1457 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1459 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1461 # print "Error creating flavor: unknown processor model. Rollback successful."
1462 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1464 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1465 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1467 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1468 myflavorDict
['extended']['numas'] = vnfc
['numas']
1472 # Step 6.2 New flavors are created in the VIM
1473 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1475 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1476 VNFCitem
["flavor_id"] = flavor_id
1477 VNFCDict
[vnfc
['name']] = VNFCitem
1479 logger
.debug("Creating new images in the VIM for each VNFC")
1480 # Step 6.3 New images are created in the VIM
1481 #For each VNFC, we must create the appropriate image.
1482 #This "for" loop might be integrated with the previous one
1483 #In case this integration is made, the VNFCDict might become a VNFClist.
1484 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1485 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1487 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1488 image_dict
['universal_name']=vnfc
.get('image name')
1489 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1490 image_dict
['location']=vnfc
.get('VNFC image')
1491 #image_dict['new_location']=vnfc.get('image location')
1492 image_dict
['checksum']=vnfc
.get('image checksum')
1493 image_metadata_dict
= vnfc
.get('image metadata', None)
1494 image_metadata_str
= None
1495 if image_metadata_dict
is not None:
1496 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1497 image_dict
['metadata']=image_metadata_str
1498 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1499 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1500 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1501 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1502 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1503 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1504 if vnfc
.get("boot-data"):
1505 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1508 # Step 7. Storing the VNF descriptor in the repository
1509 if "descriptor" not in vnf_descriptor
["vnf"]:
1510 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1512 # Step 8. Adding the VNF to the NFVO DB
1513 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1515 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1516 _
, message
= rollback(mydb
, vims
, rollback_list
)
1517 if isinstance(e
, db_base_Exception
):
1518 error_text
= "Exception at database"
1519 elif isinstance(e
, KeyError):
1520 error_text
= "KeyError exception "
1521 e
.http_code
= httperrors
.Internal_Server_Error
1523 error_text
= "Exception at VIM"
1524 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1525 #logger.error("start_scenario %s", error_text)
1526 raise NfvoException(error_text
, e
.http_code
)
1529 @deprecated("Use new_vnfd_v3")
1530 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
1531 global global_config
1533 # Step 1. Check the VNF descriptor
1534 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
1535 # Step 2. Check tenant exist
1537 if tenant_id
!= "any":
1538 check_tenant(mydb
, tenant_id
)
1539 if "tenant_id" in vnf_descriptor
["vnf"]:
1540 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1541 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1542 httperrors
.Unauthorized
)
1544 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1545 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1546 if global_config
["auto_push_VNF_to_VIMs"]:
1547 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1549 # Step 4. Review the descriptor and add missing fields
1550 #print vnf_descriptor
1551 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1552 vnf_name
= vnf_descriptor
['vnf']['name']
1553 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1554 if "physical" in vnf_descriptor
['vnf']:
1555 del vnf_descriptor
['vnf']['physical']
1556 #print vnf_descriptor
1558 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1559 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1560 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1562 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1563 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1564 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1566 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1567 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1569 VNFCitem
["name"] = vnfc
['name']
1570 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
1572 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1575 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1576 myflavorDict
["description"] = VNFCitem
["description"]
1577 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1578 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1579 myflavorDict
["disk"] = vnfc
.get("disk", 0)
1580 myflavorDict
["extended"] = {}
1582 devices
= vnfc
.get("devices")
1584 myflavorDict
["extended"]["devices"] = devices
1587 # 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
1588 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1590 # Previous code has been commented
1591 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1592 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1593 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1594 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1596 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1598 # print "Error creating flavor: unknown processor model. Rollback successful."
1599 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1601 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1602 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1604 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1605 myflavorDict
['extended']['numas'] = vnfc
['numas']
1609 # Step 6.2 New flavors are created in the VIM
1610 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1612 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1613 VNFCitem
["flavor_id"] = flavor_id
1614 VNFCDict
[vnfc
['name']] = VNFCitem
1616 logger
.debug("Creating new images in the VIM for each VNFC")
1617 # Step 6.3 New images are created in the VIM
1618 #For each VNFC, we must create the appropriate image.
1619 #This "for" loop might be integrated with the previous one
1620 #In case this integration is made, the VNFCDict might become a VNFClist.
1621 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1622 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1624 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1625 image_dict
['universal_name']=vnfc
.get('image name')
1626 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1627 image_dict
['location']=vnfc
.get('VNFC image')
1628 #image_dict['new_location']=vnfc.get('image location')
1629 image_dict
['checksum']=vnfc
.get('image checksum')
1630 image_metadata_dict
= vnfc
.get('image metadata', None)
1631 image_metadata_str
= None
1632 if image_metadata_dict
is not None:
1633 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1634 image_dict
['metadata']=image_metadata_str
1635 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1636 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1637 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1638 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1639 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1640 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1641 if vnfc
.get("boot-data"):
1642 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1644 # Step 7. Storing the VNF descriptor in the repository
1645 if "descriptor" not in vnf_descriptor
["vnf"]:
1646 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1648 # Step 8. Adding the VNF to the NFVO DB
1649 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1651 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1652 _
, message
= rollback(mydb
, vims
, rollback_list
)
1653 if isinstance(e
, db_base_Exception
):
1654 error_text
= "Exception at database"
1655 elif isinstance(e
, KeyError):
1656 error_text
= "KeyError exception "
1657 e
.http_code
= httperrors
.Internal_Server_Error
1659 error_text
= "Exception at VIM"
1660 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1661 #logger.error("start_scenario %s", error_text)
1662 raise NfvoException(error_text
, e
.http_code
)
1665 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
1666 #check valid tenant_id
1667 check_tenant(mydb
, tenant_id
)
1670 if tenant_id
!= "any":
1671 where_or
["tenant_id"] = tenant_id
1672 where_or
["public"] = True
1673 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1675 vnf_id
= vnf
["uuid"]
1676 filter_keys
= ('uuid', 'name', 'description', 'public', "tenant_id", "osm_id", "created_at")
1677 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
1678 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
1679 data
={'vnf' : filtered_content
}
1681 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
1682 SELECT
=('vms.uuid as uuid', 'vms.osm_id as osm_id', 'vms.name as name', 'vms.description as description',
1684 WHERE
={'vnfs.uuid': vnf_id
} )
1685 if len(content
) != 0:
1686 #raise NfvoException("vnf '{}' not found".format(vnf_id), httperrors.Not_Found)
1687 # change boot_data into boot-data
1689 if vm
.get("boot_data"):
1690 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
1693 data
['vnf']['VNFC'] = content
1694 #TODO: GET all the information from a VNFC and include it in the output.
1697 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
1698 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
1699 WHERE
={'vnfs.uuid': vnf_id
} )
1700 data
['vnf']['nets'] = content
1702 #GET ip-profile for each net
1703 for net
in data
['vnf']['nets']:
1704 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1705 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1706 WHERE
={'net_id': net
["uuid"]} )
1707 if len(ipprofiles
)==1:
1708 net
["ip_profile"] = ipprofiles
[0]
1709 elif len(ipprofiles
)>1:
1710 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), httperrors
.Bad_Request
)
1713 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1715 #GET External Interfaces
1716 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1717 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1718 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1719 WHERE
={'vnfs.uuid': vnf_id
, 'interfaces.external_name<>': None} )
1721 data
['vnf']['external-connections'] = content
1726 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1727 # Check tenant exist
1728 if tenant_id
!= "any":
1729 check_tenant(mydb
, tenant_id
)
1730 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1731 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1735 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1737 if tenant_id
!= "any":
1738 where_or
["tenant_id"] = tenant_id
1739 where_or
["public"] = True
1740 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1741 vnf_id
= vnf
["uuid"]
1743 # "Getting the list of flavors and tenants of the VNF"
1744 flavorList
= get_flavorlist(mydb
, vnf_id
)
1745 if len(flavorList
)==0:
1746 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1748 imageList
= get_imagelist(mydb
, vnf_id
)
1749 if len(imageList
)==0:
1750 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1752 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1754 raise NfvoException("vnf '{}' not found".format(vnf_id
), httperrors
.Not_Found
)
1757 for flavor
in flavorList
:
1758 #check if flavor is used by other vnf
1760 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1762 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1764 #flavor not used, must be deleted
1766 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id': flavor
})
1767 for flavor_vim
in c
:
1768 if not flavor_vim
['created']: # skip this flavor because not created by openmano
1772 for vim
in vims
.values():
1773 if vim
["config"]["datacenter_tenant_id"] == flavor_vim
["datacenter_vim_id"]:
1779 myvim
.delete_flavor(flavor_vim
["vim_id"])
1780 except vimconn
.vimconnNotFoundException
:
1781 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"],
1782 flavor_vim
["datacenter_vim_id"] )
1783 except vimconn
.vimconnException
as e
:
1784 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1785 flavor_vim
["vim_id"], flavor_vim
["datacenter_vim_id"], type(e
).__name
__, str(e
))
1786 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"],
1787 flavor_vim
["datacenter_vim_id"]))
1788 # delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1789 mydb
.delete_row_by_id('flavors', flavor
)
1790 except db_base_Exception
as e
:
1791 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1792 undeletedItems
.append("flavor {}".format(flavor
))
1795 for image
in imageList
:
1797 #check if image is used by other vnf
1798 c
= mydb
.get_rows(FROM
='vms', WHERE
=[{'image_id': image
}, {'image_list LIKE ': '%' + image
+ '%'}])
1800 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1802 #image not used, must be deleted
1804 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1806 if image_vim
["datacenter_vim_id"] not in vims
: # TODO change to datacenter_tenant_id
1808 if image_vim
['created']=='false': #skip this image because not created by openmano
1810 myvim
=vims
[ image_vim
["datacenter_id"] ]
1812 myvim
.delete_image(image_vim
["vim_id"])
1813 except vimconn
.vimconnNotFoundException
as e
:
1814 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1815 except vimconn
.vimconnException
as e
:
1816 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1817 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1818 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1819 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1820 mydb
.delete_row_by_id('images', image
)
1821 except db_base_Exception
as e
:
1822 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1823 undeletedItems
.append("image %s" % image
)
1825 return vnf_id
+ " " + vnf
["name"]
1827 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1830 @deprecated("Not used")
1831 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1832 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1836 return -httperrors
.Not_Found
, "datacenter '%s' not found" % datacenter_name
1837 myvim
= vims
.values()[0]
1838 result
,servers
= myvim
.get_hosts_info()
1840 return result
, servers
1841 topology
= {'name':myvim
['name'] , 'servers': servers
}
1842 return result
, topology
1845 def get_hosts(mydb
, nfvo_tenant_id
):
1846 vims
= get_vim(mydb
, nfvo_tenant_id
)
1848 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), httperrors
.Not_Found
)
1850 #print "nfvo.datacenter_action() error. Several datacenters found"
1851 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
1852 myvim
= vims
.values()[0]
1854 hosts
= myvim
.get_hosts()
1855 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1857 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1859 server
={'name':host
['name'], 'vms':[]}
1860 for vm
in host
['instances']:
1861 #get internal name and model
1863 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1864 WHERE
={'vim_vm_id':vm
['id']} )
1866 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1868 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1870 except db_base_Exception
as e
:
1871 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1872 datacenter
['Datacenters'][0]['servers'].append(server
)
1873 #return -400, "en construccion"
1875 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1877 except vimconn
.vimconnException
as e
:
1878 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1881 @deprecated("Use new_nsd_v3")
1882 def new_scenario(mydb
, tenant_id
, topo
):
1884 # result, vims = get_vim(mydb, tenant_id)
1886 # return result, vims
1888 if tenant_id
!= "any":
1889 check_tenant(mydb
, tenant_id
)
1890 if "tenant_id" in topo
:
1891 if topo
["tenant_id"] != tenant_id
:
1892 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1893 httperrors
.Unauthorized
)
1897 #1.1: get VNFs and external_networks (other_nets).
1899 other_nets
={} #external_networks, bridge_networks and data_networkds
1900 nodes
= topo
['topology']['nodes']
1901 for k
in nodes
.keys():
1902 if nodes
[k
]['type'] == 'VNF':
1904 vnfs
[k
]['ifaces'] = {}
1905 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1906 other_nets
[k
] = nodes
[k
]
1907 other_nets
[k
]['external']=True
1908 elif nodes
[k
]['type'] == 'network':
1909 other_nets
[k
] = nodes
[k
]
1910 other_nets
[k
]['external']=False
1913 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1914 for name
,vnf
in vnfs
.items():
1915 where
= {"OR": {"tenant_id": tenant_id
, 'public': "true"}}
1917 error_pos
= "'topology':'nodes':'" + name
+ "'"
1919 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1920 where
['uuid'] = vnf
['vnf_id']
1921 if 'VNF model' in vnf
:
1922 error_text
+= " 'VNF model' " + vnf
['VNF model']
1923 where
['name'] = vnf
['VNF model']
1925 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, httperrors
.Bad_Request
)
1927 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1931 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, httperrors
.Not_Found
)
1933 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", httperrors
.Conflict
)
1934 vnf
['uuid']=vnf_db
[0]['uuid']
1935 vnf
['description']=vnf_db
[0]['description']
1936 #get external interfaces
1937 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1938 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1939 WHERE
={'vnfs.uuid':vnf
['uuid'], 'external_name<>': None} )
1940 for ext_iface
in ext_ifaces
:
1941 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1943 #1.4 get list of connections
1944 conections
= topo
['topology']['connections']
1945 conections_list
= []
1946 conections_list_name
= []
1947 for k
in conections
.keys():
1948 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1949 ifaces_list
= conections
[k
]['nodes'].items()
1950 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1952 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1953 for k2
in conection_pair_list
:
1956 con_type
= conections
[k
].get("type", "link")
1957 if con_type
!= "link":
1959 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), httperrors
.Bad_Request
)
1960 other_nets
[k
] = {'external': False}
1961 if conections
[k
].get("graph"):
1962 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1963 ifaces_list
.append( (k
, None) )
1966 if con_type
== "external_network":
1967 other_nets
[k
]['external'] = True
1968 if conections
[k
].get("model"):
1969 other_nets
[k
]["model"] = conections
[k
]["model"]
1971 other_nets
[k
]["model"] = k
1972 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1973 other_nets
[k
]["model"] = con_type
1975 conections_list_name
.append(k
)
1976 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)
1977 #print set(ifaces_list)
1978 #check valid VNF and iface names
1979 for iface
in ifaces_list
:
1980 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1981 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1982 str(k
), iface
[0]), httperrors
.Not_Found
)
1983 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1984 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1985 str(k
), iface
[0], iface
[1]), httperrors
.Not_Found
)
1987 #1.5 unify connections from the pair list to a consolidated list
1989 while index
< len(conections_list
):
1991 while index2
< len(conections_list
):
1992 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1993 conections_list
[index
] |
= conections_list
[index2
]
1994 del conections_list
[index2
]
1995 del conections_list_name
[index2
]
1998 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
2000 #for k in conections_list:
2005 #1.6 Delete non external nets
2006 # for k in other_nets.keys():
2007 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
2008 # for con in conections_list:
2010 # for index in range(0,len(con)):
2011 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
2012 # for index in delete_indexes:
2015 #1.7: Check external_ports are present at database table datacenter_nets
2016 for k
,net
in other_nets
.items():
2017 error_pos
= "'topology':'nodes':'" + k
+ "'"
2018 if net
['external']==False:
2019 if 'name' not in net
:
2021 if 'model' not in net
:
2022 raise NfvoException("needed a 'model' at " + error_pos
, httperrors
.Bad_Request
)
2023 if net
['model']=='bridge_net':
2024 net
['type']='bridge';
2025 elif net
['model']=='dataplane_net':
2028 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, httperrors
.Not_Found
)
2030 #IF we do not want to check that external network exist at datacenter
2035 # if 'net_id' in net:
2036 # error_text += " 'net_id' " + net['net_id']
2037 # WHERE_['uuid'] = net['net_id']
2038 # if 'model' in net:
2039 # error_text += " 'model' " + net['model']
2040 # WHERE_['name'] = net['model']
2041 # if len(WHERE_) == 0:
2042 # return -httperrors.Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
2043 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
2044 # FROM='datacenter_nets', WHERE=WHERE_ )
2046 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
2048 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
2049 # return -httperrors.Bad_Request, "unknown " +error_text+ " at " + error_pos
2051 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
2052 # return -httperrors.Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
2053 # other_nets[k].update(net_db[0])
2056 net_nb
=0 #Number of nets
2057 for con
in conections_list
:
2058 #check if this is connected to a external net
2062 for index
in range(0,len(con
)):
2063 #check if this is connected to a external net
2064 for net_key
in other_nets
.keys():
2065 if con
[index
][0]==net_key
:
2066 if other_net_index
>=0:
2067 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
2068 #print "nfvo.new_scenario " + error_text
2069 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2071 other_net_index
= index
2072 net_target
= net_key
2074 #print "other_net_index", other_net_index
2076 if other_net_index
>=0:
2077 del con
[other_net_index
]
2078 #IF we do not want to check that external network exist at datacenter
2079 if other_nets
[net_target
]['external'] :
2080 if "name" not in other_nets
[net_target
]:
2081 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
2082 if other_nets
[net_target
]["type"] == "external_network":
2083 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
2084 other_nets
[net_target
]["type"] = "data"
2086 other_nets
[net_target
]["type"] = "bridge"
2088 # if other_nets[net_target]['external'] :
2089 # 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
2090 # if type_=='data' and other_nets[net_target]['type']=="ptp":
2091 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
2092 # print "nfvo.new_scenario " + error_text
2093 # return -httperrors.Bad_Request, error_text
2096 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
2099 net_type_bridge
=False
2101 net_target
= "__-__net"+str(net_nb
)
2102 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
2103 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
2106 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
2107 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
2108 if iface_type
=='mgmt' or iface_type
=='bridge':
2109 net_type_bridge
= True
2111 net_type_data
= True
2112 if net_type_bridge
and net_type_data
:
2113 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
2114 #print "nfvo.new_scenario " + error_text
2115 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2116 elif net_type_bridge
:
2119 type_
='data' if len(con
)>2 else 'ptp'
2120 net_list
[net_target
]['type'] = type_
2123 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
2124 #print "nfvo.new_scenario " + error_text
2126 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2128 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
2129 #1.8.1 obtain management net
2130 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
2131 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
2132 #1.8.2 check all interfaces from all vnfs
2134 add_mgmt_net
= False
2135 for vnf
in vnfs
.values():
2136 for iface
in vnf
['ifaces'].values():
2137 if iface
['type']=='mgmt' and 'net_key' not in iface
:
2138 #iface not connected
2139 iface
['net_key'] = 'mgmt'
2141 if add_mgmt_net
and 'mgmt' not in net_list
:
2142 net_list
['mgmt']=mgmt_net
[0]
2143 net_list
['mgmt']['external']=True
2144 net_list
['mgmt']['graph']={'visible':False}
2146 net_list
.update(other_nets
)
2148 #print 'net_list', net_list
2153 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
2154 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
2155 'tenant_id':tenant_id
, 'name':topo
['name'],
2156 'description':topo
.get('description',topo
['name']),
2157 'public': topo
.get('public', False)
2163 @deprecated("Use new_nsd_v3")
2164 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
2165 """ This creates a new scenario for version 0.2 and 0.3"""
2166 scenario
= scenario_dict
["scenario"]
2167 if tenant_id
!= "any":
2168 check_tenant(mydb
, tenant_id
)
2169 if "tenant_id" in scenario
:
2170 if scenario
["tenant_id"] != tenant_id
:
2171 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
2172 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
2173 scenario
["tenant_id"], tenant_id
), httperrors
.Unauthorized
)
2177 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
2178 for name
,vnf
in scenario
["vnfs"].iteritems():
2179 where
= {"OR": {"tenant_id": tenant_id
, 'public': "true"}}
2181 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
2183 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
2184 where
['uuid'] = vnf
['vnf_id']
2185 if 'vnf_name' in vnf
:
2186 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
2187 where
['name'] = vnf
['vnf_name']
2189 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, httperrors
.Bad_Request
)
2190 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
2193 if len(vnf_db
) == 0:
2194 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, httperrors
.Not_Found
)
2195 elif len(vnf_db
) > 1:
2196 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", httperrors
.Conflict
)
2197 vnf
['uuid'] = vnf_db
[0]['uuid']
2198 vnf
['description'] = vnf_db
[0]['description']
2200 # get external interfaces
2201 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
2202 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
2203 WHERE
={'vnfs.uuid':vnf
['uuid'], 'external_name<>': None} )
2204 for ext_iface
in ext_ifaces
:
2205 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
2206 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
2208 # 2: Insert net_key and ip_address at every vnf interface
2209 for net_name
, net
in scenario
["networks"].items():
2210 net_type_bridge
= False
2211 net_type_data
= False
2212 for iface_dict
in net
["interfaces"]:
2213 if version
== "0.2":
2214 temp_dict
= iface_dict
2216 elif version
== "0.3":
2217 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
2218 ip_address
= iface_dict
.get('ip_address', None)
2219 for vnf
, iface
in temp_dict
.items():
2220 if vnf
not in scenario
["vnfs"]:
2221 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
2223 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2224 raise NfvoException(error_text
, httperrors
.Not_Found
)
2225 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
2226 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
2227 .format(net_name
, iface
)
2228 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2229 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2230 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
2231 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
2232 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
2233 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2234 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2235 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
2236 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
2237 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
2238 if iface_type
== 'mgmt' or iface_type
== 'bridge':
2239 net_type_bridge
= True
2241 net_type_data
= True
2243 if net_type_bridge
and net_type_data
:
2244 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
2246 # logger.debug("nfvo.new_scenario " + error_text)
2247 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2248 elif net_type_bridge
:
2251 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
2253 if net
.get("implementation"): # for v0.3
2254 if type_
== "bridge" and net
["implementation"] == "underlay":
2255 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
2256 "'network':'{}'".format(net_name
)
2257 # logger.debug(error_text)
2258 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2259 elif type_
!= "bridge" and net
["implementation"] == "overlay":
2260 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
2261 "'network':'{}'".format(net_name
)
2262 # logger.debug(error_text)
2263 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2264 net
.pop("implementation")
2265 if "type" in net
and version
== "0.3": # for v0.3
2266 if type_
== "data" and net
["type"] == "e-line":
2267 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
2268 "'e-line' at 'network':'{}'".format(net_name
)
2269 # logger.debug(error_text)
2270 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2271 elif type_
== "ptp" and net
["type"] == "e-lan":
2275 net
['name'] = net_name
2276 net
['external'] = net
.get('external', False)
2278 # 3: insert at database
2279 scenario
["nets"] = scenario
["networks"]
2280 scenario
['tenant_id'] = tenant_id
2281 scenario_id
= mydb
.new_scenario(scenario
)
2285 def new_nsd_v3(mydb
, tenant_id
, nsd_descriptor
):
2287 Parses an OSM IM nsd_catalog and insert at DB
2290 :param nsd_descriptor:
2291 :return: The list of created NSD ids
2294 mynsd
= nsd_catalog
.nsd()
2296 pybindJSONDecoder
.load_ietf_json(nsd_descriptor
, None, None, obj
=mynsd
, skip_unknown
=True)
2297 except Exception as e
:
2298 raise NfvoException("Error. Invalid NS descriptor format: " + str(e
), httperrors
.Bad_Request
)
2302 db_sce_interfaces
= []
2305 db_sce_rsp_hops
= []
2306 db_sce_classifiers
= []
2307 db_sce_classifier_matches
= []
2309 db_ip_profiles_index
= 0
2312 for nsd_yang
in mynsd
.nsd_catalog
.nsd
.itervalues():
2313 nsd
= nsd_yang
.get()
2316 scenario_uuid
= str(uuid4())
2317 uuid_list
.append(scenario_uuid
)
2318 nsd_uuid_list
.append(scenario_uuid
)
2320 "uuid": scenario_uuid
,
2321 "osm_id": get_str(nsd
, "id", 255),
2322 "name": get_str(nsd
, "name", 255),
2323 "description": get_str(nsd
, "description", 255),
2324 "tenant_id": tenant_id
,
2325 "vendor": get_str(nsd
, "vendor", 255),
2326 "short_name": get_str(nsd
, "short-name", 255),
2327 "descriptor": str(nsd_descriptor
)[:60000],
2329 db_scenarios
.append(db_scenario
)
2331 # table sce_vnfs (constituent-vnfd)
2332 vnf_index2scevnf_uuid
= {}
2333 vnf_index2vnf_uuid
= {}
2334 for vnf
in nsd
.get("constituent-vnfd").itervalues():
2335 existing_vnf
= mydb
.get_rows(FROM
="vnfs", WHERE
={'osm_id': str(vnf
["vnfd-id-ref"])[:255],
2336 'tenant_id': tenant_id
})
2337 if not existing_vnf
:
2338 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'constituent-vnfd':'vnfd-id-ref':"
2339 "'{}'. Reference to a non-existing VNFD in the catalog".format(
2340 str(nsd
["id"]), str(vnf
["vnfd-id-ref"])[:255]),
2341 httperrors
.Bad_Request
)
2342 sce_vnf_uuid
= str(uuid4())
2343 uuid_list
.append(sce_vnf_uuid
)
2345 "uuid": sce_vnf_uuid
,
2346 "scenario_id": scenario_uuid
,
2347 # "name": get_str(vnf, "member-vnf-index", 255),
2348 "name": existing_vnf
[0]["name"][:200] + "." + get_str(vnf
, "member-vnf-index", 50),
2349 "vnf_id": existing_vnf
[0]["uuid"],
2350 "member_vnf_index": str(vnf
["member-vnf-index"]),
2351 # TODO 'start-by-default': True
2353 vnf_index2scevnf_uuid
[str(vnf
['member-vnf-index'])] = sce_vnf_uuid
2354 vnf_index2vnf_uuid
[str(vnf
['member-vnf-index'])] = existing_vnf
[0]["uuid"]
2355 db_sce_vnfs
.append(db_sce_vnf
)
2357 # table ip_profiles (ip-profiles)
2358 ip_profile_name2db_table_index
= {}
2359 for ip_profile
in nsd
.get("ip-profiles").itervalues():
2361 "ip_version": str(ip_profile
["ip-profile-params"].get("ip-version", "ipv4")),
2362 "subnet_address": str(ip_profile
["ip-profile-params"].get("subnet-address")),
2363 "gateway_address": str(ip_profile
["ip-profile-params"].get("gateway-address")),
2364 "dhcp_enabled": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("enabled", True)),
2365 "dhcp_start_address": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("start-address")),
2366 "dhcp_count": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("count")),
2369 for dns
in ip_profile
["ip-profile-params"]["dns-server"].itervalues():
2370 dns_list
.append(str(dns
.get("address")))
2371 db_ip_profile
["dns_address"] = ";".join(dns_list
)
2372 if ip_profile
["ip-profile-params"].get('security-group'):
2373 db_ip_profile
["security_group"] = ip_profile
["ip-profile-params"]['security-group']
2374 ip_profile_name2db_table_index
[str(ip_profile
["name"])] = db_ip_profiles_index
2375 db_ip_profiles_index
+= 1
2376 db_ip_profiles
.append(db_ip_profile
)
2378 # table sce_nets (internal-vld)
2379 for vld
in nsd
.get("vld").itervalues():
2380 sce_net_uuid
= str(uuid4())
2381 uuid_list
.append(sce_net_uuid
)
2383 "uuid": sce_net_uuid
,
2384 "name": get_str(vld
, "name", 255),
2385 "scenario_id": scenario_uuid
,
2387 "multipoint": not vld
.get("type") == "ELINE",
2388 "osm_id": get_str(vld
, "id", 255),
2390 "description": get_str(vld
, "description", 255),
2392 # guess type of network
2393 if vld
.get("mgmt-network"):
2394 db_sce_net
["type"] = "bridge"
2395 db_sce_net
["external"] = True
2396 elif vld
.get("provider-network").get("overlay-type") == "VLAN":
2397 db_sce_net
["type"] = "data"
2399 # later on it will be fixed to bridge or data depending on the type of interfaces attached to it
2400 db_sce_net
["type"] = None
2401 db_sce_nets
.append(db_sce_net
)
2403 # ip-profile, link db_ip_profile with db_sce_net
2404 if vld
.get("ip-profile-ref"):
2405 ip_profile_name
= vld
.get("ip-profile-ref")
2406 if ip_profile_name
not in ip_profile_name2db_table_index
:
2407 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'ip-profile-ref':'{}'."
2408 " Reference to a non-existing 'ip_profiles'".format(
2409 str(nsd
["id"]), str(vld
["id"]), str(vld
["ip-profile-ref"])),
2410 httperrors
.Bad_Request
)
2411 db_ip_profiles
[ip_profile_name2db_table_index
[ip_profile_name
]]["sce_net_id"] = sce_net_uuid
2412 elif vld
.get("vim-network-name"):
2413 db_sce_net
["vim_network_name"] = get_str(vld
, "vim-network-name", 255)
2415 # table sce_interfaces (vld:vnfd-connection-point-ref)
2416 for iface
in vld
.get("vnfd-connection-point-ref").itervalues():
2417 vnf_index
= str(iface
['member-vnf-index-ref'])
2418 # check correct parameters
2419 if vnf_index
not in vnf_index2vnf_uuid
:
2420 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2421 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2422 "'nsd':'constituent-vnfd'".format(
2423 str(nsd
["id"]), str(vld
["id"]), str(iface
["member-vnf-index-ref"])),
2424 httperrors
.Bad_Request
)
2426 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid', 'i.type as iface_type'),
2427 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2428 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2429 'external_name': get_str(iface
, "vnfd-connection-point-ref",
2431 if not existing_ifaces
:
2432 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2433 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2434 "connection-point name at VNFD '{}'".format(
2435 str(nsd
["id"]), str(vld
["id"]), str(iface
["vnfd-connection-point-ref"]),
2436 str(iface
.get("vnfd-id-ref"))[:255]),
2437 httperrors
.Bad_Request
)
2438 interface_uuid
= existing_ifaces
[0]["uuid"]
2439 if existing_ifaces
[0]["iface_type"] == "data":
2440 db_sce_net
["type"] = "data"
2441 sce_interface_uuid
= str(uuid4())
2442 uuid_list
.append(sce_net_uuid
)
2443 iface_ip_address
= None
2444 if iface
.get("ip-address"):
2445 iface_ip_address
= str(iface
.get("ip-address"))
2446 db_sce_interface
= {
2447 "uuid": sce_interface_uuid
,
2448 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2449 "sce_net_id": sce_net_uuid
,
2450 "interface_id": interface_uuid
,
2451 "ip_address": iface_ip_address
,
2453 db_sce_interfaces
.append(db_sce_interface
)
2454 if not db_sce_net
["type"]:
2455 db_sce_net
["type"] = "bridge"
2457 # table sce_vnffgs (vnffgd)
2458 for vnffg
in nsd
.get("vnffgd").itervalues():
2459 sce_vnffg_uuid
= str(uuid4())
2460 uuid_list
.append(sce_vnffg_uuid
)
2462 "uuid": sce_vnffg_uuid
,
2463 "name": get_str(vnffg
, "name", 255),
2464 "scenario_id": scenario_uuid
,
2465 "vendor": get_str(vnffg
, "vendor", 255),
2466 "description": get_str(vld
, "description", 255),
2468 db_sce_vnffgs
.append(db_sce_vnffg
)
2471 for rsp
in vnffg
.get("rsp").itervalues():
2472 sce_rsp_uuid
= str(uuid4())
2473 uuid_list
.append(sce_rsp_uuid
)
2475 "uuid": sce_rsp_uuid
,
2476 "name": get_str(rsp
, "name", 255),
2477 "sce_vnffg_id": sce_vnffg_uuid
,
2478 "id": get_str(rsp
, "id", 255), # only useful to link with classifiers; will be removed later in the code
2480 db_sce_rsps
.append(db_sce_rsp
)
2481 for iface
in rsp
.get("vnfd-connection-point-ref").itervalues():
2482 vnf_index
= str(iface
['member-vnf-index-ref'])
2483 if_order
= int(iface
['order'])
2484 # check correct parameters
2485 if vnf_index
not in vnf_index2vnf_uuid
:
2486 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2487 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2488 "'nsd':'constituent-vnfd'".format(
2489 str(nsd
["id"]), str(rsp
["id"]), str(iface
["member-vnf-index-ref"])),
2490 httperrors
.Bad_Request
)
2492 ingress_existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2493 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2495 'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2496 'external_name': get_str(iface
, "vnfd-ingress-connection-point-ref",
2498 if not ingress_existing_ifaces
:
2499 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2500 "-ref':'vnfd-ingress-connection-point-ref':'{}'. Reference to a non-existing "
2501 "connection-point name at VNFD '{}'".format(
2502 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-ingress-connection-point-ref"]),
2503 str(iface
.get("vnfd-id-ref"))[:255]), httperrors
.Bad_Request
)
2505 egress_existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2506 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2508 'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2509 'external_name': get_str(iface
, "vnfd-egress-connection-point-ref",
2511 if not egress_existing_ifaces
:
2512 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2513 "-ref':'vnfd-egress-connection-point-ref':'{}'. Reference to a non-existing "
2514 "connection-point name at VNFD '{}'".format(
2515 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-egress-connection-point-ref"]),
2516 str(iface
.get("vnfd-id-ref"))[:255]), HTTP_Bad_Request
)
2518 ingress_interface_uuid
= ingress_existing_ifaces
[0]["uuid"]
2519 egress_interface_uuid
= egress_existing_ifaces
[0]["uuid"]
2520 sce_rsp_hop_uuid
= str(uuid4())
2521 uuid_list
.append(sce_rsp_hop_uuid
)
2523 "uuid": sce_rsp_hop_uuid
,
2524 "if_order": if_order
,
2525 "ingress_interface_id": ingress_interface_uuid
,
2526 "egress_interface_id": egress_interface_uuid
,
2527 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2528 "sce_rsp_id": sce_rsp_uuid
,
2530 db_sce_rsp_hops
.append(db_sce_rsp_hop
)
2532 # deal with classifiers
2533 for classifier
in vnffg
.get("classifier").itervalues():
2534 sce_classifier_uuid
= str(uuid4())
2535 uuid_list
.append(sce_classifier_uuid
)
2538 vnf_index
= str(classifier
['member-vnf-index-ref'])
2539 if vnf_index
not in vnf_index2vnf_uuid
:
2540 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'classifier[{}]':'vnfd-connection-point"
2541 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2542 "'nsd':'constituent-vnfd'".format(
2543 str(nsd
["id"]), str(classifier
["id"]), str(classifier
["member-vnf-index-ref"])),
2544 httperrors
.Bad_Request
)
2545 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2546 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2547 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2548 'external_name': get_str(classifier
, "vnfd-connection-point-ref",
2550 if not existing_ifaces
:
2551 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2552 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2553 "connection-point name at VNFD '{}'".format(
2554 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-connection-point-ref"]),
2555 str(iface
.get("vnfd-id-ref"))[:255]),
2556 httperrors
.Bad_Request
)
2557 interface_uuid
= existing_ifaces
[0]["uuid"]
2559 db_sce_classifier
= {
2560 "uuid": sce_classifier_uuid
,
2561 "name": get_str(classifier
, "name", 255),
2562 "sce_vnffg_id": sce_vnffg_uuid
,
2563 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2564 "interface_id": interface_uuid
,
2566 rsp_id
= get_str(classifier
, "rsp-id-ref", 255)
2567 rsp
= next((item
for item
in db_sce_rsps
if item
["id"] == rsp_id
), None)
2568 db_sce_classifier
["sce_rsp_id"] = rsp
["uuid"]
2569 db_sce_classifiers
.append(db_sce_classifier
)
2571 for match
in classifier
.get("match-attributes").itervalues():
2572 sce_classifier_match_uuid
= str(uuid4())
2573 uuid_list
.append(sce_classifier_match_uuid
)
2574 db_sce_classifier_match
= {
2575 "uuid": sce_classifier_match_uuid
,
2576 "ip_proto": get_str(match
, "ip-proto", 2),
2577 "source_ip": get_str(match
, "source-ip-address", 16),
2578 "destination_ip": get_str(match
, "destination-ip-address", 16),
2579 "source_port": get_str(match
, "source-port", 5),
2580 "destination_port": get_str(match
, "destination-port", 5),
2581 "sce_classifier_id": sce_classifier_uuid
,
2583 db_sce_classifier_matches
.append(db_sce_classifier_match
)
2586 # remove unneeded id's in sce_rsps
2587 for rsp
in db_sce_rsps
:
2591 {"scenarios": db_scenarios
},
2592 {"sce_nets": db_sce_nets
},
2593 {"ip_profiles": db_ip_profiles
},
2594 {"sce_vnfs": db_sce_vnfs
},
2595 {"sce_interfaces": db_sce_interfaces
},
2596 {"sce_vnffgs": db_sce_vnffgs
},
2597 {"sce_rsps": db_sce_rsps
},
2598 {"sce_rsp_hops": db_sce_rsp_hops
},
2599 {"sce_classifiers": db_sce_classifiers
},
2600 {"sce_classifier_matches": db_sce_classifier_matches
},
2603 logger
.debug("new_nsd_v3 done: %s",
2604 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
2605 mydb
.new_rows(db_tables
, uuid_list
)
2606 return nsd_uuid_list
2607 except NfvoException
:
2609 except Exception as e
:
2610 logger
.error("Exception {}".format(e
))
2611 raise # NfvoException("Exception {}".format(e), httperrors.Bad_Request)
2614 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
2615 data
["uuid"] = scenario_id
2616 data
["tenant_id"] = tenant_id
2617 c
= mydb
.edit_scenario( data
)
2621 @deprecated("Use create_instance")
2622 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
2623 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2624 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
2625 vims
= {datacenter_id
: myvim
}
2626 myvim_tenant
= myvim
['tenant_id']
2627 datacenter_name
= myvim
['name']
2631 #print "Checking that the scenario_id exists and getting the scenario dictionary"
2632 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
=datacenter_id
)
2633 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
2634 scenarioDict
['datacenter_id'] = datacenter_id
2635 #print '================scenarioDict======================='
2636 #print json.dumps(scenarioDict, indent=4)
2637 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
2639 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
2640 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2642 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
2643 auxNetDict
['scenario'] = {}
2645 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
2646 for sce_net
in scenarioDict
['nets']:
2647 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
2649 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
2650 myNetName
= myNetName
[0:255] #limit length
2651 myNetType
= sce_net
['type']
2653 myNetDict
["name"] = myNetName
2654 myNetDict
["type"] = myNetType
2655 myNetDict
["tenant_id"] = myvim_tenant
2656 myNetIPProfile
= sce_net
.get('ip_profile', None)
2658 #We should use the dictionary as input parameter for new_network
2660 if not sce_net
["external"]:
2661 network_id
, _
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2662 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
2663 sce_net
['vim_id'] = network_id
2664 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
2665 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2666 sce_net
["created"] = True
2668 if sce_net
['vim_id'] == None:
2669 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
2670 _
, message
= rollback(mydb
, vims
, rollbackList
)
2671 logger
.error("nfvo.start_scenario: %s", error_text
)
2672 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2673 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
2674 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
2676 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
2677 #For each vnf net, we create it and we add it to instanceNetlist.
2679 for sce_vnf
in scenarioDict
['vnfs']:
2680 for net
in sce_vnf
['nets']:
2681 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
2683 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
2684 myNetName
= myNetName
[0:255] #limit length
2685 myNetType
= net
['type']
2687 myNetDict
["name"] = myNetName
2688 myNetDict
["type"] = myNetType
2689 myNetDict
["tenant_id"] = myvim_tenant
2690 myNetIPProfile
= net
.get('ip_profile', None)
2693 #We should use the dictionary as input parameter for new_network
2694 network_id
, _
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2695 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
2696 net
['vim_id'] = network_id
2697 if sce_vnf
['uuid'] not in auxNetDict
:
2698 auxNetDict
[sce_vnf
['uuid']] = {}
2699 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
2700 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2701 net
["created"] = True
2703 #print "auxNetDict:"
2704 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2706 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
2707 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2709 for sce_vnf
in scenarioDict
['vnfs']:
2710 vnf_availability_zones
= []
2711 for vm
in sce_vnf
['vms']:
2712 vm_av
= vm
.get('availability_zone')
2713 if vm_av
and vm_av
not in vnf_availability_zones
:
2714 vnf_availability_zones
.append(vm_av
)
2716 # check if there is enough availability zones available at vim level.
2717 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
2718 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
2719 raise NfvoException('No enough availability zones at VIM for this deployment', httperrors
.Bad_Request
)
2721 for vm
in sce_vnf
['vms']:
2724 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
2725 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
2726 #myVMDict['description'] = vm['description']
2727 myVMDict
['description'] = myVMDict
['name'][0:99]
2729 myVMDict
['start'] = "no"
2730 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2731 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
2733 #create image at vim in case it not exist
2734 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2735 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
2736 vm
['vim_image_id'] = image_id
2738 #create flavor at vim in case it not exist
2739 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2740 if flavor_dict
['extended']!=None:
2741 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2742 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
2743 vm
['vim_flavor_id'] = flavor_id
2746 myVMDict
['imageRef'] = vm
['vim_image_id']
2747 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2748 myVMDict
['networks'] = []
2749 for iface
in vm
['interfaces']:
2751 if iface
['type']=="data":
2752 netDict
['type'] = iface
['model']
2753 elif "model" in iface
and iface
["model"]!=None:
2754 netDict
['model']=iface
['model']
2755 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2756 #discover type of interface looking at flavor
2757 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2758 for flavor_iface
in numa
.get('interfaces',[]):
2759 if flavor_iface
.get('name') == iface
['internal_name']:
2760 if flavor_iface
['dedicated'] == 'yes':
2761 netDict
['type']="PF" #passthrough
2762 elif flavor_iface
['dedicated'] == 'no':
2763 netDict
['type']="VF" #siov
2764 elif flavor_iface
['dedicated'] == 'yes:sriov':
2765 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2766 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2768 netDict
["use"]=iface
['type']
2769 if netDict
["use"]=="data" and not netDict
.get("type"):
2770 #print "netDict", netDict
2771 #print "iface", iface
2772 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'])
2773 if flavor_dict
.get('extended')==None:
2774 raise NfvoException(e_text
+ "After database migration some information is not available. \
2775 Try to delete and create the scenarios and VNFs again", httperrors
.Conflict
)
2777 raise NfvoException(e_text
, httperrors
.Internal_Server_Error
)
2778 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2779 netDict
["type"]="virtual"
2780 if "vpci" in iface
and iface
["vpci"] is not None:
2781 netDict
['vpci'] = iface
['vpci']
2782 if "mac" in iface
and iface
["mac"] is not None:
2783 netDict
['mac_address'] = iface
['mac']
2784 if "port-security" in iface
and iface
["port-security"] is not None:
2785 netDict
['port_security'] = iface
['port-security']
2786 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2787 netDict
['floating_ip'] = iface
['floating-ip']
2788 netDict
['name'] = iface
['internal_name']
2789 if iface
['net_id'] is None:
2790 for vnf_iface
in sce_vnf
["interfaces"]:
2793 if vnf_iface
['interface_id']==iface
['uuid']:
2794 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
2797 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2798 #skip bridge ifaces not connected to any net
2799 #if 'net_id' not in netDict or netDict['net_id']==None:
2801 myVMDict
['networks'].append(netDict
)
2802 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2803 #print myVMDict['name']
2804 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2805 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2806 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2808 if 'availability_zone' in myVMDict
:
2809 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
2813 vm_id
, _
= myvim
.new_vminstance(myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2814 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2815 availability_zone_index
=av_index
,
2816 availability_zone_list
=vnf_availability_zones
)
2817 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
2818 vm
['vim_id'] = vm_id
2819 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2820 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2821 for net
in myVMDict
['networks']:
2823 for iface
in vm
['interfaces']:
2824 if net
["name"]==iface
["internal_name"]:
2825 iface
["vim_id"]=net
["vim_id"]
2828 logger
.debug("start scenario Deployment done")
2829 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2830 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
2831 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
2832 return mydb
.get_instance_scenario(instance_id
)
2834 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
2835 _
, message
= rollback(mydb
, vims
, rollbackList
)
2836 if isinstance(e
, db_base_Exception
):
2837 error_text
= "Exception at database"
2839 error_text
= "Exception at VIM"
2840 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2841 #logger.error("start_scenario %s", error_text)
2842 raise NfvoException(error_text
, e
.http_code
)
2844 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
2845 """ join the cloud config information into cloud_config_preserve.
2846 In case of conflict cloud_config_preserve preserves
2849 if not cloud_config_preserve
and not cloud_config
:
2852 new_cloud_config
= {"key-pairs":[], "users":[]}
2854 if cloud_config_preserve
:
2855 for key
in cloud_config_preserve
.get("key-pairs", () ):
2856 if key
not in new_cloud_config
["key-pairs"]:
2857 new_cloud_config
["key-pairs"].append(key
)
2859 for key
in cloud_config
.get("key-pairs", () ):
2860 if key
not in new_cloud_config
["key-pairs"]:
2861 new_cloud_config
["key-pairs"].append(key
)
2862 if not new_cloud_config
["key-pairs"]:
2863 del new_cloud_config
["key-pairs"]
2867 new_cloud_config
["users"] += cloud_config
.get("users", () )
2868 if cloud_config_preserve
:
2869 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
2870 index_to_delete
= []
2871 users
= new_cloud_config
.get("users", [])
2872 for index0
in range(0,len(users
)):
2873 if index0
in index_to_delete
:
2875 for index1
in range(index0
+1,len(users
)):
2876 if index1
in index_to_delete
:
2878 if users
[index0
]["name"] == users
[index1
]["name"]:
2879 index_to_delete
.append(index1
)
2880 for key
in users
[index1
].get("key-pairs",()):
2881 if "key-pairs" not in users
[index0
]:
2882 users
[index0
]["key-pairs"] = [key
]
2883 elif key
not in users
[index0
]["key-pairs"]:
2884 users
[index0
]["key-pairs"].append(key
)
2885 index_to_delete
.sort(reverse
=True)
2886 for index
in index_to_delete
:
2888 if not new_cloud_config
["users"]:
2889 del new_cloud_config
["users"]
2892 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
2893 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
2894 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
2895 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
2898 new_cloud_config
["user-data"] = []
2899 if cloud_config
and cloud_config
.get("user-data"):
2900 if isinstance(cloud_config
["user-data"], list):
2901 new_cloud_config
["user-data"] += cloud_config
["user-data"]
2903 new_cloud_config
["user-data"].append(cloud_config
["user-data"])
2904 if cloud_config_preserve
and cloud_config_preserve
.get("user-data"):
2905 if isinstance(cloud_config_preserve
["user-data"], list):
2906 new_cloud_config
["user-data"] += cloud_config_preserve
["user-data"]
2908 new_cloud_config
["user-data"].append(cloud_config_preserve
["user-data"])
2909 if not new_cloud_config
["user-data"]:
2910 del new_cloud_config
["user-data"]
2913 new_cloud_config
["config-files"] = []
2914 if cloud_config
and cloud_config
.get("config-files") != None:
2915 new_cloud_config
["config-files"] += cloud_config
["config-files"]
2916 if cloud_config_preserve
:
2917 for file in cloud_config_preserve
.get("config-files", ()):
2918 for index
in range(0, len(new_cloud_config
["config-files"])):
2919 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
2920 new_cloud_config
["config-files"][index
] = file
2923 new_cloud_config
["config-files"].append(file)
2924 if not new_cloud_config
["config-files"]:
2925 del new_cloud_config
["config-files"]
2926 return new_cloud_config
2929 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
2930 datacenter_id
= None
2931 datacenter_name
= None
2934 if datacenter_tenant_id
:
2935 thread_id
= datacenter_tenant_id
2936 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
2938 where_
={"td.nfvo_tenant_id": tenant_id
}
2939 if datacenter_id_name
:
2940 if utils
.check_valid_uuid(datacenter_id_name
):
2941 datacenter_id
= datacenter_id_name
2942 where_
["dt.datacenter_id"] = datacenter_id
2944 datacenter_name
= datacenter_id_name
2945 where_
["d.name"] = datacenter_name
2946 if datacenter_tenant_id
:
2947 where_
["dt.uuid"] = datacenter_tenant_id
2948 datacenters
= mydb
.get_rows(
2949 SELECT
=("dt.uuid as datacenter_tenant_id",),
2950 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
2951 "join datacenters as d on d.uuid=dt.datacenter_id",
2953 if len(datacenters
) > 1:
2954 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
2956 thread_id
= datacenters
[0]["datacenter_tenant_id"]
2957 thread
= vim_threads
["running"].get(thread_id
)
2959 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
2960 return thread_id
, thread
2961 except db_base_Exception
as e
:
2962 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
2965 def get_datacenter_uuid(mydb
, tenant_id
, datacenter_id_name
):
2967 if utils
.check_valid_uuid(datacenter_id_name
):
2968 WHERE_dict
['d.uuid'] = datacenter_id_name
2970 WHERE_dict
['d.name'] = datacenter_id_name
2973 WHERE_dict
['nfvo_tenant_id'] = tenant_id
2974 from_
= "tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join datacenter_tenants as" \
2975 " dt on td.datacenter_tenant_id=dt.uuid"
2977 from_
= 'datacenters as d'
2978 vimaccounts
= mydb
.get_rows(FROM
=from_
, SELECT
=("d.uuid as uuid, d.name as name",), WHERE
=WHERE_dict
)
2979 if len(vimaccounts
) == 0:
2980 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
2981 elif len(vimaccounts
)>1:
2982 #print "nfvo.datacenter_action() error. Several datacenters found"
2983 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
2984 return vimaccounts
[0]["uuid"], vimaccounts
[0]["name"]
2987 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
2988 datacenter_id
= None
2989 datacenter_name
= None
2990 if datacenter_id_name
:
2991 if utils
.check_valid_uuid(datacenter_id_name
):
2992 datacenter_id
= datacenter_id_name
2994 datacenter_name
= datacenter_id_name
2995 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
2997 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
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 vims
.keys()[0], vims
.values()[0]
3005 """Takes dict d and updates it with the values in dict u.
3006 It merges all depth levels"""
3007 for k
, v
in u
.iteritems():
3008 if isinstance(v
, collections
.Mapping
):
3009 r
= update(d
.get(k
, {}), v
)
3016 def create_instance(mydb
, tenant_id
, instance_dict
):
3017 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
3018 # logger.debug("Creating instance...")
3019 scenario
= instance_dict
["scenario"]
3021 # find main datacenter
3023 myvim_threads_id
= {}
3024 datacenter
= instance_dict
.get("datacenter")
3025 default_wim_account
= instance_dict
.get("wim_account")
3026 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3027 myvims
[default_datacenter_id
] = vim
3028 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
3029 tenant
= mydb
.get_rows_by_id('nfvo_tenants', tenant_id
)
3030 # myvim_tenant = myvim['tenant_id']
3033 # print "Checking that the scenario exists and getting the scenario dictionary"
3034 if isinstance(scenario
, str):
3035 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, datacenter_vim_id
=myvim_threads_id
[default_datacenter_id
],
3036 datacenter_id
=default_datacenter_id
)
3038 scenarioDict
= scenario
3039 scenarioDict
["uuid"] = None
3041 # logger.debug(">>>>>> Dictionaries before merging")
3042 # logger.debug(">>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
3043 # logger.debug(">>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
3045 db_instance_vnfs
= []
3046 db_instance_vms
= []
3047 db_instance_interfaces
= []
3048 db_instance_sfis
= []
3049 db_instance_sfs
= []
3050 db_instance_classifications
= []
3051 db_instance_sfps
= []
3056 instance_name
= instance_dict
["name"]
3057 instance_uuid
= str(uuid4())
3058 uuid_list
.append(instance_uuid
)
3059 db_instance_scenario
= {
3060 "uuid": instance_uuid
,
3061 "name": instance_name
,
3062 "tenant_id": tenant_id
,
3063 "scenario_id": scenarioDict
['uuid'],
3064 "datacenter_id": default_datacenter_id
,
3065 # filled bellow 'datacenter_tenant_id'
3066 "description": instance_dict
.get("description"),
3068 if scenarioDict
.get("cloud-config"):
3069 db_instance_scenario
["cloud_config"] = yaml
.safe_dump(scenarioDict
["cloud-config"],
3070 default_flow_style
=True, width
=256)
3071 instance_action_id
= get_task_id()
3072 db_instance_action
= {
3073 "uuid": instance_action_id
, # same uuid for the instance and the action on create
3074 "tenant_id": tenant_id
,
3075 "instance_id": instance_uuid
,
3076 "description": "CREATE",
3079 # Auxiliary dictionaries from x to y
3080 sce_net2instance
= {}
3081 net2task_id
= {'scenario': {}}
3082 # Mapping between local networks and WIMs
3085 def ip_profile_IM2RO(ip_profile_im
):
3086 # translate from input format to database format
3088 if 'subnet-address' in ip_profile_im
:
3089 ip_profile_ro
['subnet_address'] = ip_profile_im
['subnet-address']
3090 if 'ip-version' in ip_profile_im
:
3091 ip_profile_ro
['ip_version'] = ip_profile_im
['ip-version']
3092 if 'gateway-address' in ip_profile_im
:
3093 ip_profile_ro
['gateway_address'] = ip_profile_im
['gateway-address']
3094 if 'dns-address' in ip_profile_im
:
3095 ip_profile_ro
['dns_address'] = ip_profile_im
['dns-address']
3096 if isinstance(ip_profile_ro
['dns_address'], (list, tuple)):
3097 ip_profile_ro
['dns_address'] = ";".join(ip_profile_ro
['dns_address'])
3098 if 'dhcp' in ip_profile_im
:
3099 ip_profile_ro
['dhcp_start_address'] = ip_profile_im
['dhcp'].get('start-address')
3100 ip_profile_ro
['dhcp_enabled'] = ip_profile_im
['dhcp'].get('enabled', True)
3101 ip_profile_ro
['dhcp_count'] = ip_profile_im
['dhcp'].get('count')
3102 return ip_profile_ro
3104 # logger.debug("Creating instance from scenario-dict:\n%s",
3105 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
3107 # 0 check correct parameters
3108 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).iteritems():
3109 for scenario_net
in scenarioDict
['nets']:
3110 if net_name
== scenario_net
.get("name") or net_name
== scenario_net
.get("osm_id") or net_name
== scenario_net
.get("uuid"):
3113 raise NfvoException("Invalid scenario network name or id '{}' at instance:networks".format(net_name
),
3114 httperrors
.Bad_Request
)
3115 if "sites" not in net_instance_desc
:
3116 net_instance_desc
["sites"] = [ {} ]
3117 site_without_datacenter_field
= False
3118 for site
in net_instance_desc
["sites"]:
3119 if site
.get("datacenter"):
3120 site
["datacenter"], _
= get_datacenter_uuid(mydb
, tenant_id
, site
["datacenter"])
3121 if site
["datacenter"] not in myvims
:
3122 # Add this datacenter to myvims
3123 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
3125 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
3126 site
["datacenter"] = d
# change name to id
3128 if site_without_datacenter_field
:
3129 raise NfvoException("Found more than one entries without datacenter field at "
3130 "instance:networks:{}:sites".format(net_name
), httperrors
.Bad_Request
)
3131 site_without_datacenter_field
= True
3132 site
["datacenter"] = default_datacenter_id
# change name to id
3134 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
3135 for scenario_vnf
in scenarioDict
['vnfs']:
3136 if vnf_name
== scenario_vnf
['member_vnf_index'] or vnf_name
== scenario_vnf
['uuid'] or vnf_name
== scenario_vnf
['name']:
3139 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_name
), httperrors
.Bad_Request
)
3140 if "datacenter" in vnf_instance_desc
:
3141 # Add this datacenter to myvims
3142 vnf_instance_desc
["datacenter"], _
= get_datacenter_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3143 if vnf_instance_desc
["datacenter"] not in myvims
:
3144 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3146 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3147 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
3149 for net_id
, net_instance_desc
in vnf_instance_desc
.get("networks", {}).iteritems():
3150 for scenario_net
in scenario_vnf
['nets']:
3151 if net_id
== scenario_net
['osm_id'] or net_id
== scenario_net
['uuid'] or net_id
== scenario_net
["name"]:
3154 raise NfvoException("Invalid net id or name '{}' at instance:vnfs:networks".format(net_id
), httperrors
.Bad_Request
)
3155 if net_instance_desc
.get("vim-network-name"):
3156 scenario_net
["vim-network-name"] = net_instance_desc
["vim-network-name"]
3157 if net_instance_desc
.get("vim-network-id"):
3158 scenario_net
["vim-network-id"] = net_instance_desc
["vim-network-id"]
3159 if net_instance_desc
.get("name"):
3160 scenario_net
["name"] = net_instance_desc
["name"]
3161 if 'ip-profile' in net_instance_desc
:
3162 ipprofile_db
= ip_profile_IM2RO(net_instance_desc
['ip-profile'])
3163 if 'ip_profile' not in scenario_net
:
3164 scenario_net
['ip_profile'] = ipprofile_db
3166 update(scenario_net
['ip_profile'], ipprofile_db
)
3168 for vdu_id
, vdu_instance_desc
in vnf_instance_desc
.get("vdus", {}).iteritems():
3169 for scenario_vm
in scenario_vnf
['vms']:
3170 if vdu_id
== scenario_vm
['osm_id'] or vdu_id
== scenario_vm
["name"]:
3173 raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id
), httperrors
.Bad_Request
)
3174 scenario_vm
["instance_parameters"] = vdu_instance_desc
3175 for iface_id
, iface_instance_desc
in vdu_instance_desc
.get("interfaces", {}).iteritems():
3176 for scenario_interface
in scenario_vm
['interfaces']:
3177 if iface_id
== scenario_interface
['internal_name'] or iface_id
== scenario_interface
["external_name"]:
3178 scenario_interface
.update(iface_instance_desc
)
3181 raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id
), httperrors
.Bad_Request
)
3183 # 0.1 parse cloud-config parameters
3184 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
3186 # 0.2 merge instance information into scenario
3187 # Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
3188 # However, this is not possible yet.
3189 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).iteritems():
3190 for scenario_net
in scenarioDict
['nets']:
3191 if net_name
== scenario_net
.get("name") or net_name
== scenario_net
.get("osm_id") or net_name
== scenario_net
.get("uuid"):
3192 if "wim_account" in net_instance_desc
and net_instance_desc
["wim_account"] is not None:
3193 scenario_net
["wim_account"] = net_instance_desc
["wim_account"]
3194 if 'ip-profile' in net_instance_desc
:
3195 ipprofile_db
= ip_profile_IM2RO(net_instance_desc
['ip-profile'])
3196 if 'ip_profile' not in scenario_net
:
3197 scenario_net
['ip_profile'] = ipprofile_db
3199 update(scenario_net
['ip_profile'], ipprofile_db
)
3200 for interface
in net_instance_desc
.get('interfaces', ()):
3201 if 'ip_address' in interface
:
3202 for vnf
in scenarioDict
['vnfs']:
3203 if interface
['vnf'] == vnf
['name']:
3204 for vnf_interface
in vnf
['interfaces']:
3205 if interface
['vnf_interface'] == vnf_interface
['external_name']:
3206 vnf_interface
['ip_address'] = interface
['ip_address']
3208 # logger.debug(">>>>>>>> Merged dictionary")
3209 # logger.debug("Creating instance scenario-dict MERGED:\n%s",
3210 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
3212 # 1. Creating new nets (sce_nets) in the VIM"
3213 number_mgmt_networks
= 0
3214 db_instance_nets
= []
3215 for sce_net
in scenarioDict
['nets']:
3216 sce_net_uuid
= sce_net
.get('uuid', sce_net
["name"])
3217 # get involved datacenters where this network need to be created
3218 involved_datacenters
= []
3219 for sce_vnf
in scenarioDict
.get("vnfs", ()):
3220 vnf_datacenter
= sce_vnf
.get("datacenter", default_datacenter_id
)
3221 if vnf_datacenter
in involved_datacenters
:
3223 if sce_vnf
.get("interfaces"):
3224 for sce_vnf_ifaces
in sce_vnf
["interfaces"]:
3225 if sce_vnf_ifaces
.get("sce_net_id") == sce_net
["uuid"]:
3226 involved_datacenters
.append(vnf_datacenter
)
3228 if not involved_datacenters
:
3229 involved_datacenters
.append(default_datacenter_id
)
3230 target_wim_account
= sce_net
.get("wim_account", default_wim_account
)
3233 # TODO: use this information during network creation
3234 wim_account_id
= wim_account_name
= None
3235 if len(involved_datacenters
) > 1 and 'uuid' in sce_net
:
3236 if target_wim_account
is None or target_wim_account
is True: # automatic selection of WIM
3237 # OBS: sce_net without uuid are used internally to VNFs
3238 # and the assumption is that VNFs will not be split among
3239 # different datacenters
3240 wim_account
= wim_engine
.find_suitable_wim_account(
3241 involved_datacenters
, tenant_id
)
3242 wim_account_id
= wim_account
['uuid']
3243 wim_account_name
= wim_account
['name']
3244 wim_usage
[sce_net
['uuid']] = wim_account_id
3245 elif isinstance(target_wim_account
, str): # manual selection of WIM
3246 wim_account
.persist
.get_wim_account_by(target_wim_account
, tenant_id
)
3247 wim_account_id
= wim_account
['uuid']
3248 wim_account_name
= wim_account
['name']
3249 wim_usage
[sce_net
['uuid']] = wim_account_id
3250 else: # not WIM usage
3251 wim_usage
[sce_net
['uuid']] = False
3255 if instance_dict
.get("networks"):
3256 if sce_net
.get("uuid") in instance_dict
["networks"]:
3257 descriptor_net
= instance_dict
["networks"][sce_net
["uuid"]]
3258 descriptor_net_name
= sce_net
["uuid"]
3259 elif sce_net
.get("osm_id") in instance_dict
["networks"]:
3260 descriptor_net
= instance_dict
["networks"][sce_net
["osm_id"]]
3261 descriptor_net_name
= sce_net
["osm_id"]
3262 elif sce_net
["name"] in instance_dict
["networks"]:
3263 descriptor_net
= instance_dict
["networks"][sce_net
["name"]]
3264 descriptor_net_name
= sce_net
["name"]
3265 net_name
= descriptor_net
.get("vim-network-name")
3266 # add datacenters from instantiation parameters
3267 if descriptor_net
.get("sites"):
3268 for site
in descriptor_net
["sites"]:
3269 if site
.get("datacenter") and site
["datacenter"] not in involved_datacenters
:
3270 involved_datacenters
.append(site
["datacenter"])
3271 sce_net2instance
[sce_net_uuid
] = {}
3272 net2task_id
['scenario'][sce_net_uuid
] = {}
3275 related_network
= None
3276 if descriptor_net
.get("use-network"):
3277 target_instance_nets
= mydb
.get_rows(
3279 FROM
="instance_nets",
3280 WHERE
={"instance_scenario_id": descriptor_net
["use-network"]["instance_scenario_id"],
3281 "osm_id": descriptor_net
["use-network"]["osm_id"]},
3283 if not target_instance_nets
:
3284 raise NfvoException(
3285 "Cannot find the target network at instance:networks[{}]:use-network".format(descriptor_net_name
),
3286 httperrors
.Bad_Request
)
3288 use_network
= target_instance_nets
[0]["related"]
3290 if sce_net
["external"]:
3291 number_mgmt_networks
+= 1
3293 for datacenter_id
in involved_datacenters
:
3295 netmap_create
= None
3296 if descriptor_net
.get("sites"):
3297 for site
in descriptor_net
["sites"]:
3298 if site
.get("datacenter") == datacenter_id
:
3299 netmap_use
= site
.get("netmap-use")
3300 netmap_create
= site
.get("netmap-create")
3303 vim
= myvims
[datacenter_id
]
3304 myvim_thread_id
= myvim_threads_id
[datacenter_id
]
3306 net_type
= sce_net
['type']
3308 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} # 'shared': True
3311 if sce_net
["external"]:
3312 net_name
= sce_net
["name"]
3314 net_name
= "{}-{}".format(instance_name
, sce_net
["name"])
3315 net_name
= net_name
[:255] # limit length
3317 if netmap_use
or netmap_create
:
3318 create_network
= False
3319 lookfor_network
= False
3321 lookfor_network
= True
3322 if utils
.check_valid_uuid(netmap_use
):
3323 lookfor_filter
["id"] = netmap_use
3325 lookfor_filter
["name"] = netmap_use
3327 create_network
= True
3328 net_vim_name
= net_name
3329 if isinstance(netmap_create
, str):
3330 net_vim_name
= netmap_create
3331 elif sce_net
.get("vim_network_name"):
3332 create_network
= False
3333 lookfor_network
= True
3334 lookfor_filter
["name"] = sce_net
.get("vim_network_name")
3335 elif sce_net
["external"]:
3336 if sce_net
.get('vim_id'):
3337 # there is a netmap at datacenter_nets database # TODO REVISE!!!!
3338 create_network
= False
3339 lookfor_network
= True
3340 lookfor_filter
["id"] = sce_net
['vim_id']
3341 elif vim
["config"].get("management_network_id") or vim
["config"].get("management_network_name"):
3342 if number_mgmt_networks
> 1:
3343 raise NfvoException("Found several VLD of type mgmt. "
3344 "You must concrete what vim-network must be use for each one",
3345 httperrors
.Bad_Request
)
3346 create_network
= False
3347 lookfor_network
= True
3348 if vim
["config"].get("management_network_id"):
3349 lookfor_filter
["id"] = vim
["config"]["management_network_id"]
3351 lookfor_filter
["name"] = vim
["config"]["management_network_name"]
3353 # There is not a netmap, look at datacenter for a net with this name and create if not found
3354 create_network
= True
3355 lookfor_network
= True
3356 lookfor_filter
["name"] = sce_net
["name"]
3357 net_vim_name
= sce_net
["name"]
3359 net_vim_name
= net_name
3360 create_network
= True
3361 lookfor_network
= False
3365 task_action
= "CREATE"
3366 task_extra
["params"] = (net_vim_name
, net_type
, sce_net
.get('ip_profile', None), wim_account_name
)
3368 task_extra
["find"] = (lookfor_filter
,)
3369 elif lookfor_network
:
3370 task_action
= "FIND"
3371 task_extra
["params"] = (lookfor_filter
,)
3373 # fill database content
3374 net_uuid
= str(uuid4())
3375 uuid_list
.append(net_uuid
)
3376 sce_net2instance
[sce_net_uuid
][datacenter_id
] = net_uuid
3377 if not related_network
: # all db_instance_nets will have same related
3378 related_network
= use_network
or net_uuid
3381 "osm_id": sce_net
.get("osm_id") or sce_net
["name"],
3382 "related": related_network
,
3384 "vim_name": net_vim_name
,
3385 "instance_scenario_id": instance_uuid
,
3386 "sce_net_id": sce_net
.get("uuid"),
3387 "created": create_network
,
3388 'datacenter_id': datacenter_id
,
3389 'datacenter_tenant_id': myvim_thread_id
,
3390 'status': 'BUILD' # if create_network else "ACTIVE"
3392 db_instance_nets
.append(db_net
)
3394 "instance_action_id": instance_action_id
,
3395 "status": "SCHEDULED",
3396 "task_index": task_index
,
3397 "datacenter_vim_id": myvim_thread_id
,
3398 "action": task_action
,
3399 "item": "instance_nets",
3400 "item_id": net_uuid
,
3401 "related": related_network
,
3402 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
3404 net2task_id
['scenario'][sce_net_uuid
][datacenter_id
] = task_index
3406 db_vim_actions
.append(db_vim_action
)
3408 if 'ip_profile' in sce_net
:
3410 'instance_net_id': net_uuid
,
3411 'ip_version': sce_net
['ip_profile']['ip_version'],
3412 'subnet_address': sce_net
['ip_profile']['subnet_address'],
3413 'gateway_address': sce_net
['ip_profile']['gateway_address'],
3414 'dns_address': sce_net
['ip_profile']['dns_address'],
3415 'dhcp_enabled': sce_net
['ip_profile']['dhcp_enabled'],
3416 'dhcp_start_address': sce_net
['ip_profile']['dhcp_start_address'],
3417 'dhcp_count': sce_net
['ip_profile']['dhcp_count'],
3419 db_ip_profiles
.append(db_ip_profile
)
3423 "default_datacenter_id": default_datacenter_id
,
3424 "myvim_threads_id": myvim_threads_id
,
3425 "instance_uuid": instance_uuid
,
3426 "instance_name": instance_name
,
3427 "instance_action_id": instance_action_id
,
3429 "cloud_config": cloud_config
,
3430 "RO_pub_key": tenant
[0].get('RO_pub_key'),
3431 "instance_parameters": instance_dict
,
3434 "task_index": task_index
,
3435 "uuid_list": uuid_list
,
3436 "db_instance_nets": db_instance_nets
,
3437 "db_vim_actions": db_vim_actions
,
3438 "db_ip_profiles": db_ip_profiles
,
3439 "db_instance_vnfs": db_instance_vnfs
,
3440 "db_instance_vms": db_instance_vms
,
3441 "db_instance_interfaces": db_instance_interfaces
,
3442 "net2task_id": net2task_id
,
3443 "sce_net2instance": sce_net2instance
,
3445 # sce_vnf_list = sorted(scenarioDict['vnfs'], key=lambda k: k['name'])
3446 for sce_vnf
in scenarioDict
.get('vnfs', ()): # sce_vnf_list:
3447 instantiate_vnf(mydb
, sce_vnf
, vnf_params
, vnf_params_out
, rollbackList
)
3448 task_index
= vnf_params_out
["task_index"]
3449 uuid_list
= vnf_params_out
["uuid_list"]
3452 # task_depends_on = []
3453 for vnffg
in scenarioDict
.get('vnffgs', ()):
3454 for rsp
in vnffg
['rsps']:
3456 for cp
in rsp
['connection_points']:
3457 count
= mydb
.get_rows(
3459 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_rsp_hops as h "
3460 "on interfaces.uuid=h.ingress_interface_id",
3461 WHERE
={'h.uuid': cp
['uuid']})[0]['count']
3462 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == cp
['sce_vnf_id']), None)
3463 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3465 for instance_vm
in instance_vms
:
3466 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3468 dependencies
.append(action
['task_index'])
3469 # TODO: throw exception if count != len(instance_vms)
3470 # TODO: and action shouldn't ever be None
3472 for i
in range(count
):
3474 sfi_uuid
= str(uuid4())
3476 "ingress_interface_id": cp
["ingress_interface_id"],
3477 "egress_interface_id": cp
["egress_interface_id"]
3479 uuid_list
.append(sfi_uuid
)
3482 "related": sfi_uuid
,
3483 "instance_scenario_id": instance_uuid
,
3484 'sce_rsp_hop_id': cp
['uuid'],
3485 'datacenter_id': datacenter_id
,
3486 'datacenter_tenant_id': myvim_thread_id
,
3487 "vim_sfi_id": None, # vim thread will populate
3489 db_instance_sfis
.append(db_sfi
)
3491 "instance_action_id": instance_action_id
,
3492 "task_index": task_index
,
3493 "datacenter_vim_id": myvim_thread_id
,
3495 "status": "SCHEDULED",
3496 "item": "instance_sfis",
3497 "item_id": sfi_uuid
,
3498 "related": sfi_uuid
,
3499 "extra": yaml
.safe_dump({"params": extra_params
, "depends_on": [dependencies
[i
]]},
3500 default_flow_style
=True, width
=256)
3502 sfis_created
.append(task_index
)
3504 db_vim_actions
.append(db_vim_action
)
3506 sf_uuid
= str(uuid4())
3507 uuid_list
.append(sf_uuid
)
3511 "instance_scenario_id": instance_uuid
,
3512 'sce_rsp_hop_id': cp
['uuid'],
3513 'datacenter_id': datacenter_id
,
3514 'datacenter_tenant_id': myvim_thread_id
,
3515 "vim_sf_id": None, # vim thread will populate
3517 db_instance_sfs
.append(db_sf
)
3519 "instance_action_id": instance_action_id
,
3520 "task_index": task_index
,
3521 "datacenter_vim_id": myvim_thread_id
,
3523 "status": "SCHEDULED",
3524 "item": "instance_sfs",
3527 "extra": yaml
.safe_dump({"params": "", "depends_on": sfis_created
},
3528 default_flow_style
=True, width
=256)
3530 sfs_created
.append(task_index
)
3532 db_vim_actions
.append(db_vim_action
)
3533 classifier
= rsp
['classifier']
3535 # TODO the following ~13 lines can be reused for the sfi case
3536 count
= mydb
.get_rows(
3537 SELECT
=('vms.count'),
3538 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_classifiers as c on interfaces.uuid=c.interface_id",
3539 WHERE
={'c.uuid': classifier
['uuid']})[0]['count']
3540 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == classifier
['sce_vnf_id']), None)
3541 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3543 for instance_vm
in instance_vms
:
3544 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3546 dependencies
.append(action
['task_index'])
3547 # TODO: throw exception if count != len(instance_vms)
3548 # TODO: and action shouldn't ever be None
3549 classifications_created
= []
3550 for i
in range(count
):
3551 for match
in classifier
['matches']:
3552 # create classifications
3553 classification_uuid
= str(uuid4())
3554 uuid_list
.append(classification_uuid
)
3555 db_classification
= {
3556 "uuid": classification_uuid
,
3557 "related": classification_uuid
,
3558 "instance_scenario_id": instance_uuid
,
3559 'sce_classifier_match_id': match
['uuid'],
3560 'datacenter_id': datacenter_id
,
3561 'datacenter_tenant_id': myvim_thread_id
,
3562 "vim_classification_id": None, # vim thread will populate
3564 db_instance_classifications
.append(db_classification
)
3565 classification_params
= {
3566 "ip_proto": match
["ip_proto"],
3567 "source_ip": match
["source_ip"],
3568 "destination_ip": match
["destination_ip"],
3569 "source_port": match
["source_port"],
3570 "destination_port": match
["destination_port"]
3573 "instance_action_id": instance_action_id
,
3574 "task_index": task_index
,
3575 "datacenter_vim_id": myvim_thread_id
,
3577 "status": "SCHEDULED",
3578 "item": "instance_classifications",
3579 "item_id": classification_uuid
,
3580 "related": classification_uuid
,
3581 "extra": yaml
.safe_dump({"params": classification_params
, "depends_on": [dependencies
[i
]]},
3582 default_flow_style
=True, width
=256)
3584 classifications_created
.append(task_index
)
3586 db_vim_actions
.append(db_vim_action
)
3589 sfp_uuid
= str(uuid4())
3590 uuid_list
.append(sfp_uuid
)
3593 "related": sfp_uuid
,
3594 "instance_scenario_id": instance_uuid
,
3595 'sce_rsp_id': rsp
['uuid'],
3596 'datacenter_id': datacenter_id
,
3597 'datacenter_tenant_id': myvim_thread_id
,
3598 "vim_sfp_id": None, # vim thread will populate
3600 db_instance_sfps
.append(db_sfp
)
3602 "instance_action_id": instance_action_id
,
3603 "task_index": task_index
,
3604 "datacenter_vim_id": myvim_thread_id
,
3606 "status": "SCHEDULED",
3607 "item": "instance_sfps",
3608 "item_id": sfp_uuid
,
3609 "related": sfp_uuid
,
3610 "extra": yaml
.safe_dump({"params": "", "depends_on": sfs_created
+ classifications_created
},
3611 default_flow_style
=True, width
=256)
3614 db_vim_actions
.append(db_vim_action
)
3615 db_instance_action
["number_tasks"] = task_index
3618 logger
.debug('wim_usage:\n%s\n\n', pformat(wim_usage
))
3619 wan_links
= wim_engine
.derive_wan_links(wim_usage
, db_instance_nets
, tenant_id
)
3620 wim_actions
= wim_engine
.create_actions(wan_links
)
3621 wim_actions
, db_instance_action
= (
3622 wim_engine
.incorporate_actions(wim_actions
, db_instance_action
))
3625 scenarioDict
["datacenter2tenant"] = myvim_threads_id
3627 db_instance_scenario
['datacenter_tenant_id'] = myvim_threads_id
[default_datacenter_id
]
3628 db_instance_scenario
['datacenter_id'] = default_datacenter_id
3630 {"instance_scenarios": db_instance_scenario
},
3631 {"instance_vnfs": db_instance_vnfs
},
3632 {"instance_nets": db_instance_nets
},
3633 {"ip_profiles": db_ip_profiles
},
3634 {"instance_vms": db_instance_vms
},
3635 {"instance_interfaces": db_instance_interfaces
},
3636 {"instance_actions": db_instance_action
},
3637 {"instance_sfis": db_instance_sfis
},
3638 {"instance_sfs": db_instance_sfs
},
3639 {"instance_classifications": db_instance_classifications
},
3640 {"instance_sfps": db_instance_sfps
},
3641 {"instance_wim_nets": wan_links
},
3642 {"vim_wim_actions": db_vim_actions
+ wim_actions
}
3645 logger
.debug("create_instance done DB tables: %s",
3646 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
3647 mydb
.new_rows(db_tables
, uuid_list
)
3648 for myvim_thread_id
in myvim_threads_id
.values():
3649 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
3651 wim_engine
.dispatch(wim_actions
)
3653 returned_instance
= mydb
.get_instance_scenario(instance_uuid
)
3654 returned_instance
["action_id"] = instance_action_id
3655 return returned_instance
3656 except (NfvoException
, vimconn
.vimconnException
, wimconn
.WimConnectorError
, db_base_Exception
) as e
:
3657 message
= rollback(mydb
, myvims
, rollbackList
)
3658 if isinstance(e
, db_base_Exception
):
3659 error_text
= "database Exception"
3660 elif isinstance(e
, vimconn
.vimconnException
):
3661 error_text
= "VIM Exception"
3662 elif isinstance(e
, wimconn
.WimConnectorError
):
3663 error_text
= "WIM Exception"
3665 error_text
= "Exception"
3666 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
3667 # logger.error("create_instance: %s", error_text)
3669 raise NfvoException(error_text
, e
.http_code
)
3672 def instantiate_vnf(mydb
, sce_vnf
, params
, params_out
, rollbackList
):
3673 default_datacenter_id
= params
["default_datacenter_id"]
3674 myvim_threads_id
= params
["myvim_threads_id"]
3675 instance_uuid
= params
["instance_uuid"]
3676 instance_name
= params
["instance_name"]
3677 instance_action_id
= params
["instance_action_id"]
3678 myvims
= params
["myvims"]
3679 cloud_config
= params
["cloud_config"]
3680 RO_pub_key
= params
["RO_pub_key"]
3682 task_index
= params_out
["task_index"]
3683 uuid_list
= params_out
["uuid_list"]
3684 db_instance_nets
= params_out
["db_instance_nets"]
3685 db_vim_actions
= params_out
["db_vim_actions"]
3686 db_ip_profiles
= params_out
["db_ip_profiles"]
3687 db_instance_vnfs
= params_out
["db_instance_vnfs"]
3688 db_instance_vms
= params_out
["db_instance_vms"]
3689 db_instance_interfaces
= params_out
["db_instance_interfaces"]
3690 net2task_id
= params_out
["net2task_id"]
3691 sce_net2instance
= params_out
["sce_net2instance"]
3693 vnf_net2instance
= {}
3695 # 2. Creating new nets (vnf internal nets) in the VIM"
3696 # For each vnf net, we create it and we add it to instanceNetlist.
3697 if sce_vnf
.get("datacenter"):
3698 datacenter_id
= sce_vnf
["datacenter"]
3699 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
3701 datacenter_id
= default_datacenter_id
3702 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
3703 for net
in sce_vnf
['nets']:
3705 # descriptor_net = instance_dict.get("vnfs", {}).get(sce_vnf["name"], {})
3706 # net_name = descriptor_net.get("name")
3709 net_name
= "{}-{}".format(instance_name
, net
["name"])
3710 net_name
= net_name
[:255] # limit length
3711 net_type
= net
['type']
3713 if sce_vnf
['uuid'] not in vnf_net2instance
:
3714 vnf_net2instance
[sce_vnf
['uuid']] = {}
3715 if sce_vnf
['uuid'] not in net2task_id
:
3716 net2task_id
[sce_vnf
['uuid']] = {}
3717 net2task_id
[sce_vnf
['uuid']][net
['uuid']] = task_index
3719 # fill database content
3720 net_uuid
= str(uuid4())
3721 uuid_list
.append(net_uuid
)
3722 vnf_net2instance
[sce_vnf
['uuid']][net
['uuid']] = net_uuid
3725 "related": net_uuid
,
3727 "vim_name": net_name
,
3728 "instance_scenario_id": instance_uuid
,
3729 "net_id": net
["uuid"],
3731 'datacenter_id': datacenter_id
,
3732 'datacenter_tenant_id': myvim_thread_id
,
3734 db_instance_nets
.append(db_net
)
3737 if net
.get("vim-network-name"):
3738 lookfor_filter
["name"] = net
["vim-network-name"]
3739 if net
.get("vim-network-id"):
3740 lookfor_filter
["id"] = net
["vim-network-id"]
3742 task_action
= "FIND"
3743 task_extra
= {"params": (lookfor_filter
,)}
3745 task_action
= "CREATE"
3746 task_extra
= {"params": (net_name
, net_type
, net
.get('ip_profile', None))}
3749 "instance_action_id": instance_action_id
,
3750 "task_index": task_index
,
3751 "datacenter_vim_id": myvim_thread_id
,
3752 "status": "SCHEDULED",
3753 "action": task_action
,
3754 "item": "instance_nets",
3755 "item_id": net_uuid
,
3756 "related": net_uuid
,
3757 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
3760 db_vim_actions
.append(db_vim_action
)
3762 if 'ip_profile' in net
:
3764 'instance_net_id': net_uuid
,
3765 'ip_version': net
['ip_profile']['ip_version'],
3766 'subnet_address': net
['ip_profile']['subnet_address'],
3767 'gateway_address': net
['ip_profile']['gateway_address'],
3768 'dns_address': net
['ip_profile']['dns_address'],
3769 'dhcp_enabled': net
['ip_profile']['dhcp_enabled'],
3770 'dhcp_start_address': net
['ip_profile']['dhcp_start_address'],
3771 'dhcp_count': net
['ip_profile']['dhcp_count'],
3773 db_ip_profiles
.append(db_ip_profile
)
3775 # print "vnf_net2instance:"
3776 # print yaml.safe_dump(vnf_net2instance, indent=4, default_flow_style=False)
3778 # 3. Creating new vm instances in the VIM
3779 # myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
3781 if sce_vnf
.get('mgmt_access'):
3782 ssh_access
= sce_vnf
['mgmt_access'].get('config-access', {}).get('ssh-access')
3783 vnf_availability_zones
= []
3784 for vm
in sce_vnf
.get('vms'):
3785 vm_av
= vm
.get('availability_zone')
3786 if vm_av
and vm_av
not in vnf_availability_zones
:
3787 vnf_availability_zones
.append(vm_av
)
3789 # check if there is enough availability zones available at vim level.
3790 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
3791 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
3792 raise NfvoException('No enough availability zones at VIM for this deployment', httperrors
.Bad_Request
)
3794 if sce_vnf
.get("datacenter"):
3795 vim
= myvims
[sce_vnf
["datacenter"]]
3796 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
3797 datacenter_id
= sce_vnf
["datacenter"]
3799 vim
= myvims
[default_datacenter_id
]
3800 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
3801 datacenter_id
= default_datacenter_id
3802 sce_vnf
["datacenter_id"] = datacenter_id
3805 vnf_uuid
= str(uuid4())
3806 uuid_list
.append(vnf_uuid
)
3809 'instance_scenario_id': instance_uuid
,
3810 'vnf_id': sce_vnf
['vnf_id'],
3811 'sce_vnf_id': sce_vnf
['uuid'],
3812 'datacenter_id': datacenter_id
,
3813 'datacenter_tenant_id': myvim_thread_id
,
3815 db_instance_vnfs
.append(db_instance_vnf
)
3817 for vm
in sce_vnf
['vms']:
3819 if vm
.get("pdu_type"):
3823 sce_vnf_name
= sce_vnf
['member_vnf_index'] if sce_vnf
['member_vnf_index'] else sce_vnf
['name']
3824 myVMDict
['name'] = "{}-{}-{}".format(instance_name
[:64], sce_vnf_name
[:64], vm
["name"][:64])
3825 myVMDict
['description'] = myVMDict
['name'][0:99]
3827 # myVMDict['start'] = "no"
3828 if vm
.get("instance_parameters") and vm
["instance_parameters"].get("name"):
3829 myVMDict
['name'] = vm
["instance_parameters"].get("name")
3830 myVMDict
['name'] = myVMDict
['name'][0:255] # limit name length
3831 # create image at vim in case it not exist
3832 image_uuid
= vm
['image_id']
3833 if vm
.get("image_list"):
3834 for alternative_image
in vm
["image_list"]:
3835 if alternative_image
["vim_type"] == vim
["config"]["_vim_type_internal"]:
3836 image_uuid
= alternative_image
['image_id']
3838 image_dict
= mydb
.get_table_by_uuid_name("images", image_uuid
)
3839 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
3840 vm
['vim_image_id'] = image_id
3842 # create flavor at vim in case it not exist
3843 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
3844 if flavor_dict
['extended'] != None:
3845 flavor_dict
['extended'] = yaml
.load(flavor_dict
['extended'])
3846 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
3848 # Obtain information for additional disks
3849 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',),
3850 WHERE
={'vim_id': flavor_id
})
3851 if not extended_flavor_dict
:
3852 raise NfvoException("flavor '{}' not found".format(flavor_id
), httperrors
.Not_Found
)
3854 # extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
3855 myVMDict
['disks'] = None
3856 extended_info
= extended_flavor_dict
[0]['extended']
3857 if extended_info
!= None:
3858 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
3859 if 'disks' in extended_flavor_dict_yaml
:
3860 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
3861 if vm
.get("instance_parameters") and vm
["instance_parameters"].get("devices"):
3862 for disk
in myVMDict
['disks']:
3863 if disk
.get("name") in vm
["instance_parameters"]["devices"]:
3864 disk
.update(vm
["instance_parameters"]["devices"][disk
.get("name")])
3866 vm
['vim_flavor_id'] = flavor_id
3867 myVMDict
['imageRef'] = vm
['vim_image_id']
3868 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
3869 myVMDict
['availability_zone'] = vm
.get('availability_zone')
3870 myVMDict
['networks'] = []
3871 task_depends_on
= []
3872 # TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
3873 is_management_vm
= False
3875 for iface
in vm
['interfaces']:
3877 if iface
['type'] == "data":
3878 netDict
['type'] = iface
['model']
3879 elif "model" in iface
and iface
["model"] != None:
3880 netDict
['model'] = iface
['model']
3881 # TODO in future, remove this because mac_address will not be set, and the type of PV,VF
3882 # is obtained from iterface table model
3883 # discover type of interface looking at flavor
3884 for numa
in flavor_dict
.get('extended', {}).get('numas', []):
3885 for flavor_iface
in numa
.get('interfaces', []):
3886 if flavor_iface
.get('name') == iface
['internal_name']:
3887 if flavor_iface
['dedicated'] == 'yes':
3888 netDict
['type'] = "PF" # passthrough
3889 elif flavor_iface
['dedicated'] == 'no':
3890 netDict
['type'] = "VF" # siov
3891 elif flavor_iface
['dedicated'] == 'yes:sriov':
3892 netDict
['type'] = "VFnotShared" # sriov but only one sriov on the PF
3893 netDict
["mac_address"] = flavor_iface
.get("mac_address")
3895 netDict
["use"] = iface
['type']
3896 if netDict
["use"] == "data" and not netDict
.get("type"):
3897 # print "netDict", netDict
3898 # print "iface", iface
3899 e_text
= "Cannot determine the interface type PF or VF of VNF '{}' VM '{}' iface '{}'".fromat(
3900 sce_vnf
['name'], vm
['name'], iface
['internal_name'])
3901 if flavor_dict
.get('extended') == None:
3902 raise NfvoException(e_text
+ "After database migration some information is not available. \
3903 Try to delete and create the scenarios and VNFs again", httperrors
.Conflict
)
3905 raise NfvoException(e_text
, httperrors
.Internal_Server_Error
)
3906 if netDict
["use"] == "mgmt":
3907 is_management_vm
= True
3908 netDict
["type"] = "virtual"
3909 if netDict
["use"] == "bridge":
3910 netDict
["type"] = "virtual"
3911 if iface
.get("vpci"):
3912 netDict
['vpci'] = iface
['vpci']
3913 if iface
.get("mac"):
3914 netDict
['mac_address'] = iface
['mac']
3915 if iface
.get("mac_address"):
3916 netDict
['mac_address'] = iface
['mac_address']
3917 if iface
.get("ip_address"):
3918 netDict
['ip_address'] = iface
['ip_address']
3919 if iface
.get("port-security") is not None:
3920 netDict
['port_security'] = iface
['port-security']
3921 if iface
.get("floating-ip") is not None:
3922 netDict
['floating_ip'] = iface
['floating-ip']
3923 netDict
['name'] = iface
['internal_name']
3924 if iface
['net_id'] is None:
3925 for vnf_iface
in sce_vnf
["interfaces"]:
3928 if vnf_iface
['interface_id'] == iface
['uuid']:
3929 netDict
['net_id'] = "TASK-{}".format(
3930 net2task_id
['scenario'][vnf_iface
['sce_net_id']][datacenter_id
])
3931 instance_net_id
= sce_net2instance
[vnf_iface
['sce_net_id']][datacenter_id
]
3932 task_depends_on
.append(net2task_id
['scenario'][vnf_iface
['sce_net_id']][datacenter_id
])
3935 netDict
['net_id'] = "TASK-{}".format(net2task_id
[sce_vnf
['uuid']][iface
['net_id']])
3936 instance_net_id
= vnf_net2instance
[sce_vnf
['uuid']][iface
['net_id']]
3937 task_depends_on
.append(net2task_id
[sce_vnf
['uuid']][iface
['net_id']])
3938 # skip bridge ifaces not connected to any net
3939 if 'net_id' not in netDict
or netDict
['net_id'] == None:
3941 myVMDict
['networks'].append(netDict
)
3944 # 'instance_vm_id': instance_vm_uuid,
3945 "instance_net_id": instance_net_id
,
3946 'interface_id': iface
['uuid'],
3947 # 'vim_interface_id': ,
3948 'type': 'external' if iface
['external_name'] is not None else 'internal',
3949 'ip_address': iface
.get('ip_address'),
3950 'mac_address': iface
.get('mac'),
3951 'floating_ip': int(iface
.get('floating-ip', False)),
3952 'port_security': int(iface
.get('port-security', True))
3954 db_vm_ifaces
.append(db_vm_iface
)
3955 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3956 # print myVMDict['name']
3957 # print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
3958 # print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
3959 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3961 # We add the RO key to cloud_config if vnf will need ssh access
3962 cloud_config_vm
= cloud_config
3963 if is_management_vm
and params
["instance_parameters"].get("mgmt_keys"):
3964 cloud_config_vm
= unify_cloud_config({"key-pairs": params
["instance_parameters"]["mgmt_keys"]},
3967 if vm
.get("instance_parameters") and vm
["instance_parameters"].get("mgmt_keys"):
3968 cloud_config_vm
= unify_cloud_config({"key-pairs": vm
["instance_parameters"]["mgmt_keys"]},
3970 # if ssh_access and ssh_access['required'] and ssh_access['default-user'] and tenant[0].get('RO_pub_key'):
3971 # RO_key = {"key-pairs": [tenant[0]['RO_pub_key']]}
3972 # cloud_config_vm = unify_cloud_config(cloud_config_vm, RO_key)
3973 if vm
.get("boot_data"):
3974 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config_vm
)
3976 if myVMDict
.get('availability_zone'):
3977 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
3980 for vm_index
in range(0, vm
.get('count', 1)):
3981 vm_name
= myVMDict
['name'] + "-" + str(vm_index
+1)
3982 task_params
= (vm_name
, myVMDict
['description'], myVMDict
.get('start', None),
3983 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'], cloud_config_vm
,
3984 myVMDict
['disks'], av_index
, vnf_availability_zones
)
3985 # put interface uuid back to scenario[vnfs][vms[[interfaces]
3986 for net
in myVMDict
['networks']:
3988 for iface
in vm
['interfaces']:
3989 if net
["name"] == iface
["internal_name"]:
3990 iface
["vim_id"] = net
["vim_id"]
3992 vm_uuid
= str(uuid4())
3993 uuid_list
.append(vm_uuid
)
3997 'instance_vnf_id': vnf_uuid
,
3998 # TODO delete "vim_vm_id": vm_id,
3999 "vm_id": vm
["uuid"],
4000 "vim_name": vm_name
,
4003 db_instance_vms
.append(db_vm
)
4006 for db_vm_iface
in db_vm_ifaces
:
4007 iface_uuid
= str(uuid4())
4008 uuid_list
.append(iface_uuid
)
4009 db_vm_iface_instance
= {
4011 "instance_vm_id": vm_uuid
4013 db_vm_iface_instance
.update(db_vm_iface
)
4014 if db_vm_iface_instance
.get("ip_address"): # increment ip_address
4015 ip
= db_vm_iface_instance
.get("ip_address")
4020 ip
= ip
[i
:] + str(int(ip
[:i
]) + 1)
4021 db_vm_iface_instance
["ip_address"] = ip
4023 db_vm_iface_instance
["ip_address"] = None
4024 db_instance_interfaces
.append(db_vm_iface_instance
)
4025 myVMDict
['networks'][iface_index
]["uuid"] = iface_uuid
4029 "instance_action_id": instance_action_id
,
4030 "task_index": task_index
,
4031 "datacenter_vim_id": myvim_thread_id
,
4033 "status": "SCHEDULED",
4034 "item": "instance_vms",
4037 "extra": yaml
.safe_dump({"params": task_params
, "depends_on": task_depends_on
},
4038 default_flow_style
=True, width
=256)
4041 db_vim_actions
.append(db_vim_action
)
4042 params_out
["task_index"] = task_index
4043 params_out
["uuid_list"] = uuid_list
4046 def delete_instance(mydb
, tenant_id
, instance_id
):
4047 # print "Checking that the instance_id exists and getting the instance dictionary"
4048 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
4049 # print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
4050 tenant_id
= instanceDict
["tenant_id"]
4053 # We need to retrieve the WIM Actions now, before the instance_scenario is
4054 # deleted. The reason for that is that: ON CASCADE rules will delete the
4055 # instance_wim_nets record in the database
4056 wim_actions
= wim_engine
.delete_actions(instance_scenario_id
=instance_id
)
4059 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
4060 # 1. Delete from Database
4061 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
4063 # 2. delete from VIM
4067 vimthread_affected
= {}
4068 net2vm_dependencies
= {}
4071 instance_action_id
= get_task_id()
4073 db_instance_action
= {
4074 "uuid": instance_action_id
, # same uuid for the instance and the action on create
4075 "tenant_id": tenant_id
,
4076 "instance_id": instance_id
,
4077 "description": "DELETE",
4078 # "number_tasks": 0 # filled bellow
4081 # 2.1 deleting VNFFGs
4082 for sfp
in instanceDict
.get('sfps', ()):
4083 vimthread_affected
[sfp
["datacenter_tenant_id"]] = None
4084 datacenter_key
= (sfp
["datacenter_id"], sfp
["datacenter_tenant_id"])
4085 if datacenter_key
not in myvims
:
4087 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sfp
["datacenter_id"], sfp
["datacenter_tenant_id"])
4088 except NfvoException
as e
:
4089 logger
.error(str(e
))
4091 myvim_threads
[datacenter_key
] = myvim_thread
4092 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sfp
["datacenter_id"],
4093 datacenter_tenant_id
=sfp
["datacenter_tenant_id"])
4095 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfp
["datacenter_id"], sfp
["datacenter_tenant_id"]))
4096 myvims
[datacenter_key
] = None
4098 myvims
[datacenter_key
] = vims
.values()[0]
4099 myvim
= myvims
[datacenter_key
]
4100 myvim_thread
= myvim_threads
[datacenter_key
]
4103 error_msg
+= "\n vim_sfp_id={} cannot be deleted because datacenter={} not found".format(sfp
['vim_sfp_id'], sfp
["datacenter_id"])
4105 extra
= {"params": (sfp
['vim_sfp_id'])}
4107 "instance_action_id": instance_action_id
,
4108 "task_index": task_index
,
4109 "datacenter_vim_id": sfp
["datacenter_tenant_id"],
4111 "status": "SCHEDULED",
4112 "item": "instance_sfps",
4113 "item_id": sfp
["uuid"],
4114 "related": sfp
["related"],
4115 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4118 db_vim_actions
.append(db_vim_action
)
4120 for classification
in instanceDict
['classifications']:
4121 vimthread_affected
[classification
["datacenter_tenant_id"]] = None
4122 datacenter_key
= (classification
["datacenter_id"], classification
["datacenter_tenant_id"])
4123 if datacenter_key
not in myvims
:
4125 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, classification
["datacenter_id"], classification
["datacenter_tenant_id"])
4126 except NfvoException
as e
:
4127 logger
.error(str(e
))
4129 myvim_threads
[datacenter_key
] = myvim_thread
4130 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=classification
["datacenter_id"],
4131 datacenter_tenant_id
=classification
["datacenter_tenant_id"])
4133 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(classification
["datacenter_id"],
4134 classification
["datacenter_tenant_id"]))
4135 myvims
[datacenter_key
] = None
4137 myvims
[datacenter_key
] = vims
.values()[0]
4138 myvim
= myvims
[datacenter_key
]
4139 myvim_thread
= myvim_threads
[datacenter_key
]
4142 error_msg
+= "\n vim_classification_id={} cannot be deleted because datacenter={} not found".format(classification
['vim_classification_id'],
4143 classification
["datacenter_id"])
4145 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfps"]
4146 extra
= {"params": (classification
['vim_classification_id']), "depends_on": depends_on
}
4148 "instance_action_id": instance_action_id
,
4149 "task_index": task_index
,
4150 "datacenter_vim_id": classification
["datacenter_tenant_id"],
4152 "status": "SCHEDULED",
4153 "item": "instance_classifications",
4154 "item_id": classification
["uuid"],
4155 "related": classification
["related"],
4156 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4159 db_vim_actions
.append(db_vim_action
)
4161 for sf
in instanceDict
.get('sfs', ()):
4162 vimthread_affected
[sf
["datacenter_tenant_id"]] = None
4163 datacenter_key
= (sf
["datacenter_id"], sf
["datacenter_tenant_id"])
4164 if datacenter_key
not in myvims
:
4166 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sf
["datacenter_id"], sf
["datacenter_tenant_id"])
4167 except NfvoException
as e
:
4168 logger
.error(str(e
))
4170 myvim_threads
[datacenter_key
] = myvim_thread
4171 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sf
["datacenter_id"],
4172 datacenter_tenant_id
=sf
["datacenter_tenant_id"])
4174 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sf
["datacenter_id"], sf
["datacenter_tenant_id"]))
4175 myvims
[datacenter_key
] = None
4177 myvims
[datacenter_key
] = vims
.values()[0]
4178 myvim
= myvims
[datacenter_key
]
4179 myvim_thread
= myvim_threads
[datacenter_key
]
4182 error_msg
+= "\n vim_sf_id={} cannot be deleted because datacenter={} not found".format(sf
['vim_sf_id'], sf
["datacenter_id"])
4184 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfps"]
4185 extra
= {"params": (sf
['vim_sf_id']), "depends_on": depends_on
}
4187 "instance_action_id": instance_action_id
,
4188 "task_index": task_index
,
4189 "datacenter_vim_id": sf
["datacenter_tenant_id"],
4191 "status": "SCHEDULED",
4192 "item": "instance_sfs",
4193 "item_id": sf
["uuid"],
4194 "related": sf
["related"],
4195 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4198 db_vim_actions
.append(db_vim_action
)
4200 for sfi
in instanceDict
.get('sfis', ()):
4201 vimthread_affected
[sfi
["datacenter_tenant_id"]] = None
4202 datacenter_key
= (sfi
["datacenter_id"], sfi
["datacenter_tenant_id"])
4203 if datacenter_key
not in myvims
:
4205 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sfi
["datacenter_id"], sfi
["datacenter_tenant_id"])
4206 except NfvoException
as e
:
4207 logger
.error(str(e
))
4209 myvim_threads
[datacenter_key
] = myvim_thread
4210 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sfi
["datacenter_id"],
4211 datacenter_tenant_id
=sfi
["datacenter_tenant_id"])
4213 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfi
["datacenter_id"], sfi
["datacenter_tenant_id"]))
4214 myvims
[datacenter_key
] = None
4216 myvims
[datacenter_key
] = vims
.values()[0]
4217 myvim
= myvims
[datacenter_key
]
4218 myvim_thread
= myvim_threads
[datacenter_key
]
4221 error_msg
+= "\n vim_sfi_id={} cannot be deleted because datacenter={} not found".format(sfi
['vim_sfi_id'], sfi
["datacenter_id"])
4223 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfs"]
4224 extra
= {"params": (sfi
['vim_sfi_id']), "depends_on": depends_on
}
4226 "instance_action_id": instance_action_id
,
4227 "task_index": task_index
,
4228 "datacenter_vim_id": sfi
["datacenter_tenant_id"],
4230 "status": "SCHEDULED",
4231 "item": "instance_sfis",
4232 "item_id": sfi
["uuid"],
4233 "related": sfi
["related"],
4234 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4237 db_vim_actions
.append(db_vim_action
)
4241 for sce_vnf
in instanceDict
.get('vnfs', ()):
4242 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
4243 vimthread_affected
[sce_vnf
["datacenter_tenant_id"]] = None
4244 if datacenter_key
not in myvims
:
4246 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
4247 except NfvoException
as e
:
4248 logger
.error(str(e
))
4250 myvim_threads
[datacenter_key
] = myvim_thread
4251 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
4252 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
4254 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
4255 sce_vnf
["datacenter_tenant_id"]))
4256 myvims
[datacenter_key
] = None
4258 myvims
[datacenter_key
] = vims
.values()[0]
4259 myvim
= myvims
[datacenter_key
]
4260 myvim_thread
= myvim_threads
[datacenter_key
]
4262 for vm
in sce_vnf
['vms']:
4264 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
4266 sfi_dependencies
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfis"]
4268 "instance_action_id": instance_action_id
,
4269 "task_index": task_index
,
4270 "datacenter_vim_id": sce_vnf
["datacenter_tenant_id"],
4272 "status": "SCHEDULED",
4273 "item": "instance_vms",
4274 "item_id": vm
["uuid"],
4275 "related": vm
["related"],
4276 "extra": yaml
.safe_dump({"params": vm
["interfaces"], "depends_on": sfi_dependencies
},
4277 default_flow_style
=True, width
=256)
4279 db_vim_actions
.append(db_vim_action
)
4280 for interface
in vm
["interfaces"]:
4281 if not interface
.get("instance_net_id"):
4283 if interface
["instance_net_id"] not in net2vm_dependencies
:
4284 net2vm_dependencies
[interface
["instance_net_id"]] = []
4285 net2vm_dependencies
[interface
["instance_net_id"]].append(task_index
)
4290 for net
in instanceDict
['nets']:
4291 vimthread_affected
[net
["datacenter_tenant_id"]] = None
4292 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
4293 if datacenter_key
not in myvims
:
4295 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, net
["datacenter_id"], net
["datacenter_tenant_id"])
4296 except NfvoException
as e
:
4297 logger
.error(str(e
))
4299 myvim_threads
[datacenter_key
] = myvim_thread
4300 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
4301 datacenter_tenant_id
=net
["datacenter_tenant_id"])
4303 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
4304 myvims
[datacenter_key
] = None
4306 myvims
[datacenter_key
] = vims
.values()[0]
4307 myvim
= myvims
[datacenter_key
]
4308 myvim_thread
= myvim_threads
[datacenter_key
]
4311 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
4313 extra
= {"params": (net
['vim_net_id'], net
['sdn_net_id'])}
4314 if net2vm_dependencies
.get(net
["uuid"]):
4315 extra
["depends_on"] = net2vm_dependencies
[net
["uuid"]]
4316 sfi_dependencies
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfis"]
4317 if len(sfi_dependencies
) > 0:
4318 if "depends_on" in extra
:
4319 extra
["depends_on"] += sfi_dependencies
4321 extra
["depends_on"] = sfi_dependencies
4323 "instance_action_id": instance_action_id
,
4324 "task_index": task_index
,
4325 "datacenter_vim_id": net
["datacenter_tenant_id"],
4327 "status": "SCHEDULED",
4328 "item": "instance_nets",
4329 "item_id": net
["uuid"],
4330 "related": net
["related"],
4331 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4334 db_vim_actions
.append(db_vim_action
)
4336 db_instance_action
["number_tasks"] = task_index
4339 wim_actions
, db_instance_action
= (
4340 wim_engine
.incorporate_actions(wim_actions
, db_instance_action
))
4344 {"instance_actions": db_instance_action
},
4345 {"vim_wim_actions": db_vim_actions
+ wim_actions
}
4348 logger
.debug("delete_instance done DB tables: %s",
4349 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
4350 mydb
.new_rows(db_tables
, ())
4351 for myvim_thread_id
in vimthread_affected
.keys():
4352 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
4354 wim_engine
.dispatch(wim_actions
)
4356 if len(error_msg
) > 0:
4357 return 'action_id={} instance {} deleted but some elements could not be deleted, or already deleted '\
4358 '(error: 404) from VIM: {}'.format(instance_action_id
, message
, error_msg
)
4360 return "action_id={} instance {} deleted".format(instance_action_id
, message
)
4362 def get_instance_id(mydb
, tenant_id
, instance_id
):
4364 #check valid tenant_id
4365 check_tenant(mydb
, tenant_id
)
4368 instance_dict
= mydb
.get_instance_scenario(instance_id
, tenant_id
, verbose
=True)
4369 for net
in instance_dict
["nets"]:
4370 if net
.get("sdn_net_id"):
4371 net_sdn
= ovim
.show_network(net
["sdn_net_id"])
4373 "admin_state_up": net_sdn
.get("admin_state_up"),
4374 "flows": net_sdn
.get("flows"),
4375 "last_error": net_sdn
.get("last_error"),
4376 "ports": net_sdn
.get("ports"),
4377 "type": net_sdn
.get("type"),
4378 "status": net_sdn
.get("status"),
4379 "vlan": net_sdn
.get("vlan"),
4381 return instance_dict
4383 @deprecated("Instance is automatically refreshed by vim_threads")
4384 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
4385 '''Refreshes a scenario instance. It modifies instanceDict'''
4387 - 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
4390 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
4391 # #print "nfvo.refresh_instance begins"
4392 # #print json.dumps(instanceDict, indent=4)
4394 # #print "Getting the VIM URL and the VIM tenant_id"
4397 # # 1. Getting VIM vm and net list
4398 # vms_updated = [] #List of VM instance uuids in openmano that were updated
4401 # for sce_vnf in instanceDict['vnfs']:
4402 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
4403 # if datacenter_key not in vm_list:
4404 # vm_list[datacenter_key] = []
4405 # if datacenter_key not in myvims:
4406 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
4407 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
4408 # if len(vims) == 0:
4409 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
4410 # myvims[datacenter_key] = None
4412 # myvims[datacenter_key] = vims.values()[0]
4413 # for vm in sce_vnf['vms']:
4414 # vm_list[datacenter_key].append(vm['vim_vm_id'])
4415 # vms_notupdated.append(vm["uuid"])
4417 # nets_updated = [] #List of VM instance uuids in openmano that were updated
4418 # nets_notupdated=[]
4420 # for net in instanceDict['nets']:
4421 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
4422 # if datacenter_key not in net_list:
4423 # net_list[datacenter_key] = []
4424 # if datacenter_key not in myvims:
4425 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
4426 # datacenter_tenant_id=net["datacenter_tenant_id"])
4427 # if len(vims) == 0:
4428 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
4429 # myvims[datacenter_key] = None
4431 # myvims[datacenter_key] = vims.values()[0]
4433 # net_list[datacenter_key].append(net['vim_net_id'])
4434 # nets_notupdated.append(net["uuid"])
4436 # # 1. Getting the status of all VMs
4438 # for datacenter_key in myvims:
4439 # if not vm_list.get(datacenter_key):
4443 # if not myvims[datacenter_key]:
4444 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
4447 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
4449 # except vimconn.vimconnException as e:
4450 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
4451 # failed_message = str(e)
4453 # for vm in vm_list[datacenter_key]:
4454 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
4456 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
4457 # for sce_vnf in instanceDict['vnfs']:
4458 # for vm in sce_vnf['vms']:
4459 # vm_id = vm['vim_vm_id']
4460 # interfaces = vm_dict[vm_id].pop('interfaces', [])
4461 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
4462 # has_mgmt_iface = False
4463 # for iface in vm["interfaces"]:
4464 # if iface["type"]=="mgmt":
4465 # has_mgmt_iface = True
4466 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
4467 # vm_dict[vm_id]['status'] = "ACTIVE"
4468 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
4469 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
4470 # 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'):
4471 # vm['status'] = vm_dict[vm_id]['status']
4472 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
4473 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
4474 # # 2.1. Update in openmano DB the VMs whose status changed
4476 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
4477 # vms_notupdated.remove(vm["uuid"])
4479 # vms_updated.append(vm["uuid"])
4480 # except db_base_Exception as e:
4481 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
4482 # # 2.2. Update in openmano DB the interface VMs
4483 # for interface in interfaces:
4484 # #translate from vim_net_id to instance_net_id
4485 # network_id_list=[]
4486 # for net in instanceDict['nets']:
4487 # if net["vim_net_id"] == interface["vim_net_id"]:
4488 # network_id_list.append(net["uuid"])
4489 # if not network_id_list:
4491 # del interface["vim_net_id"]
4493 # for network_id in network_id_list:
4494 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
4495 # except db_base_Exception as e:
4496 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
4498 # # 3. Getting the status of all nets
4500 # for datacenter_key in myvims:
4501 # if not net_list.get(datacenter_key):
4504 # failed_message = ""
4505 # if not myvims[datacenter_key]:
4506 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
4509 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
4511 # except vimconn.vimconnException as e:
4512 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
4513 # failed_message = str(e)
4515 # for net in net_list[datacenter_key]:
4516 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
4518 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
4519 # # TODO: update nets inside a vnf
4520 # for net in instanceDict['nets']:
4521 # net_id = net['vim_net_id']
4522 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
4523 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
4524 # 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'):
4525 # net['status'] = net_dict[net_id]['status']
4526 # net['error_msg'] = net_dict[net_id].get('error_msg')
4527 # net['vim_info'] = net_dict[net_id].get('vim_info')
4528 # # 5.1. Update in openmano DB the nets whose status changed
4530 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
4531 # nets_notupdated.remove(net["uuid"])
4533 # nets_updated.append(net["uuid"])
4534 # except db_base_Exception as e:
4535 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
4537 # # Returns appropriate output
4538 # #print "nfvo.refresh_instance finishes"
4539 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
4540 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
4541 instance_id
= instanceDict
['uuid']
4542 # if len(vms_notupdated)+len(nets_notupdated)>0:
4543 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
4544 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
4546 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
4548 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
4549 #print "Checking that the instance_id exists and getting the instance dictionary"
4550 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
4551 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
4553 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
4554 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
4556 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), httperrors
.Not_Found
)
4557 myvim
= vims
.values()[0]
4562 myvim_threads_id
= {}
4563 if action_dict
.get("vdu-scaling"):
4564 db_instance_vms
= []
4566 db_instance_interfaces
= []
4567 instance_action_id
= get_task_id()
4568 db_instance_action
= {
4569 "uuid": instance_action_id
, # same uuid for the instance and the action on create
4570 "tenant_id": nfvo_tenant
,
4571 "instance_id": instance_id
,
4572 "description": "SCALE",
4574 vm_result
["instance_action_id"] = instance_action_id
4575 vm_result
["created"] = []
4576 vm_result
["deleted"] = []
4578 for vdu
in action_dict
["vdu-scaling"]:
4579 vdu_id
= vdu
.get("vdu-id")
4580 osm_vdu_id
= vdu
.get("osm_vdu_id")
4581 member_vnf_index
= vdu
.get("member-vnf-index")
4582 vdu_count
= vdu
.get("count", 1)
4584 target_vms
= mydb
.get_rows(
4585 FROM
="instance_vms as vms join instance_vnfs as vnfs on vms.instance_vnf_id=vnfs.uuid",
4586 WHERE
={"vms.uuid": vdu_id
},
4587 ORDER_BY
="vms.created_at"
4590 raise NfvoException("Cannot find the vdu with id {}".format(vdu_id
), httperrors
.Not_Found
)
4592 if not osm_vdu_id
and not member_vnf_index
:
4593 raise NfvoException("Invalid input vdu parameters. Must supply either 'vdu-id' of 'osm_vdu_id','member-vnf-index'")
4594 target_vms
= mydb
.get_rows(
4595 # SELECT=("ivms.uuid", "ivnfs.datacenter_id", "ivnfs.datacenter_tenant_id"),
4596 FROM
="instance_vms as ivms join instance_vnfs as ivnfs on ivms.instance_vnf_id=ivnfs.uuid"\
4597 " join sce_vnfs as svnfs on ivnfs.sce_vnf_id=svnfs.uuid"\
4598 " join vms on ivms.vm_id=vms.uuid",
4599 WHERE
={"vms.osm_id": osm_vdu_id
, "svnfs.member_vnf_index": member_vnf_index
,
4600 "ivnfs.instance_scenario_id": instance_id
},
4601 ORDER_BY
="ivms.created_at"
4604 raise NfvoException("Cannot find the vdu with osm_vdu_id {} and member-vnf-index {}".format(osm_vdu_id
, member_vnf_index
), httperrors
.Not_Found
)
4605 vdu_id
= target_vms
[-1]["uuid"]
4606 target_vm
= target_vms
[-1]
4607 datacenter
= target_vm
["datacenter_id"]
4608 myvim_threads_id
[datacenter
], _
= get_vim_thread(mydb
, nfvo_tenant
, datacenter
)
4610 if vdu
["type"] == "delete":
4611 for index
in range(0, vdu_count
):
4612 target_vm
= target_vms
[-1-index
]
4613 vdu_id
= target_vm
["uuid"]
4615 vm_interfaces
= None
4616 for sce_vnf
in instanceDict
['vnfs']:
4617 for vm
in sce_vnf
['vms']:
4618 if vm
["uuid"] == vdu_id
:
4619 # TODO revise this should not be vm["uuid"] instance_vms["vm_id"]
4620 vm_interfaces
= vm
["interfaces"]
4624 "instance_action_id": instance_action_id
,
4625 "task_index": task_index
,
4626 "datacenter_vim_id": target_vm
["datacenter_tenant_id"],
4628 "status": "SCHEDULED",
4629 "item": "instance_vms",
4631 "related": target_vm
["related"],
4632 "extra": yaml
.safe_dump({"params": vm_interfaces
},
4633 default_flow_style
=True, width
=256)
4636 db_vim_actions
.append(db_vim_action
)
4637 vm_result
["deleted"].append(vdu_id
)
4638 # delete from database
4639 db_instance_vms
.append({"TO-DELETE": vdu_id
})
4641 else: # vdu["type"] == "create":
4643 where
= {"item": "instance_vms", "item_id": target_vm
["uuid"], "action": "CREATE"}
4645 vim_action_to_clone
= mydb
.get_rows(FROM
="vim_wim_actions", WHERE
=where
)
4646 if not vim_action_to_clone
:
4647 raise NfvoException("Cannot find the vim_action at database with {}".format(where
), httperrors
.Internal_Server_Error
)
4648 vim_action_to_clone
= vim_action_to_clone
[0]
4649 extra
= yaml
.safe_load(vim_action_to_clone
["extra"])
4651 # generate a new depends_on. Convert format TASK-Y into new format TASK-ACTION-XXXX.XXXX.Y
4652 # TODO do the same for flavor and image when available
4653 task_depends_on
= []
4654 task_params
= extra
["params"]
4655 task_params_networks
= deepcopy(task_params
[5])
4656 for iface
in task_params
[5]:
4657 if iface
["net_id"].startswith("TASK-"):
4658 if "." not in iface
["net_id"]:
4659 task_depends_on
.append("{}.{}".format(vim_action_to_clone
["instance_action_id"],
4660 iface
["net_id"][5:]))
4661 iface
["net_id"] = "TASK-{}.{}".format(vim_action_to_clone
["instance_action_id"],
4662 iface
["net_id"][5:])
4664 task_depends_on
.append(iface
["net_id"][5:])
4665 if "mac_address" in iface
:
4666 del iface
["mac_address"]
4668 vm_ifaces_to_clone
= mydb
.get_rows(FROM
="instance_interfaces", WHERE
={"instance_vm_id": target_vm
["uuid"]})
4669 for index
in range(0, vdu_count
):
4670 vm_uuid
= str(uuid4())
4671 vm_name
= target_vm
.get('vim_name')
4673 suffix
= vm_name
.rfind("-")
4674 vm_name
= vm_name
[:suffix
+1] + str(index
+ 1 + int(vm_name
[suffix
+1:]))
4680 'instance_vnf_id': target_vm
['instance_vnf_id'],
4681 'vm_id': target_vm
['vm_id'],
4682 'vim_name': vm_name
,
4684 db_instance_vms
.append(db_instance_vm
)
4686 for vm_iface
in vm_ifaces_to_clone
:
4687 iface_uuid
= str(uuid4())
4688 iface2iface
[vm_iface
["uuid"]] = iface_uuid
4691 'instance_vm_id': vm_uuid
,
4692 "instance_net_id": vm_iface
["instance_net_id"],
4693 'interface_id': vm_iface
['interface_id'],
4694 'type': vm_iface
['type'],
4695 'floating_ip': vm_iface
['floating_ip'],
4696 'port_security': vm_iface
['port_security']
4698 db_instance_interfaces
.append(db_vm_iface
)
4699 task_params_copy
= deepcopy(task_params
)
4700 for iface
in task_params_copy
[5]:
4701 iface
["uuid"] = iface2iface
[iface
["uuid"]]
4702 # increment ip_address
4703 if "ip_address" in iface
:
4704 ip
= iface
.get("ip_address")
4709 ip
= ip
[i
:] + str(int(ip
[:i
]) + 1)
4710 iface
["ip_address"] = ip
4712 iface
["ip_address"] = None
4714 task_params_copy
[0] = vm_name
4716 "instance_action_id": instance_action_id
,
4717 "task_index": task_index
,
4718 "datacenter_vim_id": vim_action_to_clone
["datacenter_vim_id"],
4720 "status": "SCHEDULED",
4721 "item": "instance_vms",
4726 # TODO examinar parametros, quitar MAC o incrementar. Incrementar IP y colocar las dependencias con ACTION-asdfasd.
4729 "extra": yaml
.safe_dump({"params": task_params_copy
, "depends_on": task_depends_on
}, default_flow_style
=True, width
=256)
4732 db_vim_actions
.append(db_vim_action
)
4733 vm_result
["created"].append(vm_uuid
)
4735 db_instance_action
["number_tasks"] = task_index
4737 {"instance_vms": db_instance_vms
},
4738 {"instance_interfaces": db_instance_interfaces
},
4739 {"instance_actions": db_instance_action
},
4741 # {"instance_sfis": db_instance_sfis},
4742 # {"instance_sfs": db_instance_sfs},
4743 # {"instance_classifications": db_instance_classifications},
4744 # {"instance_sfps": db_instance_sfps},
4745 {"vim_wim_actions": db_vim_actions
}
4747 logger
.debug("create_vdu done DB tables: %s",
4748 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
4749 mydb
.new_rows(db_tables
, [])
4750 for myvim_thread
in myvim_threads_id
.values():
4751 vim_threads
["running"][myvim_thread
].insert_task(db_vim_actions
)
4755 input_vnfs
= action_dict
.pop("vnfs", [])
4756 input_vms
= action_dict
.pop("vms", [])
4757 action_over_all
= True if not input_vnfs
and not input_vms
else False
4758 for sce_vnf
in instanceDict
['vnfs']:
4759 for vm
in sce_vnf
['vms']:
4760 if not action_over_all
and sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
4761 sce_vnf
['member_vnf_index'] not in input_vnfs
and \
4762 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
4765 if "add_public_key" in action_dict
:
4767 if sce_vnf
.get('mgmt_access'):
4768 mgmt_access
= yaml
.load(sce_vnf
['mgmt_access'])
4769 ssh_access
= mgmt_access
['config-access']['ssh-access']
4770 tenant
= mydb
.get_rows_by_id('nfvo_tenants', nfvo_tenant
)
4772 if ssh_access
['required'] and ssh_access
['default-user']:
4773 if 'ip_address' in vm
:
4774 mgmt_ip
= vm
['ip_address'].split(';')
4775 password
= mgmt_access
['config-access'].get('password')
4776 priv_RO_key
= decrypt_key(tenant
[0]['encrypted_RO_priv_key'], tenant
[0]['uuid'])
4777 myvim
.inject_user_key(mgmt_ip
[0], ssh_access
['default-user'],
4778 action_dict
['add_public_key'],
4779 password
=password
, ro_key
=priv_RO_key
)
4781 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4782 httperrors
.Internal_Server_Error
)
4784 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4785 httperrors
.Internal_Server_Error
)
4787 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4788 httperrors
.Internal_Server_Error
)
4790 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
4791 if "console" in action_dict
:
4792 if not global_config
["http_console_proxy"]:
4793 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4794 "description": "{protocol}//{ip}:{port}/{suffix}".format(
4795 protocol
=data
["protocol"],
4796 ip
= data
["server"],
4797 port
= data
["port"],
4798 suffix
= data
["suffix"]),
4802 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
4803 vm_result
[ vm
['uuid'] ] = {"vim_result": -httperrors
.Unauthorized
,
4804 "description": "this console is only reachable by local interface",
4809 #print "console data", data
4811 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
4812 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4813 "description": "{protocol}//{ip}:{port}/{suffix}".format(
4814 protocol
=data
["protocol"],
4815 ip
= global_config
["http_console_host"],
4816 port
= console_thread
.port
,
4817 suffix
= data
["suffix"]),
4821 except NfvoException
as e
:
4822 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
4826 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
4828 except vimconn
.vimconnException
as e
:
4829 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
4832 if vm_ok
==0: #all goes wrong
4837 def instance_action_get(mydb
, nfvo_tenant
, instance_id
, action_id
):
4839 if nfvo_tenant
and nfvo_tenant
!= "any":
4840 filter["tenant_id"] = nfvo_tenant
4841 if instance_id
and instance_id
!= "any":
4842 filter["instance_id"] = instance_id
4844 filter["uuid"] = action_id
4845 rows
= mydb
.get_rows(FROM
="instance_actions", WHERE
=filter)
4848 raise NfvoException("Not found any action with this criteria", httperrors
.Not_Found
)
4849 vim_wim_actions
= mydb
.get_rows(FROM
="vim_wim_actions", WHERE
={"instance_action_id": action_id
})
4850 rows
[0]["vim_wim_actions"] = vim_wim_actions
4851 # for backward compatibility set vim_actions = vim_wim_actions
4852 rows
[0]["vim_actions"] = vim_wim_actions
4853 return {"actions": rows
}
4856 def create_or_use_console_proxy_thread(console_server
, console_port
):
4857 #look for a non-used port
4858 console_thread_key
= console_server
+ ":" + str(console_port
)
4859 if console_thread_key
in global_config
["console_thread"]:
4860 #global_config["console_thread"][console_thread_key].start_timeout()
4861 return global_config
["console_thread"][console_thread_key
]
4863 for port
in global_config
["console_port_iterator"]():
4864 #print "create_or_use_console_proxy_thread() port:", port
4865 if port
in global_config
["console_ports"]:
4868 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
4870 global_config
["console_thread"][console_thread_key
] = clithread
4871 global_config
["console_ports"][port
] = console_thread_key
4873 except cli
.ConsoleProxyExceptionPortUsed
as e
:
4874 #port used, try with onoher
4876 except cli
.ConsoleProxyException
as e
:
4877 raise NfvoException(str(e
), httperrors
.Bad_Request
)
4878 raise NfvoException("Not found any free 'http_console_ports'", httperrors
.Conflict
)
4881 def check_tenant(mydb
, tenant_id
):
4882 '''check that tenant exists at database'''
4883 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
4885 raise NfvoException("tenant '{}' not found".format(tenant_id
), httperrors
.Not_Found
)
4888 def new_tenant(mydb
, tenant_dict
):
4890 tenant_uuid
= str(uuid4())
4891 tenant_dict
['uuid'] = tenant_uuid
4893 pub_key
, priv_key
= create_RO_keypair(tenant_uuid
)
4894 tenant_dict
['RO_pub_key'] = pub_key
4895 tenant_dict
['encrypted_RO_priv_key'] = priv_key
4896 mydb
.new_row("nfvo_tenants", tenant_dict
, confidential_data
=True)
4897 except db_base_Exception
as e
:
4898 raise NfvoException("Error creating the new tenant: {} ".format(tenant_dict
['name']) + str(e
), e
.http_code
)
4901 def delete_tenant(mydb
, tenant
):
4902 #get nfvo_tenant info
4904 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
4905 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
4906 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
4909 def new_datacenter(mydb
, datacenter_descriptor
):
4910 sdn_port_mapping
= None
4911 if "config" in datacenter_descriptor
:
4912 sdn_port_mapping
= datacenter_descriptor
["config"].pop("sdn-port-mapping", None)
4913 datacenter_descriptor
["config"] = yaml
.safe_dump(datacenter_descriptor
["config"], default_flow_style
=True,
4915 # Check that datacenter-type is correct
4916 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
4917 # module_info = None
4919 module
= "vimconn_" + datacenter_type
4920 pkg
= __import__("osm_ro." + module
)
4921 # vim_conn = getattr(pkg, module)
4922 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
4923 except (IOError, ImportError):
4924 # if module_info and module_info[0]:
4925 # file.close(module_info[0])
4926 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}.py' not installed".format(datacenter_type
,
4928 httperrors
.Bad_Request
)
4930 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True, confidential_data
=True)
4931 if sdn_port_mapping
:
4933 datacenter_sdn_port_mapping_set(mydb
, None, datacenter_id
, sdn_port_mapping
)
4934 except Exception as e
:
4935 mydb
.delete_row_by_id("datacenters", datacenter_id
) # Rollback
4937 return datacenter_id
4940 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
4941 # obtain data, check that only one exist
4942 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
4945 datacenter_id
= datacenter
['uuid']
4946 where
= {'uuid': datacenter
['uuid']}
4947 remove_port_mapping
= False
4948 new_sdn_port_mapping
= None
4949 if "config" in datacenter_descriptor
:
4950 if datacenter_descriptor
['config'] != None:
4952 new_config_dict
= datacenter_descriptor
["config"]
4953 if "sdn-port-mapping" in new_config_dict
:
4954 remove_port_mapping
= True
4955 new_sdn_port_mapping
= new_config_dict
.pop("sdn-port-mapping")
4956 # delete null fields
4958 for k
in new_config_dict
:
4959 if new_config_dict
[k
] is None:
4961 if k
== 'sdn-controller':
4962 remove_port_mapping
= True
4964 config_text
= datacenter
.get("config")
4967 config_dict
= yaml
.load(config_text
)
4968 config_dict
.update(new_config_dict
)
4969 # delete null fields
4972 except Exception as e
:
4973 raise NfvoException("Bad format at datacenter:config " + str(e
), httperrors
.Bad_Request
)
4975 datacenter_descriptor
["config"] = yaml
.safe_dump(config_dict
, default_flow_style
=True, width
=256)
4977 datacenter_descriptor
["config"] = None
4978 if remove_port_mapping
:
4980 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_id
)
4981 except ovimException
as e
:
4982 raise NfvoException("Error deleting datacenter-port-mapping " + str(e
), httperrors
.Conflict
)
4984 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
4985 if new_sdn_port_mapping
:
4987 datacenter_sdn_port_mapping_set(mydb
, None, datacenter_id
, new_sdn_port_mapping
)
4988 except ovimException
as e
:
4990 mydb
.update_rows('datacenters', datacenter
, where
)
4991 raise NfvoException("Error adding datacenter-port-mapping " + str(e
), httperrors
.Conflict
)
4992 return datacenter_id
4995 def delete_datacenter(mydb
, datacenter
):
4996 #get nfvo_tenant info
4997 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
4998 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
5000 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_dict
['uuid'])
5001 except ovimException
as e
:
5002 raise NfvoException("Error deleting datacenter-port-mapping " + str(e
))
5003 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
5006 def create_vim_account(mydb
, nfvo_tenant
, datacenter_id
, name
=None, vim_id
=None, vim_tenant
=None, vim_tenant_name
=None,
5007 vim_username
=None, vim_password
=None, config
=None):
5008 # get datacenter info
5010 if not datacenter_id
:
5012 raise NfvoException("You must provide 'vim_id", http_code
=httperrors
.Bad_Request
)
5013 datacenter_id
= vim_id
5014 datacenter_id
, datacenter_name
= get_datacenter_uuid(mydb
, None, datacenter_id
)
5016 create_vim_tenant
= True if not vim_tenant
and not vim_tenant_name
else False
5018 # get nfvo_tenant info
5019 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
5020 if vim_tenant_name
==None:
5021 vim_tenant_name
=tenant_dict
['name']
5023 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
5024 # #check that this association does not exist before
5025 # tenants_datacenters = mydb.get_rows(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict)
5026 # if len(tenants_datacenters)>0:
5027 # raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id, tenant_dict['uuid']), httperrors.Conflict)
5029 vim_tenant_id_exist_atdb
=False
5030 if not create_vim_tenant
:
5031 where_
={"datacenter_id": datacenter_id
}
5032 if vim_tenant
!=None:
5033 where_
["vim_tenant_id"] = vim_tenant
5034 if vim_tenant_name
!=None:
5035 where_
["vim_tenant_name"] = vim_tenant_name
5036 #check if vim_tenant_id is already at database
5037 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
5038 if len(datacenter_tenants_dict
)>=1:
5039 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
5040 vim_tenant_id_exist_atdb
=True
5041 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
5043 datacenter_tenants_dict
= {}
5044 #insert at table datacenter_tenants
5045 else: #if vim_tenant==None:
5046 #create tenant at VIM if not provided
5048 _
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
, vim_user
=vim_username
,
5049 vim_passwd
=vim_password
)
5050 datacenter_name
= myvim
["name"]
5051 vim_tenant
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
5052 except vimconn
.vimconnException
as e
:
5053 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), httperrors
.Internal_Server_Error
)
5054 datacenter_tenants_dict
= {}
5055 datacenter_tenants_dict
["created"]="true"
5057 #fill datacenter_tenants table
5058 if not vim_tenant_id_exist_atdb
:
5059 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant
5060 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
5061 datacenter_tenants_dict
["user"] = vim_username
5062 datacenter_tenants_dict
["passwd"] = vim_password
5063 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
5065 datacenter_tenants_dict
["name"] = name
5067 datacenter_tenants_dict
["name"] = datacenter_name
5069 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
5070 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True, confidential_data
=True)
5071 datacenter_tenants_dict
["uuid"] = id_
5073 #fill tenants_datacenters table
5074 datacenter_tenant_id
= datacenter_tenants_dict
["uuid"]
5075 tenants_datacenter_dict
["datacenter_tenant_id"] = datacenter_tenant_id
5076 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
5079 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
5080 new_thread
= vim_thread
.vim_thread(task_lock
, thread_name
, datacenter_name
, datacenter_tenant_id
,
5081 db
=db
, db_lock
=db_lock
, ovim
=ovim
)
5083 thread_id
= datacenter_tenants_dict
["uuid"]
5084 vim_threads
["running"][thread_id
] = new_thread
5086 except vimconn
.vimconnException
as e
:
5087 raise NfvoException(str(e
), httperrors
.Bad_Request
)
5090 def edit_vim_account(mydb
, nfvo_tenant
, datacenter_tenant_id
, datacenter_id
=None, name
=None, vim_tenant
=None,
5091 vim_tenant_name
=None, vim_username
=None, vim_password
=None, config
=None):
5093 # get vim_account; check is valid for this tenant
5094 from_
= "datacenter_tenants as dt JOIN tenants_datacenters as td ON dt.uuid=td.datacenter_tenant_id"
5095 where_
= {"td.nfvo_tenant_id": nfvo_tenant
}
5096 if datacenter_tenant_id
:
5097 where_
["dt.uuid"] = datacenter_tenant_id
5099 where_
["dt.datacenter_id"] = datacenter_id
5100 vim_accounts
= mydb
.get_rows(SELECT
="dt.uuid as uuid, config", FROM
=from_
, WHERE
=where_
)
5101 if not vim_accounts
:
5102 raise NfvoException("vim_account not found for this tenant", http_code
=httperrors
.Not_Found
)
5103 elif len(vim_accounts
) > 1:
5104 raise NfvoException("found more than one vim_account for this tenant", http_code
=httperrors
.Conflict
)
5105 datacenter_tenant_id
= vim_accounts
[0]["uuid"]
5106 original_config
= vim_accounts
[0]["config"]
5110 original_config_dict
= yaml
.load(original_config
)
5111 original_config_dict
.update(config
)
5112 update
["config"] = yaml
.safe_dump(original_config_dict
, default_flow_style
=True, width
=256)
5114 update_
['name'] = name
5116 update_
['vim_tenant_id'] = vim_tenant
5118 update_
['vim_tenant_name'] = vim_tenant_name
5120 update_
['user'] = vim_username
5122 update_
['passwd'] = vim_password
5124 mydb
.update_rows("datacenter_tenants", UPDATE
=update_
, WHERE
={"uuid": datacenter_tenant_id
})
5126 vim_threads
["running"][datacenter_tenant_id
].insert_task("reload")
5127 return datacenter_tenant_id
5129 def delete_vim_account(mydb
, tenant_id
, vim_account_id
, datacenter
=None):
5130 #get nfvo_tenant info
5131 if not tenant_id
or tenant_id
=="any":
5134 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
5135 tenant_uuid
= tenant_dict
['uuid']
5137 #check that this association exist before
5138 tenants_datacenter_dict
= {}
5140 datacenter_id
, _
= get_datacenter_uuid(mydb
, tenant_uuid
, datacenter
)
5141 tenants_datacenter_dict
["datacenter_id"] = datacenter_id
5142 elif vim_account_id
:
5143 tenants_datacenter_dict
["datacenter_tenant_id"] = vim_account_id
5145 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
5146 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
5147 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
5148 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), httperrors
.Not_Found
)
5150 #delete this association
5151 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
5153 #get vim_tenant info and deletes
5155 for tenant_datacenter_item
in tenant_datacenter_list
:
5156 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
5157 #try to delete vim:tenant
5159 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
5160 if vim_tenant_dict
['created']=='true':
5161 #delete tenant at VIM if created by NFVO
5163 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5164 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
5165 except vimconn
.vimconnException
as e
:
5166 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
5167 logger
.warn(warning
)
5168 except db_base_Exception
as e
:
5169 logger
.error("Cannot delete datacenter_tenants " + str(e
))
5170 pass # the error will be caused because dependencies, vim_tenant can not be deleted
5171 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
5172 thread
= vim_threads
["running"].get(thread_id
)
5174 thread
.insert_task("exit")
5175 vim_threads
["deleting"][thread_id
] = thread
5176 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
5179 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
5181 #get datacenter info
5182 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5184 if 'net-update' in action_dict
:
5186 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
5188 except vimconn
.vimconnException
as e
:
5189 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
5190 raise NfvoException(str(e
), httperrors
.Internal_Server_Error
)
5191 #update nets Change from VIM format to NFVO format
5194 net_nfvo
={'datacenter_id': datacenter_id
}
5195 net_nfvo
['name'] = net
['name']
5196 #net_nfvo['description']= net['name']
5197 net_nfvo
['vim_net_id'] = net
['id']
5198 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
5199 net_nfvo
['shared'] = net
['shared']
5200 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
5201 net_list
.append(net_nfvo
)
5202 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
5203 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
5205 elif 'net-edit' in action_dict
:
5206 net
= action_dict
['net-edit'].pop('net')
5207 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
5208 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
5209 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
5211 elif 'net-delete' in action_dict
:
5212 net
= action_dict
['net-deelte'].get('net')
5213 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
5214 result
= mydb
.delete_row(FROM
='datacenter_nets',
5215 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
5219 raise NfvoException("Unknown action " + str(action_dict
), httperrors
.Bad_Request
)
5222 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
5223 #get datacenter info
5224 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5226 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
5227 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
5228 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
5232 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
5233 #get datacenter info
5234 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5237 action_dict
= action_dict
["netmap"]
5238 if 'vim_id' in action_dict
:
5239 filter_dict
["id"] = action_dict
['vim_id']
5240 if 'vim_name' in action_dict
:
5241 filter_dict
["name"] = action_dict
['vim_name']
5243 filter_dict
["shared"] = True
5246 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
5247 except vimconn
.vimconnException
as e
:
5248 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
5249 raise NfvoException(str(e
), httperrors
.Internal_Server_Error
)
5250 if len(vim_nets
)>1 and action_dict
:
5251 raise NfvoException("more than two networks found, specify with vim_id", httperrors
.Conflict
)
5252 elif len(vim_nets
)==0: # and action_dict:
5253 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), httperrors
.Not_Found
)
5255 for net
in vim_nets
:
5256 net_nfvo
={'datacenter_id': datacenter_id
}
5257 if action_dict
and "name" in action_dict
:
5258 net_nfvo
['name'] = action_dict
['name']
5260 net_nfvo
['name'] = net
['name']
5261 #net_nfvo['description']= net['name']
5262 net_nfvo
['vim_net_id'] = net
['id']
5263 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
5264 net_nfvo
['shared'] = net
['shared']
5265 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
5267 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
5268 net_nfvo
["status"] = "OK"
5269 net_nfvo
["uuid"] = net_id
5270 except db_base_Exception
as e
:
5274 net_nfvo
["status"] = "FAIL: " + str(e
)
5275 net_list
.append(net_nfvo
)
5278 def get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
):
5279 # obtain all network data
5281 if utils
.check_valid_uuid(network_id
):
5282 filter_dict
= {"id": network_id
}
5284 filter_dict
= {"name": network_id
}
5286 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5287 network
= myvim
.get_network_list(filter_dict
=filter_dict
)
5288 except vimconn
.vimconnException
as e
:
5289 raise NfvoException("Not possible to get_sdn_net_id from VIM: {}".format(str(e
)), e
.http_code
)
5291 # ensure the network is defined
5292 if len(network
) == 0:
5293 raise NfvoException("Network {} is not present in the system".format(network_id
),
5294 httperrors
.Bad_Request
)
5296 # ensure there is only one network with the provided name
5297 if len(network
) > 1:
5298 raise NfvoException("Multiple networks present in vim identified by {}".format(network_id
), httperrors
.Bad_Request
)
5300 # ensure it is a dataplane network
5301 if network
[0]['type'] != 'data':
5304 # ensure we use the id
5305 network_id
= network
[0]['id']
5307 # search in dabase mano_db in table instance nets for the sdn_net_id that corresponds to the vim_net_id==network_id
5308 # and with instance_scenario_id==NULL
5309 #search_dict = {'vim_net_id': network_id, 'instance_scenario_id': None}
5310 search_dict
= {'vim_net_id': network_id
}
5313 #sdn_network_id = mydb.get_rows(SELECT=('sdn_net_id',), FROM='instance_nets', WHERE=search_dict)[0]['sdn_net_id']
5314 result
= mydb
.get_rows(SELECT
=('sdn_net_id',), FROM
='instance_nets', WHERE
=search_dict
)
5315 except db_base_Exception
as e
:
5316 raise NfvoException("db_base_Exception obtaining SDN network to associated to vim network {}".format(
5317 network_id
) + str(e
), e
.http_code
)
5321 if net
['sdn_net_id'] != None:
5323 sdn_net_id
= net
['sdn_net_id']
5325 if sdn_net_counter
== 0:
5327 elif sdn_net_counter
== 1:
5330 raise NfvoException("More than one SDN network is associated to vim network {}".format(
5331 network_id
), httperrors
.Internal_Server_Error
)
5333 def get_sdn_controller_id(mydb
, datacenter
):
5334 # Obtain sdn controller id
5335 config
= mydb
.get_rows(SELECT
=('config',), FROM
='datacenters', WHERE
={'uuid': datacenter
})[0].get('config', '{}')
5339 return yaml
.load(config
).get('sdn-controller')
5341 def vim_net_sdn_attach(mydb
, tenant_id
, datacenter
, network_id
, descriptor
):
5343 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
5344 if not sdn_network_id
:
5345 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
), httperrors
.Internal_Server_Error
)
5347 #Obtain sdn controller id
5348 controller_id
= get_sdn_controller_id(mydb
, datacenter
)
5349 if not controller_id
:
5350 raise NfvoException("No SDN controller is set for datacenter {}".format(datacenter
), httperrors
.Internal_Server_Error
)
5352 #Obtain sdn controller info
5353 sdn_controller
= ovim
.show_of_controller(controller_id
)
5356 'name': 'external_port',
5357 'net_id': sdn_network_id
,
5358 'ofc_id': controller_id
,
5359 'switch_dpid': sdn_controller
['dpid'],
5360 'switch_port': descriptor
['port']
5363 if 'vlan' in descriptor
:
5364 port_data
['vlan'] = descriptor
['vlan']
5365 if 'mac' in descriptor
:
5366 port_data
['mac'] = descriptor
['mac']
5368 result
= ovim
.new_port(port_data
)
5369 except ovimException
as e
:
5370 raise NfvoException("ovimException attaching SDN network {} to vim network {}".format(
5371 sdn_network_id
, network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5372 except db_base_Exception
as e
:
5373 raise NfvoException("db_base_Exception attaching SDN network to vim network {}".format(
5374 network_id
) + str(e
), e
.http_code
)
5376 return 'Port uuid: '+ result
5378 def vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, network_id
, port_id
=None):
5380 filter = {'uuid': port_id
}
5382 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
5383 if not sdn_network_id
:
5384 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
),
5385 httperrors
.Internal_Server_Error
)
5386 #in case no port_id is specified only ports marked as 'external_port' will be detached
5387 filter = {'name': 'external_port', 'net_id': sdn_network_id
}
5390 port_list
= ovim
.get_ports(columns
={'uuid'}, filter=filter)
5391 except ovimException
as e
:
5392 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
5393 httperrors
.Internal_Server_Error
)
5395 if len(port_list
) == 0:
5396 raise NfvoException("No ports attached to the network {} were found with the requested criteria".format(network_id
),
5397 httperrors
.Bad_Request
)
5400 for port
in port_list
:
5402 port_uuid_list
.append(port
['uuid'])
5403 ovim
.delete_port(port
['uuid'])
5404 except ovimException
as e
:
5405 raise NfvoException("ovimException deleting port {} for net {}. ".format(port
['uuid'], network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5407 return 'Detached ports uuid: {}'.format(','.join(port_uuid_list
))
5409 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
5410 #get datacenter info
5411 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5414 if utils
.check_valid_uuid(name
):
5415 filter_dict
["id"] = name
5417 filter_dict
["name"] = name
5419 if item
=="networks":
5420 #filter_dict['tenant_id'] = myvim['tenant_id']
5421 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
5423 if len(content
) == 0:
5424 raise NfvoException("Network {} is not present in the system. ".format(name
),
5425 httperrors
.Bad_Request
)
5427 #Update the networks with the attached ports
5429 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, net
['id'])
5430 if sdn_network_id
!= None:
5432 #port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan'}, filter={'name': 'external_port', 'net_id': sdn_network_id})
5433 port_list
= ovim
.get_ports(columns
={'uuid', 'switch_port', 'vlan','name'}, filter={'net_id': sdn_network_id
})
5434 except ovimException
as e
:
5435 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5436 #Remove field name and if port name is external_port save it as 'type'
5437 for port
in port_list
:
5438 if port
['name'] == 'external_port':
5439 port
['type'] = "External"
5441 net
['sdn_network_id'] = sdn_network_id
5442 net
['sdn_attached_ports'] = port_list
5444 elif item
=="tenants":
5445 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
5446 elif item
== "images":
5448 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
5450 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5451 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
5452 if name
and len(content
)==1:
5453 return {item
[:-1]: content
[0]}
5454 elif name
and len(content
)==0:
5455 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
5458 return {item
: content
}
5459 except vimconn
.vimconnException
as e
:
5460 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
5461 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
5464 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
5465 #get datacenter info
5466 if tenant_id
== "any":
5469 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5471 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
5472 logger
.debug("vim_action_delete vim response: " + str(content
))
5473 items
= content
.values()[0]
5474 if type(items
)==list and len(items
)==0:
5475 raise NfvoException("Not found " + item
, httperrors
.Not_Found
)
5476 elif type(items
)==list and len(items
)>1:
5477 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), httperrors
.Not_Found
)
5478 else: # it is a dict
5479 item_id
= items
["id"]
5480 item_name
= str(items
.get("name"))
5483 if item
=="networks":
5484 # If there is a SDN network associated to the vim-network, proceed to clear the relationship and delete it
5485 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, item_id
)
5486 if sdn_network_id
!= None:
5487 #Delete any port attachment to this network
5489 port_list
= ovim
.get_ports(columns
={'uuid'}, filter={'net_id': sdn_network_id
})
5490 except ovimException
as e
:
5491 raise NfvoException(
5492 "ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
5493 httperrors
.Internal_Server_Error
)
5495 # By calling one by one all ports to be detached we ensure that not only the external_ports get detached
5496 for port
in port_list
:
5497 vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, item_id
, port
['uuid'])
5499 #Delete from 'instance_nets' the correspondence between the vim-net-id and the sdn-net-id
5501 mydb
.delete_row(FROM
='instance_nets', WHERE
={'instance_scenario_id': None, 'sdn_net_id': sdn_network_id
, 'vim_net_id': item_id
})
5502 except db_base_Exception
as e
:
5503 raise NfvoException("Error deleting correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
5504 str(e
), e
.http_code
)
5506 #Delete the SDN network
5508 ovim
.delete_network(sdn_network_id
)
5509 except ovimException
as e
:
5510 logger
.error("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
), exc_info
=True)
5511 raise NfvoException("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
),
5512 httperrors
.Internal_Server_Error
)
5514 content
= myvim
.delete_network(item_id
)
5515 elif item
=="tenants":
5516 content
= myvim
.delete_tenant(item_id
)
5517 elif item
== "images":
5518 content
= myvim
.delete_image(item_id
)
5520 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5521 except vimconn
.vimconnException
as e
:
5522 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
5523 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
5525 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
5528 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
5529 #get datacenter info
5530 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
5531 if tenant_id
== "any":
5533 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5535 if item
=="networks":
5536 net
= descriptor
["network"]
5537 net_name
= net
.pop("name")
5538 net_type
= net
.pop("type", "bridge")
5539 net_public
= net
.pop("shared", False)
5540 net_ipprofile
= net
.pop("ip_profile", None)
5541 net_vlan
= net
.pop("vlan", None)
5542 content
, _
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
5544 #If the datacenter has a SDN controller defined and the network is of dataplane type, then create the sdn network
5545 if get_sdn_controller_id(mydb
, datacenter
) != None and (net_type
== 'data' or net_type
== 'ptp'):
5546 #obtain datacenter_tenant_id
5547 datacenter_tenant_id
= mydb
.get_rows(SELECT
=('uuid',),
5548 FROM
='datacenter_tenants',
5549 WHERE
={'datacenter_id': datacenter
})[0]['uuid']
5552 sdn_network
['vlan'] = net_vlan
5553 sdn_network
['type'] = net_type
5554 sdn_network
['name'] = net_name
5555 sdn_network
['region'] = datacenter_tenant_id
5556 ovim_content
= ovim
.new_network(sdn_network
)
5557 except ovimException
as e
:
5558 logger
.error("ovimException creating SDN network={} ".format(
5559 sdn_network
) + str(e
), exc_info
=True)
5560 raise NfvoException("ovimException creating SDN network={} ".format(sdn_network
) + str(e
),
5561 httperrors
.Internal_Server_Error
)
5563 # Save entry in in dabase mano_db in table instance_nets to stablish a dictionary vim_net_id <->sdn_net_id
5564 # use instance_scenario_id=None to distinguish from real instaces of nets
5565 correspondence
= {'instance_scenario_id': None,
5566 'sdn_net_id': ovim_content
,
5567 'vim_net_id': content
,
5568 'datacenter_tenant_id': datacenter_tenant_id
5571 mydb
.new_row('instance_nets', correspondence
, add_uuid
=True)
5572 except db_base_Exception
as e
:
5573 raise NfvoException("Error saving correspondence for VIM/SDN dataplane networks{}: {}".format(
5574 correspondence
, e
), e
.http_code
)
5575 elif item
=="tenants":
5576 tenant
= descriptor
["tenant"]
5577 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
5579 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5580 except vimconn
.vimconnException
as e
:
5581 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
5583 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
5585 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
5586 data
= ovim
.new_of_controller(sdn_controller
)
5587 logger
.debug('New SDN controller created with uuid {}'.format(data
))
5590 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
5591 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
5592 msg
= 'SDN controller {} updated'.format(data
)
5596 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
5597 if controller_id
== None:
5598 data
= ovim
.get_of_controllers()
5600 data
= ovim
.show_of_controller(controller_id
)
5602 msg
= 'SDN controller list:\n {}'.format(data
)
5606 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
5607 select_
= ('uuid', 'config')
5608 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
5609 for datacenter
in datacenters
:
5610 if datacenter
['config']:
5611 config
= yaml
.load(datacenter
['config'])
5612 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
5613 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), httperrors
.Conflict
)
5615 data
= ovim
.delete_of_controller(controller_id
)
5616 msg
= 'SDN controller {} deleted'.format(data
)
5620 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
5621 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
5622 if len(controller
) < 1:
5623 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), httperrors
.Not_Found
)
5626 sdn_controller_id
= yaml
.load(controller
[0]["config"])["sdn-controller"]
5628 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), httperrors
.Bad_Request
)
5630 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
5631 switch_dpid
= sdn_controller
["dpid"]
5634 for compute_node
in sdn_port_mapping
:
5635 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
5637 element
["compute_node"] = compute_node
["compute_node"]
5638 for port
in compute_node
["ports"]:
5639 pci
= port
.get("pci")
5640 element
["switch_port"] = port
.get("switch_port")
5641 element
["switch_mac"] = port
.get("switch_mac")
5642 if not element
["switch_port"] and not element
["switch_mac"]:
5643 raise NfvoException ("The mapping must contain 'switch_port' or 'switch_mac'", httperrors
.Bad_Request
)
5644 for pci_expanded
in utils
.expand_brackets(pci
):
5645 element
["pci"] = pci_expanded
5646 maps
.append(dict(element
))
5648 return ovim
.set_of_port_mapping(maps
, ofc_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, region
=datacenter_id
)
5650 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
5651 maps
= ovim
.get_of_port_mappings(db_filter
={"region": datacenter_id
})
5654 "sdn-controller": None,
5655 "datacenter-id": datacenter_id
,
5657 "ports_mapping": list()
5660 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
5661 if datacenter
['config']:
5662 config
= yaml
.load(datacenter
['config'])
5663 if 'sdn-controller' in config
:
5664 controller_id
= config
['sdn-controller']
5665 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
5666 result
["sdn-controller"] = controller_id
5667 result
["dpid"] = sdn_controller
["dpid"]
5669 if result
["sdn-controller"] == None:
5670 raise NfvoException("SDN controller is not defined for datacenter {}".format(datacenter_id
), httperrors
.Bad_Request
)
5671 if result
["dpid"] == None:
5672 raise NfvoException("It was not possible to determine DPID for SDN controller {}".format(result
["sdn-controller"]),
5673 httperrors
.Internal_Server_Error
)
5678 ports_correspondence_dict
= dict()
5680 if result
["sdn-controller"] != link
["ofc_id"]:
5681 raise NfvoException("The sdn-controller specified for different port mappings differ", httperrors
.Internal_Server_Error
)
5682 if result
["dpid"] != link
["switch_dpid"]:
5683 raise NfvoException("The dpid specified for different port mappings differ", httperrors
.Internal_Server_Error
)
5685 element
["pci"] = link
["pci"]
5686 if link
["switch_port"]:
5687 element
["switch_port"] = link
["switch_port"]
5688 if link
["switch_mac"]:
5689 element
["switch_mac"] = link
["switch_mac"]
5691 if not link
["compute_node"] in ports_correspondence_dict
:
5693 content
["compute_node"] = link
["compute_node"]
5694 content
["ports"] = list()
5695 ports_correspondence_dict
[link
["compute_node"]] = content
5697 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
5699 for key
in sorted(ports_correspondence_dict
):
5700 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
5704 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
5705 return ovim
.clear_of_port_mapping(db_filter
={"region":datacenter_id
})
5707 def create_RO_keypair(tenant_id
):
5709 Creates a public / private keys for a RO tenant and returns their values
5711 tenant_id: ID of the tenant
5713 public_key: Public key for the RO tenant
5714 private_key: Encrypted private key for RO tenant
5718 key
= RSA
.generate(bits
)
5720 public_key
= key
.publickey().exportKey('OpenSSH')
5721 if isinstance(public_key
, ValueError):
5722 raise NfvoException("Unable to create public key: {}".format(public_key
), httperrors
.Internal_Server_Error
)
5723 private_key
= key
.exportKey(passphrase
=tenant_id
, pkcs
=8)
5724 except (ValueError, NameError) as e
:
5725 raise NfvoException("Unable to create private key: {}".format(e
), httperrors
.Internal_Server_Error
)
5726 return public_key
, private_key
5728 def decrypt_key (key
, tenant_id
):
5730 Decrypts an encrypted RSA key
5732 key: Private key to be decrypted
5733 tenant_id: ID of the tenant
5735 unencrypted_key: Unencrypted private key for RO tenant
5738 key
= RSA
.importKey(key
,tenant_id
)
5739 unencrypted_key
= key
.exportKey('PEM')
5740 if isinstance(unencrypted_key
, ValueError):
5741 raise NfvoException("Unable to decrypt the private key: {}".format(unencrypted_key
), httperrors
.Internal_Server_Error
)
5742 except ValueError as e
:
5743 raise NfvoException("Unable to decrypt the private key: {}".format(e
), httperrors
.Internal_Server_Error
)
5744 return unencrypted_key