1 # -*- coding: utf-8 -*-
4 # Copyright 2015 Telefonica Investigacion y Desarrollo, S.A.U.
5 # This file is part of openmano
8 # Licensed under the Apache License, Version 2.0 (the "License"); you may
9 # not use this file except in compliance with the License. You may obtain
10 # a copy of the License at
12 # http://www.apache.org/licenses/LICENSE-2.0
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17 # License for the specific language governing permissions and limitations
20 # For those usages not covered by the Apache License, Version 2.0 please
21 # contact with: nfvlabs@tid.es
25 NFVO engine, implementing all the methods for the creation, deletion and management of vnfs, scenarios and instances
27 __author__
="Alfonso Tierno, Gerardo Garcia, Pablo Montes"
28 __date__
="$16-sep-2014 22:05:01$"
34 from utils
import deprecated
36 import console_proxy_thread
as cli
41 from uuid
import uuid4
42 from db_base
import db_base_Exception
45 from threading
import Lock
47 from lib_osm_openvim
import ovim
as ovim_module
48 from lib_osm_openvim
.ovim
import ovimException
49 from Crypto
.PublicKey
import RSA
51 import osm_im
.vnfd
as vnfd_catalog
52 import osm_im
.nsd
as nsd_catalog
53 from pyangbind
.lib
.serialise
import pybindJSONDecoder
54 from copy
import deepcopy
58 import wim
.wimconn
as wimconn
59 import wim
.wim_thread
as wim_thread
60 from .http_tools
import errors
as httperrors
61 from .wim
.engine
import WimEngine
62 from .wim
.persistence
import WimPersistence
63 from copy
import deepcopy
64 from pprint
import pformat
68 global vimconn_imported
72 global wimconn_imported
75 global default_volume_size
76 default_volume_size
= '5' #size in GB
81 vimconn_imported
= {} # dictionary with VIM type as key, loaded module as value
82 vim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-VIMs
83 vim_persistent_info
= {}
85 wimconn_imported
= {} # dictionary with WIM type as key, loaded module as value
86 wim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-WIMs
87 wim_persistent_info
= {}
90 logger
= logging
.getLogger('openmano.nfvo')
97 class NfvoException(httperrors
.HttpMappedError
):
98 """Common Class for NFVO errors"""
104 if task_id
<= last_task_id
:
105 task_id
= last_task_id
+ 0.000001
106 last_task_id
= task_id
107 return "ACTION-{:.6f}".format(task_id
)
108 # return (t.strftime("%Y%m%dT%H%M%S.{}%Z", t.localtime(task_id))).format(int((task_id % 1)*1e6))
111 def new_task(name
, params
, depends
=None):
113 task_id
= get_task_id()
114 task
= {"status": "enqueued", "id": task_id
, "name": name
, "params": params
}
116 task
["depends"] = depends
121 return True if id[:5] == "TASK-" else False
124 def get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_name
, tenant_id
):
125 name
= datacenter_name
[:16]
126 if name
not in vim_threads
["names"]:
127 vim_threads
["names"].append(name
)
130 name
= datacenter_name
[:16] + "." + tenant_name
[:16]
131 if name
not in vim_threads
["names"]:
132 vim_threads
["names"].append(name
)
135 vim_threads
["names"].append(name
)
139 def get_non_used_wim_name(wim_name
, wim_id
, tenant_name
, tenant_id
):
141 if name
not in wim_threads
["names"]:
142 wim_threads
["names"].append(name
)
144 name
= wim_name
[:16] + "." + tenant_name
[:16]
145 if name
not in wim_threads
["names"]:
146 wim_threads
["names"].append(name
)
148 name
= wim_id
+ "-" + tenant_id
149 wim_threads
["names"].append(name
)
153 def start_service(mydb
, persistence
=None, wim
=None):
154 global db
, global_config
155 db
= nfvo_db
.nfvo_db(lock
=db_lock
)
157 db
.connect(global_config
['db_host'], global_config
['db_user'], global_config
['db_passwd'], global_config
['db_name'])
160 persistence
= persistence
or WimPersistence(db
)
162 # Initialize openvim for SDN control
163 # TODO: Avoid static configuration by adding new parameters to openmanod.cfg
164 # TODO: review ovim.py to delete not needed configuration
165 ovim_configuration
= {
166 'logger_name': 'openmano.ovim',
167 'network_vlan_range_start': 1000,
168 'network_vlan_range_end': 4096,
169 'db_name': global_config
["db_ovim_name"],
170 'db_host': global_config
["db_ovim_host"],
171 'db_user': global_config
["db_ovim_user"],
172 'db_passwd': global_config
["db_ovim_passwd"],
175 'network_type': 'bridge',
176 #TODO: log_level_of should not be needed. To be modified in ovim
177 'log_level_of': 'DEBUG'
180 # starts ovim library
181 ovim
= ovim_module
.ovim(ovim_configuration
)
184 wim_engine
= wim
or WimEngine(persistence
)
185 wim_engine
.ovim
= ovim
189 #delete old unneeded vim_wim_actions
193 from_
= 'tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join '\
194 'datacenter_tenants as dt on td.datacenter_tenant_id=dt.uuid'
195 select_
= ('type', 'd.config as config', 'd.uuid as datacenter_id', 'vim_url', 'vim_url_admin',
196 'd.name as datacenter_name', 'dt.uuid as datacenter_tenant_id',
197 'dt.vim_tenant_name as vim_tenant_name', 'dt.vim_tenant_id as vim_tenant_id',
198 'user', 'passwd', 'dt.config as dt_config', 'nfvo_tenant_id')
199 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
)
201 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
202 'datacenter_id': vim
.get('datacenter_id')}
204 extra
.update(yaml
.load(vim
["config"]))
205 if vim
.get('dt_config'):
206 extra
.update(yaml
.load(vim
["dt_config"]))
207 if vim
["type"] not in vimconn_imported
:
210 module
= "vimconn_" + vim
["type"]
211 pkg
= __import__("osm_ro." + module
)
212 vim_conn
= getattr(pkg
, module
)
213 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
214 # vim_conn = imp.load_module(vim["type"], *module_info)
215 vimconn_imported
[vim
["type"]] = vim_conn
216 except (IOError, ImportError) as e
:
217 # if module_info and module_info[0]:
218 # file.close(module_info[0])
219 raise NfvoException("Unknown vim type '{}'. Cannot open file '{}.py'; {}: {}".format(
220 vim
["type"], module
, type(e
).__name
__, str(e
)), httperrors
.Bad_Request
)
222 thread_id
= vim
['datacenter_tenant_id']
223 vim_persistent_info
[thread_id
] = {}
226 # return -httperrors.Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
227 myvim
= vimconn_imported
[ vim
["type"] ].vimconnector(
228 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
229 tenant_id
=vim
['vim_tenant_id'], tenant_name
=vim
['vim_tenant_name'],
230 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
231 user
=vim
['user'], passwd
=vim
['passwd'],
232 config
=extra
, persistent_info
=vim_persistent_info
[thread_id
]
234 except vimconn
.vimconnException
as e
:
236 logger
.error("Cannot launch thread for VIM {} '{}': {}".format(vim
['datacenter_name'],
237 vim
['datacenter_id'], e
))
238 except Exception as e
:
239 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, e
),
240 httperrors
.Internal_Server_Error
)
241 thread_name
= get_non_used_vim_name(vim
['datacenter_name'], vim
['datacenter_id'], vim
['vim_tenant_name'],
242 vim
['vim_tenant_id'])
243 new_thread
= vim_thread
.vim_thread(task_lock
, thread_name
, vim
['datacenter_name'],
244 vim
['datacenter_tenant_id'], db
=db
, db_lock
=db_lock
, ovim
=ovim
)
246 vim_threads
["running"][thread_id
] = new_thread
248 wim_engine
.start_threads()
249 except db_base_Exception
as e
:
250 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
251 except ovim_module
.ovimException
as e
:
253 if message
[:22] == "DATABASE wrong version":
254 message
= "DATABASE wrong version of lib_osm_openvim {msg} -d{dbname} -u{dbuser} -p{dbpass} {ver}' "\
255 "at host {dbhost}".format(
256 msg
=message
[22:-3], dbname
=global_config
["db_ovim_name"],
257 dbuser
=global_config
["db_ovim_user"], dbpass
=global_config
["db_ovim_passwd"],
258 ver
=message
[-3:-1], dbhost
=global_config
["db_ovim_host"])
259 raise NfvoException(message
, httperrors
.Bad_Request
)
263 global ovim
, global_config
266 for thread_id
, thread
in vim_threads
["running"].items():
267 thread
.insert_task("exit")
268 vim_threads
["deleting"][thread_id
] = thread
269 vim_threads
["running"] = {}
272 wim_engine
.stop_threads()
274 if global_config
and global_config
.get("console_thread"):
275 for thread
in global_config
["console_thread"]:
276 thread
.terminate
= True
279 return ("openmanod version {} {}\n(c) Copyright Telefonica".format(global_config
["version"],
280 global_config
["version_date"] ))
284 Clean unused or old entries at database to avoid unlimited growing
285 :param mydb: database connector
288 # get and delete unused vim_wim_actions: all elements deleted, one week before, instance not present
289 now
= t
.time()-3600*24*7
290 instance_action_id
= None
293 actions_to_delete
= mydb
.get_rows(
294 SELECT
=("item", "item_id", "instance_action_id"),
295 FROM
="vim_wim_actions as va join instance_actions as ia on va.instance_action_id=ia.uuid "
296 "left join instance_scenarios as i on ia.instance_id=i.uuid",
297 WHERE
={"va.action": "DELETE", "va.modified_at<": now
, "i.uuid": None,
298 "va.status": ("DONE", "SUPERSEDED")},
301 for to_delete
in actions_to_delete
:
302 mydb
.delete_row(FROM
="vim_wim_actions", WHERE
=to_delete
)
303 if instance_action_id
!= to_delete
["instance_action_id"]:
304 instance_action_id
= to_delete
["instance_action_id"]
305 mydb
.delete_row(FROM
="instance_actions", WHERE
={"uuid": instance_action_id
})
306 nb_deleted
+= len(actions_to_delete
)
307 if len(actions_to_delete
) < 100:
310 mydb
.update_rows("vim_wim_actions", UPDATE
={"worker": None}, WHERE
={"worker<>": None})
313 logger
.debug("Removed {} unused vim_wim_actions".format(nb_deleted
))
316 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
318 return result, content:
319 <0, error_text upon error
320 nb_records, flavor_list on success
323 WHERE_dict
['vnf_id'] = vnf_id
324 if nfvo_tenant
is not None:
325 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
327 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
328 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
329 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
330 #print "get_flavor_list result:", result
331 #print "get_flavor_list content:", content
333 for flavor
in flavors
:
334 flavorList
.append(flavor
['flavor_id'])
338 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
340 Get used images of all vms belonging to this VNFD
341 :param mydb: database conector
342 :param vnf_id: vnfd uuid
343 :param nfvo_tenant: tenant, not used
344 :return: The list of image uuid used
347 vms
= mydb
.get_rows(SELECT
=('image_id','image_list'), FROM
='vms', WHERE
={'vnf_id': vnf_id
})
349 if vm
["image_id"] and vm
["image_id"] not in image_list
:
350 image_list
.append(vm
["image_id"])
352 vm_image_list
= yaml
.load(vm
["image_list"])
353 for image_dict
in vm_image_list
:
354 if image_dict
["image_id"] not in image_list
:
355 image_list
.append(image_dict
["image_id"])
359 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
360 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None, ignore_errors
=False):
361 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
362 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
363 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
364 raise exception upon error
367 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
368 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
369 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
370 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
371 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
372 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
373 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
374 from_
= 'tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join datacenter_tenants as dt on td.datacenter_tenant_id=dt.uuid'
375 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
376 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
377 'user','passwd', 'dt.config as dt_config')
379 from_
= 'datacenters as d'
380 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
382 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
385 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
386 'datacenter_id': vim
.get('datacenter_id'),
387 '_vim_type_internal': vim
.get('type')}
389 extra
.update(yaml
.load(vim
["config"]))
390 if vim
.get('dt_config'):
391 extra
.update(yaml
.load(vim
["dt_config"]))
392 if vim
["type"] not in vimconn_imported
:
395 module
= "vimconn_" + vim
["type"]
396 pkg
= __import__("osm_ro." + module
)
397 vim_conn
= getattr(pkg
, module
)
398 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
399 # vim_conn = imp.load_module(vim["type"], *module_info)
400 vimconn_imported
[vim
["type"]] = vim_conn
401 except (IOError, ImportError) as e
:
402 # if module_info and module_info[0]:
403 # file.close(module_info[0])
405 logger
.error("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
406 vim
["type"], module
, type(e
).__name
__, str(e
)))
408 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
409 vim
["type"], module
, type(e
).__name
__, str(e
)), httperrors
.Bad_Request
)
412 if 'datacenter_tenant_id' in vim
:
413 thread_id
= vim
["datacenter_tenant_id"]
414 if thread_id
not in vim_persistent_info
:
415 vim_persistent_info
[thread_id
] = {}
416 persistent_info
= vim_persistent_info
[thread_id
]
420 # return -httperrors.Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
421 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
422 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
423 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
),
424 tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
425 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
426 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
427 config
=extra
, persistent_info
=persistent_info
429 except Exception as e
:
431 logger
.error("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)))
433 http_code
= httperrors
.Internal_Server_Error
434 if isinstance(e
, vimconn
.vimconnException
):
435 http_code
= e
.http_code
436 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), http_code
)
438 except db_base_Exception
as e
:
439 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
442 def rollback(mydb
, vims
, rollback_list
):
444 #delete things by reverse order
445 for i
in range(len(rollback_list
)-1, -1, -1):
446 item
= rollback_list
[i
]
447 if item
["where"]=="vim":
448 if item
["vim_id"] not in vims
:
450 if is_task_id(item
["uuid"]):
452 vim
= vims
[item
["vim_id"]]
454 if item
["what"]=="image":
455 vim
.delete_image(item
["uuid"])
456 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_vim_id": vim
["id"], "vim_id":item
["uuid"]})
457 elif item
["what"]=="flavor":
458 vim
.delete_flavor(item
["uuid"])
459 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_vim_id": vim
["id"], "vim_id":item
["uuid"]})
460 elif item
["what"]=="network":
461 vim
.delete_network(item
["uuid"])
462 elif item
["what"]=="vm":
463 vim
.delete_vminstance(item
["uuid"])
464 except vimconn
.vimconnException
as e
:
465 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
466 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
467 except db_base_Exception
as e
:
468 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
472 if item
["what"]=="image":
473 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
474 elif item
["what"]=="flavor":
475 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
476 except db_base_Exception
as e
:
477 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
478 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
479 if len(undeleted_items
)==0:
480 return True," Rollback successful."
482 return False," Rollback fails to delete: " + str(undeleted_items
)
485 def check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1):
487 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
489 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
491 #dataplane interfaces
492 for numa
in vnfc
.get("numas",() ):
493 for interface
in numa
.get("interfaces",()):
494 if interface
["name"] in name_dict
:
496 "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
497 vnfc
["name"], interface
["name"]),
498 httperrors
.Bad_Request
)
499 name_dict
[ interface
["name"] ] = "underlay"
501 for interface
in vnfc
.get("bridge-ifaces",() ):
502 if interface
["name"] in name_dict
:
504 "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
505 vnfc
["name"], interface
["name"]),
506 httperrors
.Bad_Request
)
507 name_dict
[ interface
["name"] ] = "overlay"
508 vnfc_interfaces
[ vnfc
["name"] ] = name_dict
509 # check bood-data info
510 # if "boot-data" in vnfc:
511 # # check that user-data is incompatible with users and config-files
512 # if (vnfc["boot-data"].get("users") or vnfc["boot-data"].get("config-files")) and vnfc["boot-data"].get("user-data"):
513 # raise NfvoException(
514 # "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
515 # httperrors.Bad_Request)
517 #check if the info in external_connections matches with the one in the vnfcs
519 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
520 if external_connection
["name"] in name_list
:
522 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
523 external_connection
["name"]),
524 httperrors
.Bad_Request
)
525 name_list
.append(external_connection
["name"])
526 if external_connection
["VNFC"] not in vnfc_interfaces
:
528 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
529 external_connection
["name"], external_connection
["VNFC"]),
530 httperrors
.Bad_Request
)
532 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
534 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
535 external_connection
["name"],
536 external_connection
["local_iface_name"]),
537 httperrors
.Bad_Request
)
539 #check if the info in internal_connections matches with the one in the vnfcs
541 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
542 if internal_connection
["name"] in name_list
:
544 "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection".format(
545 internal_connection
["name"]),
546 httperrors
.Bad_Request
)
547 name_list
.append(internal_connection
["name"])
548 #We should check that internal-connections of type "ptp" have only 2 elements
550 if len(internal_connection
["elements"])>2 and (internal_connection
.get("type") == "ptp" or internal_connection
.get("type") == "e-line"):
552 "Error at 'vnf:internal-connections[name:'{}']:elements', size must be 2 for a '{}' type. Consider change it to '{}' type".format(
553 internal_connection
["name"],
554 'ptp' if vnf_descriptor_version
==1 else 'e-line',
555 'data' if vnf_descriptor_version
==1 else "e-lan"),
556 httperrors
.Bad_Request
)
557 for port
in internal_connection
["elements"]:
559 iface
= port
["local_iface_name"]
560 if vnf
not in vnfc_interfaces
:
562 "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
563 internal_connection
["name"], vnf
),
564 httperrors
.Bad_Request
)
565 if iface
not in vnfc_interfaces
[ vnf
]:
567 "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
568 internal_connection
["name"], iface
),
569 httperrors
.Bad_Request
)
570 return -httperrors
.Bad_Request
,
571 if vnf_descriptor_version
==1 and "type" not in internal_connection
:
572 if vnfc_interfaces
[vnf
][iface
] == "overlay":
573 internal_connection
["type"] = "bridge"
575 internal_connection
["type"] = "data"
576 if vnf_descriptor_version
==2 and "implementation" not in internal_connection
:
577 if vnfc_interfaces
[vnf
][iface
] == "overlay":
578 internal_connection
["implementation"] = "overlay"
580 internal_connection
["implementation"] = "underlay"
581 if (internal_connection
.get("type") == "data" or internal_connection
.get("type") == "ptp" or \
582 internal_connection
.get("implementation") == "underlay") and vnfc_interfaces
[vnf
][iface
] == "overlay":
584 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
585 internal_connection
["name"],
586 iface
, 'bridge' if vnf_descriptor_version
==1 else 'overlay',
587 'data' if vnf_descriptor_version
==1 else 'underlay'),
588 httperrors
.Bad_Request
)
589 if (internal_connection
.get("type") == "bridge" or internal_connection
.get("implementation") == "overlay") and \
590 vnfc_interfaces
[vnf
][iface
] == "underlay":
592 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
593 internal_connection
["name"], iface
,
594 'data' if vnf_descriptor_version
==1 else 'underlay',
595 'bridge' if vnf_descriptor_version
==1 else 'overlay'),
596 httperrors
.Bad_Request
)
599 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=None):
601 if only_create_at_vim
:
602 image_mano_id
= image_dict
['uuid']
603 if return_on_error
== None:
604 return_on_error
= True
606 if image_dict
['location']:
607 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
609 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
611 image_mano_id
= images
[0]['uuid']
613 #create image in MANO DB
614 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
615 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
616 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
618 #temp_image_dict['location'] = image_dict.get('new_location') if image_dict['location'] is None
619 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
620 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
621 #create image at every vim
622 for vim_id
,vim
in vims
.iteritems():
623 datacenter_vim_id
= vim
["config"]["datacenter_tenant_id"]
624 image_created
="false"
626 image_db
= mydb
.get_rows(FROM
="datacenters_images",
627 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'image_id': image_mano_id
})
628 #look at VIM if this image exist
630 if image_dict
['location'] is not None:
631 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
634 filter_dict
['name'] = image_dict
['universal_name']
635 if image_dict
.get('checksum') != None:
636 filter_dict
['checksum'] = image_dict
['checksum']
637 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
638 vim_images
= vim
.get_image_list(filter_dict
)
639 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
640 if len(vim_images
) > 1:
641 raise vimconn
.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict
)), httperrors
.Conflict
)
642 elif len(vim_images
) == 0:
643 raise vimconn
.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict
)))
645 #logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
646 image_vim_id
= vim_images
[0]['id']
648 except vimconn
.vimconnNotFoundException
as e
:
649 #Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
651 #image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
652 if image_dict
['location']:
653 image_vim_id
= vim
.new_image(image_dict
)
654 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
657 #If we reach this point, then the image has image name, and optionally checksum, and could not be found
658 raise vimconn
.vimconnException(str(e
))
659 except vimconn
.vimconnException
as e
:
661 logger
.error("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
664 logger
.warn("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
666 except vimconn
.vimconnException
as e
:
668 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
670 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
673 #if we reach here, the image has been created or existed
675 #add new vim_id at datacenters_images
676 mydb
.new_row('datacenters_images', {'datacenter_vim_id': datacenter_vim_id
,
677 'image_id':image_mano_id
,
678 'vim_id': image_vim_id
,
679 'created':image_created
})
680 elif image_db
[0]["vim_id"]!=image_vim_id
:
681 #modify existing vim_id at datacenters_images
682 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_vim_id':vim_id
, 'image_id':image_mano_id
})
684 return image_vim_id
if only_create_at_vim
else image_mano_id
687 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
688 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',0),
689 'ram':flavor_dict
.get('ram'),
690 'vcpus':flavor_dict
.get('vcpus'),
692 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
693 del flavor_dict
['extended']
694 if 'extended' in flavor_dict
:
695 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
697 #look if flavor exist
698 if only_create_at_vim
:
699 flavor_mano_id
= flavor_dict
['uuid']
700 if return_on_error
== None:
701 return_on_error
= True
703 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
705 flavor_mano_id
= flavors
[0]['uuid']
708 #create one by one the images of aditional disks
709 dev_image_list
=[] #list of images
710 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
712 for device
in flavor_dict
['extended'].get('devices',[]):
713 if "image" not in device
and "image name" not in device
:
716 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
717 image_dict
['universal_name']=device
.get('image name')
718 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
719 image_dict
['location']=device
.get('image')
720 #image_dict['new_location']=vnfc.get('image location')
721 image_dict
['checksum']=device
.get('image checksum')
722 image_metadata_dict
= device
.get('image metadata', None)
723 image_metadata_str
= None
724 if image_metadata_dict
!= None:
725 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
726 image_dict
['metadata']=image_metadata_str
727 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
728 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
729 dev_image_list
.append(image_id
)
731 temp_flavor_dict
['name'] = flavor_dict
['name']
732 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
733 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
734 flavor_mano_id
= content
735 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
736 #create flavor at every vim
737 if 'uuid' in flavor_dict
:
738 del flavor_dict
['uuid']
740 for vim_id
,vim
in vims
.items():
741 datacenter_vim_id
= vim
["config"]["datacenter_tenant_id"]
742 flavor_created
="false"
744 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors",
745 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
})
746 #look at VIM if this flavor exist SKIPPED
747 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
749 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
753 # Create the flavor in VIM
754 # Translate images at devices from MANO id to VIM id
756 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
757 # make a copy of original devices
760 for device
in flavor_dict
["extended"].get("devices",[]):
763 devices_original
.append(dev
)
764 if 'image' in device
:
766 if 'image metadata' in device
:
767 del device
['image metadata']
768 if 'image checksum' in device
:
769 del device
['image checksum']
771 for index
in range(0,len(devices_original
)) :
772 device
=devices_original
[index
]
773 if "image" not in device
and "image name" not in device
:
774 # if 'size' in device:
775 disk_list
.append({'size': device
.get('size', default_volume_size
), 'name': device
.get('name')})
778 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
779 image_dict
['universal_name']=device
.get('image name')
780 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
781 image_dict
['location']=device
.get('image')
782 # image_dict['new_location']=device.get('image location')
783 image_dict
['checksum']=device
.get('image checksum')
784 image_metadata_dict
= device
.get('image metadata', None)
785 image_metadata_str
= None
786 if image_metadata_dict
!= None:
787 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
788 image_dict
['metadata']=image_metadata_str
789 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
790 image_dict
["uuid"]=image_mano_id
791 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
793 #save disk information (image must be based on and size
794 disk_list
.append({'image_id': image_vim_id
, 'size': device
.get('size', default_volume_size
)})
796 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
799 #check that this vim_id exist in VIM, if not create
800 flavor_vim_id
=flavor_db
[0]["vim_id"]
802 vim
.get_flavor(flavor_vim_id
)
803 continue #flavor exist
804 except vimconn
.vimconnException
:
806 #create flavor at vim
807 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
810 flavor_vim_id
=vim
.get_flavor_id_from_data(flavor_dict
)
811 flavor_created
="false"
812 except vimconn
.vimconnException
as e
:
815 if not flavor_vim_id
:
816 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
817 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
818 flavor_created
="true"
819 except vimconn
.vimconnException
as e
:
821 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
823 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
826 #if reach here the flavor has been create or exist
827 if len(flavor_db
)==0:
828 #add new vim_id at datacenters_flavors
829 extended_devices_yaml
= None
830 if len(disk_list
) > 0:
831 extended_devices
= dict()
832 extended_devices
['disks'] = disk_list
833 extended_devices_yaml
= yaml
.safe_dump(extended_devices
,default_flow_style
=True,width
=256)
834 mydb
.new_row('datacenters_flavors',
835 {'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
, 'vim_id': flavor_vim_id
,
836 'created': flavor_created
, 'extended': extended_devices_yaml
})
837 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
838 #modify existing vim_id at datacenters_flavors
839 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
},
840 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
})
842 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
845 def get_str(obj
, field
, length
):
847 Obtain the str value,
852 value
= obj
.get(field
)
853 if value
is not None:
854 value
= str(value
)[:length
]
857 def _lookfor_or_create_image(db_image
, mydb
, descriptor
):
859 fill image content at db_image dictionary. Check if the image with this image and checksum exist
860 :param db_image: dictionary to insert data
861 :param mydb: database connector
862 :param descriptor: yang descriptor
863 :return: uuid if the image exist at DB, or None if a new image must be created with the data filled at db_image
866 db_image
["name"] = get_str(descriptor
, "image", 255)
867 db_image
["checksum"] = get_str(descriptor
, "image-checksum", 32)
868 if not db_image
["checksum"]: # Ensure that if empty string, None is stored
869 db_image
["checksum"] = None
870 if db_image
["name"].startswith("/"):
871 db_image
["location"] = db_image
["name"]
872 existing_images
= mydb
.get_rows(FROM
="images", WHERE
={'location': db_image
["location"]})
874 db_image
["universal_name"] = db_image
["name"]
875 existing_images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name': db_image
['universal_name'],
876 'checksum': db_image
['checksum']})
878 return existing_images
[0]["uuid"]
880 image_uuid
= str(uuid4())
881 db_image
["uuid"] = image_uuid
884 def get_resource_allocation_params(quota_descriptor
):
886 read the quota_descriptor from vnfd and fetch the resource allocation properties from the descriptor object
887 :param quota_descriptor: cpu/mem/vif/disk-io quota descriptor
888 :return: quota params for limit, reserve, shares from the descriptor object
891 if quota_descriptor
.get("limit"):
892 quota
["limit"] = int(quota_descriptor
["limit"])
893 if quota_descriptor
.get("reserve"):
894 quota
["reserve"] = int(quota_descriptor
["reserve"])
895 if quota_descriptor
.get("shares"):
896 quota
["shares"] = int(quota_descriptor
["shares"])
899 def new_vnfd_v3(mydb
, tenant_id
, vnf_descriptor
):
901 Parses an OSM IM vnfd_catalog and insert at DB
904 :param vnf_descriptor:
905 :return: The list of cretated vnf ids
908 myvnfd
= vnfd_catalog
.vnfd()
910 pybindJSONDecoder
.load_ietf_json(vnf_descriptor
, None, None, obj
=myvnfd
, path_helper
=True,
912 except Exception as e
:
913 raise NfvoException("Error. Invalid VNF descriptor format " + str(e
), httperrors
.Bad_Request
)
921 db_ip_profiles_index
= 0
925 vnfd_catalog_descriptor
= vnf_descriptor
.get("vnfd:vnfd-catalog")
926 if not vnfd_catalog_descriptor
:
927 vnfd_catalog_descriptor
= vnf_descriptor
.get("vnfd-catalog")
928 vnfd_descriptor_list
= vnfd_catalog_descriptor
.get("vnfd")
929 if not vnfd_descriptor_list
:
930 vnfd_descriptor_list
= vnfd_catalog_descriptor
.get("vnfd:vnfd")
931 for vnfd_yang
in myvnfd
.vnfd_catalog
.vnfd
.itervalues():
932 vnfd
= vnfd_yang
.get()
935 vnf_uuid
= str(uuid4())
936 uuid_list
.append(vnf_uuid
)
937 vnfd_uuid_list
.append(vnf_uuid
)
938 vnfd_id
= get_str(vnfd
, "id", 255)
942 "name": get_str(vnfd
, "name", 255),
943 "description": get_str(vnfd
, "description", 255),
944 "tenant_id": tenant_id
,
945 "vendor": get_str(vnfd
, "vendor", 255),
946 "short_name": get_str(vnfd
, "short-name", 255),
947 "descriptor": str(vnf_descriptor
)[:60000]
950 for vnfd_descriptor
in vnfd_descriptor_list
:
951 if vnfd_descriptor
["id"] == str(vnfd
["id"]):
954 # table ip_profiles (ip-profiles)
955 ip_profile_name2db_table_index
= {}
956 for ip_profile
in vnfd
.get("ip-profiles").itervalues():
958 "ip_version": str(ip_profile
["ip-profile-params"].get("ip-version", "ipv4")),
959 "subnet_address": str(ip_profile
["ip-profile-params"].get("subnet-address")),
960 "gateway_address": str(ip_profile
["ip-profile-params"].get("gateway-address")),
961 "dhcp_enabled": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("enabled", True)),
962 "dhcp_start_address": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("start-address")),
963 "dhcp_count": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("count")),
966 for dns
in ip_profile
["ip-profile-params"]["dns-server"].itervalues():
967 dns_list
.append(str(dns
.get("address")))
968 db_ip_profile
["dns_address"] = ";".join(dns_list
)
969 if ip_profile
["ip-profile-params"].get('security-group'):
970 db_ip_profile
["security_group"] = ip_profile
["ip-profile-params"]['security-group']
971 ip_profile_name2db_table_index
[str(ip_profile
["name"])] = db_ip_profiles_index
972 db_ip_profiles_index
+= 1
973 db_ip_profiles
.append(db_ip_profile
)
975 # table nets (internal-vld)
976 net_id2uuid
= {} # for mapping interface with network
977 for vld
in vnfd
.get("internal-vld").itervalues():
978 net_uuid
= str(uuid4())
979 uuid_list
.append(net_uuid
)
981 "name": get_str(vld
, "name", 255),
984 "description": get_str(vld
, "description", 255),
985 "osm_id": get_str(vld
, "id", 255),
986 "type": "bridge", # TODO adjust depending on connection point type
988 net_id2uuid
[vld
.get("id")] = net_uuid
989 db_nets
.append(db_net
)
990 # ip-profile, link db_ip_profile with db_sce_net
991 if vld
.get("ip-profile-ref"):
992 ip_profile_name
= vld
.get("ip-profile-ref")
993 if ip_profile_name
not in ip_profile_name2db_table_index
:
994 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vld[{}]':'ip-profile-ref':"
995 "'{}'. Reference to a non-existing 'ip_profiles'".format(
996 str(vnfd
["id"]), str(vld
["id"]), str(vld
["ip-profile-ref"])),
997 httperrors
.Bad_Request
)
998 db_ip_profiles
[ip_profile_name2db_table_index
[ip_profile_name
]]["net_id"] = net_uuid
999 else: #check no ip-address has been defined
1000 for icp
in vld
.get("internal-connection-point").itervalues():
1001 if icp
.get("ip-address"):
1002 raise NfvoException("Error at 'vnfd[{}]':'vld[{}]':'internal-connection-point[{}]' "
1003 "contains an ip-address but no ip-profile has been defined at VLD".format(
1004 str(vnfd
["id"]), str(vld
["id"]), str(icp
["id"])),
1005 httperrors
.Bad_Request
)
1007 # connection points vaiable declaration
1008 cp_name2iface_uuid
= {}
1010 cp_name2vm_uuid
= {}
1011 cp_name2db_interface
= {}
1012 vdu_id2cp_name
= {} # stored only when one external connection point is presented at this VDU
1016 vdu_id2db_table_index
= {}
1018 for vdu
in vnfd
.get("vdu").itervalues():
1020 for vdu_descriptor
in vnfd_descriptor
["vdu"]:
1021 if vdu_descriptor
["id"] == str(vdu
["id"]):
1023 vm_uuid
= str(uuid4())
1024 uuid_list
.append(vm_uuid
)
1025 vdu_id
= get_str(vdu
, "id", 255)
1029 "name": get_str(vdu
, "name", 255),
1030 "description": get_str(vdu
, "description", 255),
1031 "pdu_type": get_str(vdu
, "pdu-type", 255),
1034 vdu_id2uuid
[db_vm
["osm_id"]] = vm_uuid
1035 vdu_id2db_table_index
[db_vm
["osm_id"]] = db_vms_index
1036 if vdu
.get("count"):
1037 db_vm
["count"] = int(vdu
["count"])
1040 image_present
= False
1041 if vdu
.get("image"):
1042 image_present
= True
1044 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, vdu
)
1046 image_uuid
= db_image
["uuid"]
1047 db_images
.append(db_image
)
1048 db_vm
["image_id"] = image_uuid
1049 if vdu
.get("alternative-images"):
1050 vm_alternative_images
= []
1051 for alt_image
in vdu
.get("alternative-images").itervalues():
1053 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, alt_image
)
1055 image_uuid
= db_image
["uuid"]
1056 db_images
.append(db_image
)
1057 vm_alternative_images
.append({
1058 "image_id": image_uuid
,
1059 "vim_type": str(alt_image
["vim-type"]),
1060 # "universal_name": str(alt_image["image"]),
1061 # "checksum": str(alt_image["image-checksum"]) if alt_image.get("image-checksum") else None
1064 db_vm
["image_list"] = yaml
.safe_dump(vm_alternative_images
, default_flow_style
=True, width
=256)
1068 if vdu
.get("volumes"):
1069 for volume_key
in vdu
["volumes"]:
1070 volume
= vdu
["volumes"][volume_key
]
1071 if not image_present
:
1072 # Convert the first volume to vnfc.image
1073 image_present
= True
1075 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, volume
)
1077 image_uuid
= db_image
["uuid"]
1078 db_images
.append(db_image
)
1079 db_vm
["image_id"] = image_uuid
1081 # Add Openmano devices
1082 device
= {"name": str(volume
.get("name"))}
1083 device
["type"] = str(volume
.get("device-type"))
1084 if volume
.get("size"):
1085 device
["size"] = int(volume
["size"])
1086 if volume
.get("image"):
1087 device
["image name"] = str(volume
["image"])
1088 if volume
.get("image-checksum"):
1089 device
["image checksum"] = str(volume
["image-checksum"])
1091 devices
.append(device
)
1093 if not db_vm
.get("image_id"):
1094 if not db_vm
["pdu_type"]:
1095 raise NfvoException("Not defined image for VDU")
1096 # create a fake image
1100 if vdu
.get("cloud-init"):
1101 boot_data
["user-data"] = str(vdu
["cloud-init"])
1102 elif vdu
.get("cloud-init-file"):
1103 # TODO Where this file content is present???
1104 # boot_data["user-data"] = vnfd_yang.files[vdu["cloud-init-file"]]
1105 boot_data
["user-data"] = str(vdu
["cloud-init-file"])
1107 if vdu
.get("supplemental-boot-data"):
1108 if vdu
["supplemental-boot-data"].get('boot-data-drive'):
1109 boot_data
['boot-data-drive'] = True
1110 if vdu
["supplemental-boot-data"].get('config-file'):
1111 om_cfgfile_list
= list()
1112 for custom_config_file
in vdu
["supplemental-boot-data"]['config-file'].itervalues():
1113 # TODO Where this file content is present???
1114 cfg_source
= str(custom_config_file
["source"])
1115 om_cfgfile_list
.append({"dest": custom_config_file
["dest"],
1116 "content": cfg_source
})
1117 boot_data
['config-files'] = om_cfgfile_list
1119 db_vm
["boot_data"] = yaml
.safe_dump(boot_data
, default_flow_style
=True, width
=256)
1121 db_vms
.append(db_vm
)
1124 # table interfaces (internal/external interfaces)
1125 flavor_epa_interfaces
= []
1126 # for iface in chain(vdu.get("internal-interface").itervalues(), vdu.get("external-interface").itervalues()):
1127 for iface
in vdu
.get("interface").itervalues():
1128 flavor_epa_interface
= {}
1129 iface_uuid
= str(uuid4())
1130 uuid_list
.append(iface_uuid
)
1133 "internal_name": get_str(iface
, "name", 255),
1136 flavor_epa_interface
["name"] = db_interface
["internal_name"]
1137 if iface
.get("virtual-interface").get("vpci"):
1138 db_interface
["vpci"] = get_str(iface
.get("virtual-interface"), "vpci", 12)
1139 flavor_epa_interface
["vpci"] = db_interface
["vpci"]
1141 if iface
.get("virtual-interface").get("bandwidth"):
1142 bps
= int(iface
.get("virtual-interface").get("bandwidth"))
1143 db_interface
["bw"] = int(math
.ceil(bps
/1000000.0))
1144 flavor_epa_interface
["bandwidth"] = "{} Mbps".format(db_interface
["bw"])
1146 if iface
.get("virtual-interface").get("type") == "OM-MGMT":
1147 db_interface
["type"] = "mgmt"
1148 elif iface
.get("virtual-interface").get("type") in ("VIRTIO", "E1000", "PARAVIRT"):
1149 db_interface
["type"] = "bridge"
1150 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1151 elif iface
.get("virtual-interface").get("type") in ("SR-IOV", "PCI-PASSTHROUGH"):
1152 db_interface
["type"] = "data"
1153 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1154 flavor_epa_interface
["dedicated"] = "no" if iface
["virtual-interface"]["type"] == "SR-IOV" \
1156 flavor_epa_interfaces
.append(flavor_epa_interface
)
1158 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vdu[{}]':'interface':'virtual"
1159 "-interface':'type':'{}'. Interface type is not supported".format(
1160 vnfd_id
, vdu_id
, iface
.get("virtual-interface").get("type")),
1161 httperrors
.Bad_Request
)
1163 if iface
.get("mgmt-interface"):
1164 db_interface
["type"] = "mgmt"
1166 if iface
.get("external-connection-point-ref"):
1168 cp
= vnfd
.get("connection-point")[iface
.get("external-connection-point-ref")]
1169 db_interface
["external_name"] = get_str(cp
, "name", 255)
1170 cp_name2iface_uuid
[db_interface
["external_name"]] = iface_uuid
1171 cp_name2vdu_id
[db_interface
["external_name"]] = vdu_id
1172 cp_name2vm_uuid
[db_interface
["external_name"]] = vm_uuid
1173 cp_name2db_interface
[db_interface
["external_name"]] = db_interface
1174 for cp_descriptor
in vnfd_descriptor
["connection-point"]:
1175 if cp_descriptor
["name"] == db_interface
["external_name"]:
1180 if vdu_id
in vdu_id2cp_name
:
1181 vdu_id2cp_name
[vdu_id
] = None # more than two connecdtion point for this VDU
1183 vdu_id2cp_name
[vdu_id
] = db_interface
["external_name"]
1186 if str(cp_descriptor
.get("port-security-enabled")).lower() == "false":
1187 db_interface
["port_security"] = 0
1188 elif str(cp_descriptor
.get("port-security-enabled")).lower() == "true":
1189 db_interface
["port_security"] = 1
1191 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1192 "'interface[{iface}]':'vnfd-connection-point-ref':'{cp}' is not present"
1193 " at connection-point".format(
1194 vnf
=vnfd_id
, vdu
=vdu_id
, iface
=iface
["name"],
1195 cp
=iface
.get("vnfd-connection-point-ref")),
1196 httperrors
.Bad_Request
)
1197 elif iface
.get("internal-connection-point-ref"):
1199 for icp_descriptor
in vdu_descriptor
["internal-connection-point"]:
1200 if icp_descriptor
["id"] == str(iface
.get("internal-connection-point-ref")):
1203 raise KeyError("does not exist at vdu:internal-connection-point")
1206 for vld
in vnfd
.get("internal-vld").itervalues():
1207 for cp
in vld
.get("internal-connection-point").itervalues():
1208 if cp
.get("id-ref") == iface
.get("internal-connection-point-ref"):
1210 raise KeyError("is referenced by more than one 'internal-vld'")
1214 raise KeyError("is not referenced by any 'internal-vld'")
1216 db_interface
["net_id"] = net_id2uuid
[icp_vld
.get("id")]
1217 if str(icp_descriptor
.get("port-security-enabled")).lower() == "false":
1218 db_interface
["port_security"] = 0
1219 elif str(icp_descriptor
.get("port-security-enabled")).lower() == "true":
1220 db_interface
["port_security"] = 1
1221 if icp
.get("ip-address"):
1222 if not icp_vld
.get("ip-profile-ref"):
1224 db_interface
["ip_address"] = str(icp
.get("ip-address"))
1225 except KeyError as e
:
1226 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1227 "'interface[{iface}]':'internal-connection-point-ref':'{cp}'"
1229 vnf
=vnfd_id
, vdu
=vdu_id
, iface
=iface
["name"],
1230 cp
=iface
.get("internal-connection-point-ref"), msg
=str(e
)),
1231 httperrors
.Bad_Request
)
1232 if iface
.get("position"):
1233 db_interface
["created_at"] = int(iface
.get("position")) * 50
1234 if iface
.get("mac-address"):
1235 db_interface
["mac"] = str(iface
.get("mac-address"))
1236 db_interfaces
.append(db_interface
)
1240 "name": get_str(vdu
, "name", 250) + "-flv",
1241 "vcpus": int(vdu
["vm-flavor"].get("vcpu-count", 1)),
1242 "ram": int(vdu
["vm-flavor"].get("memory-mb", 1)),
1243 "disk": int(vdu
["vm-flavor"].get("storage-gb", 0)),
1245 # TODO revise the case of several numa-node-policy node
1249 extended
["devices"] = devices
1250 if flavor_epa_interfaces
:
1251 numa
["interfaces"] = flavor_epa_interfaces
1252 if vdu
.get("guest-epa"): # TODO or dedicated_int:
1253 epa_vcpu_set
= False
1254 if vdu
["guest-epa"].get("numa-node-policy"): # TODO or dedicated_int:
1255 numa_node_policy
= vdu
["guest-epa"].get("numa-node-policy")
1256 if numa_node_policy
.get("node"):
1257 numa_node
= numa_node_policy
["node"].values()[0]
1258 if numa_node
.get("num-cores"):
1259 numa
["cores"] = numa_node
["num-cores"]
1261 if numa_node
.get("paired-threads"):
1262 if numa_node
["paired-threads"].get("num-paired-threads"):
1263 numa
["paired-threads"] = int(numa_node
["paired-threads"]["num-paired-threads"])
1265 if len(numa_node
["paired-threads"].get("paired-thread-ids")):
1266 numa
["paired-threads-id"] = []
1267 for pair
in numa_node
["paired-threads"]["paired-thread-ids"].itervalues():
1268 numa
["paired-threads-id"].append(
1269 (str(pair
["thread-a"]), str(pair
["thread-b"]))
1271 if numa_node
.get("num-threads"):
1272 numa
["threads"] = int(numa_node
["num-threads"])
1274 if numa_node
.get("memory-mb"):
1275 numa
["memory"] = max(int(numa_node
["memory-mb"] / 1024), 1)
1276 if vdu
["guest-epa"].get("mempage-size"):
1277 if vdu
["guest-epa"]["mempage-size"] != "SMALL":
1278 numa
["memory"] = max(int(db_flavor
["ram"] / 1024), 1)
1279 if vdu
["guest-epa"].get("cpu-pinning-policy") and not epa_vcpu_set
:
1280 if vdu
["guest-epa"]["cpu-pinning-policy"] == "DEDICATED":
1281 if vdu
["guest-epa"].get("cpu-thread-pinning-policy") and \
1282 vdu
["guest-epa"]["cpu-thread-pinning-policy"] != "PREFER":
1283 numa
["cores"] = max(db_flavor
["vcpus"], 1)
1285 numa
["threads"] = max(db_flavor
["vcpus"], 1)
1287 if vdu
["guest-epa"].get("cpu-quota") and not epa_vcpu_set
:
1288 cpuquota
= get_resource_allocation_params(vdu
["guest-epa"].get("cpu-quota"))
1290 extended
["cpu-quota"] = cpuquota
1291 if vdu
["guest-epa"].get("mem-quota"):
1292 vduquota
= get_resource_allocation_params(vdu
["guest-epa"].get("mem-quota"))
1294 extended
["mem-quota"] = vduquota
1295 if vdu
["guest-epa"].get("disk-io-quota"):
1296 diskioquota
= get_resource_allocation_params(vdu
["guest-epa"].get("disk-io-quota"))
1298 extended
["disk-io-quota"] = diskioquota
1299 if vdu
["guest-epa"].get("vif-quota"):
1300 vifquota
= get_resource_allocation_params(vdu
["guest-epa"].get("vif-quota"))
1302 extended
["vif-quota"] = vifquota
1304 extended
["numas"] = [numa
]
1306 extended_text
= yaml
.safe_dump(extended
, default_flow_style
=True, width
=256)
1307 db_flavor
["extended"] = extended_text
1308 # look if flavor exist
1309 temp_flavor_dict
= {'disk': db_flavor
.get('disk', 0),
1310 'ram': db_flavor
.get('ram'),
1311 'vcpus': db_flavor
.get('vcpus'),
1312 'extended': db_flavor
.get('extended')
1314 existing_flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
1315 if existing_flavors
:
1316 flavor_uuid
= existing_flavors
[0]["uuid"]
1318 flavor_uuid
= str(uuid4())
1319 uuid_list
.append(flavor_uuid
)
1320 db_flavor
["uuid"] = flavor_uuid
1321 db_flavors
.append(db_flavor
)
1322 db_vm
["flavor_id"] = flavor_uuid
1324 # VNF affinity and antiaffinity
1325 for pg
in vnfd
.get("placement-groups").itervalues():
1326 pg_name
= get_str(pg
, "name", 255)
1327 for vdu
in pg
.get("member-vdus").itervalues():
1328 vdu_id
= get_str(vdu
, "member-vdu-ref", 255)
1329 if vdu_id
not in vdu_id2db_table_index
:
1330 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'placement-groups[{pg}]':"
1331 "'member-vdus':'{vdu}'. Reference to a non-existing vdu".format(
1332 vnf
=vnfd_id
, pg
=pg_name
, vdu
=vdu_id
),
1333 httperrors
.Bad_Request
)
1334 db_vms
[vdu_id2db_table_index
[vdu_id
]]["availability_zone"] = pg_name
1335 # TODO consider the case of isolation and not colocation
1336 # if pg.get("strategy") == "ISOLATION":
1338 # VNF mgmt configuration
1339 if vnfd
["mgmt-interface"].get("vdu-id"):
1340 mgmt_vdu_id
= get_str(vnfd
["mgmt-interface"], "vdu-id", 255)
1341 if mgmt_vdu_id
not in vdu_id2uuid
:
1342 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'vdu-id':"
1343 "'{vdu}'. Reference to a non-existing vdu".format(
1344 vnf
=vnfd_id
, vdu
=mgmt_vdu_id
),
1345 httperrors
.Bad_Request
)
1346 mgmt_access
["vm_id"] = vdu_id2uuid
[vnfd
["mgmt-interface"]["vdu-id"]]
1347 mgmt_access
["vdu-id"] = vnfd
["mgmt-interface"]["vdu-id"]
1348 # if only one cp is defined by this VDU, mark this interface as of type "mgmt"
1349 if vdu_id2cp_name
.get(mgmt_vdu_id
):
1350 if cp_name2db_interface
[vdu_id2cp_name
[mgmt_vdu_id
]]:
1351 cp_name2db_interface
[vdu_id2cp_name
[mgmt_vdu_id
]]["type"] = "mgmt"
1353 if vnfd
["mgmt-interface"].get("ip-address"):
1354 mgmt_access
["ip-address"] = str(vnfd
["mgmt-interface"].get("ip-address"))
1355 if vnfd
["mgmt-interface"].get("cp") and vnfd
.get("vdu"):
1356 if vnfd
["mgmt-interface"]["cp"] not in cp_name2iface_uuid
:
1357 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'cp'['{cp}']. "
1358 "Reference to a non-existing connection-point".format(
1359 vnf
=vnfd_id
, cp
=vnfd
["mgmt-interface"]["cp"]),
1360 httperrors
.Bad_Request
)
1361 mgmt_access
["vm_id"] = cp_name2vm_uuid
[vnfd
["mgmt-interface"]["cp"]]
1362 mgmt_access
["interface_id"] = cp_name2iface_uuid
[vnfd
["mgmt-interface"]["cp"]]
1363 mgmt_access
["vdu-id"] = cp_name2vdu_id
[vnfd
["mgmt-interface"]["cp"]]
1364 # mark this interface as of type mgmt
1365 if cp_name2db_interface
[vnfd
["mgmt-interface"]["cp"]]:
1366 cp_name2db_interface
[vnfd
["mgmt-interface"]["cp"]]["type"] = "mgmt"
1368 default_user
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1371 mgmt_access
["default_user"] = default_user
1373 required
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1376 mgmt_access
["required"] = required
1378 password_
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}),
1381 mgmt_access
["password"] = password_
1384 db_vnf
["mgmt_access"] = yaml
.safe_dump(mgmt_access
, default_flow_style
=True, width
=256)
1386 db_vnfs
.append(db_vnf
)
1390 {"images": db_images
},
1391 {"flavors": db_flavors
},
1392 {"ip_profiles": db_ip_profiles
},
1394 {"interfaces": db_interfaces
},
1397 logger
.debug("create_vnf Deployment done vnfDict: %s",
1398 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
1399 mydb
.new_rows(db_tables
, uuid_list
)
1400 return vnfd_uuid_list
1401 except NfvoException
:
1403 except Exception as e
:
1404 logger
.error("Exception {}".format(e
))
1405 raise # NfvoException("Exception {}".format(e), httperrors.Bad_Request)
1408 @deprecated("Use new_vnfd_v3")
1409 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
1410 global global_config
1412 # Step 1. Check the VNF descriptor
1413 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
1414 # Step 2. Check tenant exist
1416 if tenant_id
!= "any":
1417 check_tenant(mydb
, tenant_id
)
1418 if "tenant_id" in vnf_descriptor
["vnf"]:
1419 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1420 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1421 httperrors
.Unauthorized
)
1423 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1424 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1425 if global_config
["auto_push_VNF_to_VIMs"]:
1426 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1428 # Step 4. Review the descriptor and add missing fields
1429 #print vnf_descriptor
1430 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1431 vnf_name
= vnf_descriptor
['vnf']['name']
1432 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1433 if "physical" in vnf_descriptor
['vnf']:
1434 del vnf_descriptor
['vnf']['physical']
1435 #print vnf_descriptor
1437 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1438 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1439 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1441 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1442 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1443 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1445 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1446 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1448 VNFCitem
["name"] = vnfc
['name']
1449 VNFCitem
["availability_zone"] = vnfc
.get('availability_zone')
1450 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
1452 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1455 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1456 myflavorDict
["description"] = VNFCitem
["description"]
1457 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1458 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1459 myflavorDict
["disk"] = vnfc
.get("disk", 0)
1460 myflavorDict
["extended"] = {}
1462 devices
= vnfc
.get("devices")
1464 myflavorDict
["extended"]["devices"] = devices
1467 # Mapping from processor models to rankings should be available somehow in the NFVO. They could be taken from VIM or directly from a new database table
1468 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1470 # Previous code has been commented
1471 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1472 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1473 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1474 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1476 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1478 # print "Error creating flavor: unknown processor model. Rollback successful."
1479 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1481 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1482 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1484 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1485 myflavorDict
['extended']['numas'] = vnfc
['numas']
1489 # Step 6.2 New flavors are created in the VIM
1490 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1492 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1493 VNFCitem
["flavor_id"] = flavor_id
1494 VNFCDict
[vnfc
['name']] = VNFCitem
1496 logger
.debug("Creating new images in the VIM for each VNFC")
1497 # Step 6.3 New images are created in the VIM
1498 #For each VNFC, we must create the appropriate image.
1499 #This "for" loop might be integrated with the previous one
1500 #In case this integration is made, the VNFCDict might become a VNFClist.
1501 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1502 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1504 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1505 image_dict
['universal_name']=vnfc
.get('image name')
1506 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1507 image_dict
['location']=vnfc
.get('VNFC image')
1508 #image_dict['new_location']=vnfc.get('image location')
1509 image_dict
['checksum']=vnfc
.get('image checksum')
1510 image_metadata_dict
= vnfc
.get('image metadata', None)
1511 image_metadata_str
= None
1512 if image_metadata_dict
is not None:
1513 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1514 image_dict
['metadata']=image_metadata_str
1515 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1516 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1517 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1518 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1519 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1520 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1521 if vnfc
.get("boot-data"):
1522 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1525 # Step 7. Storing the VNF descriptor in the repository
1526 if "descriptor" not in vnf_descriptor
["vnf"]:
1527 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1529 # Step 8. Adding the VNF to the NFVO DB
1530 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1532 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1533 _
, message
= rollback(mydb
, vims
, rollback_list
)
1534 if isinstance(e
, db_base_Exception
):
1535 error_text
= "Exception at database"
1536 elif isinstance(e
, KeyError):
1537 error_text
= "KeyError exception "
1538 e
.http_code
= httperrors
.Internal_Server_Error
1540 error_text
= "Exception at VIM"
1541 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1542 #logger.error("start_scenario %s", error_text)
1543 raise NfvoException(error_text
, e
.http_code
)
1546 @deprecated("Use new_vnfd_v3")
1547 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
1548 global global_config
1550 # Step 1. Check the VNF descriptor
1551 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
1552 # Step 2. Check tenant exist
1554 if tenant_id
!= "any":
1555 check_tenant(mydb
, tenant_id
)
1556 if "tenant_id" in vnf_descriptor
["vnf"]:
1557 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1558 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1559 httperrors
.Unauthorized
)
1561 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1562 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1563 if global_config
["auto_push_VNF_to_VIMs"]:
1564 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1566 # Step 4. Review the descriptor and add missing fields
1567 #print vnf_descriptor
1568 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1569 vnf_name
= vnf_descriptor
['vnf']['name']
1570 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1571 if "physical" in vnf_descriptor
['vnf']:
1572 del vnf_descriptor
['vnf']['physical']
1573 #print vnf_descriptor
1575 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1576 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1577 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1579 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1580 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1581 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1583 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1584 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1586 VNFCitem
["name"] = vnfc
['name']
1587 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
1589 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1592 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1593 myflavorDict
["description"] = VNFCitem
["description"]
1594 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1595 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1596 myflavorDict
["disk"] = vnfc
.get("disk", 0)
1597 myflavorDict
["extended"] = {}
1599 devices
= vnfc
.get("devices")
1601 myflavorDict
["extended"]["devices"] = devices
1604 # Mapping from processor models to rankings should be available somehow in the NFVO. They could be taken from VIM or directly from a new database table
1605 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1607 # Previous code has been commented
1608 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1609 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1610 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1611 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1613 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1615 # print "Error creating flavor: unknown processor model. Rollback successful."
1616 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1618 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1619 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1621 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1622 myflavorDict
['extended']['numas'] = vnfc
['numas']
1626 # Step 6.2 New flavors are created in the VIM
1627 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1629 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1630 VNFCitem
["flavor_id"] = flavor_id
1631 VNFCDict
[vnfc
['name']] = VNFCitem
1633 logger
.debug("Creating new images in the VIM for each VNFC")
1634 # Step 6.3 New images are created in the VIM
1635 #For each VNFC, we must create the appropriate image.
1636 #This "for" loop might be integrated with the previous one
1637 #In case this integration is made, the VNFCDict might become a VNFClist.
1638 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1639 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1641 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1642 image_dict
['universal_name']=vnfc
.get('image name')
1643 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1644 image_dict
['location']=vnfc
.get('VNFC image')
1645 #image_dict['new_location']=vnfc.get('image location')
1646 image_dict
['checksum']=vnfc
.get('image checksum')
1647 image_metadata_dict
= vnfc
.get('image metadata', None)
1648 image_metadata_str
= None
1649 if image_metadata_dict
is not None:
1650 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1651 image_dict
['metadata']=image_metadata_str
1652 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1653 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1654 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1655 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1656 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1657 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1658 if vnfc
.get("boot-data"):
1659 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1661 # Step 7. Storing the VNF descriptor in the repository
1662 if "descriptor" not in vnf_descriptor
["vnf"]:
1663 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1665 # Step 8. Adding the VNF to the NFVO DB
1666 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1668 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1669 _
, message
= rollback(mydb
, vims
, rollback_list
)
1670 if isinstance(e
, db_base_Exception
):
1671 error_text
= "Exception at database"
1672 elif isinstance(e
, KeyError):
1673 error_text
= "KeyError exception "
1674 e
.http_code
= httperrors
.Internal_Server_Error
1676 error_text
= "Exception at VIM"
1677 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1678 #logger.error("start_scenario %s", error_text)
1679 raise NfvoException(error_text
, e
.http_code
)
1682 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
1683 #check valid tenant_id
1684 check_tenant(mydb
, tenant_id
)
1687 if tenant_id
!= "any":
1688 where_or
["tenant_id"] = tenant_id
1689 where_or
["public"] = True
1690 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1692 vnf_id
= vnf
["uuid"]
1693 filter_keys
= ('uuid', 'name', 'description', 'public', "tenant_id", "osm_id", "created_at")
1694 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
1695 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
1696 data
={'vnf' : filtered_content
}
1698 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
1699 SELECT
=('vms.uuid as uuid', 'vms.osm_id as osm_id', 'vms.name as name', 'vms.description as description',
1701 WHERE
={'vnfs.uuid': vnf_id
} )
1702 if len(content
) != 0:
1703 #raise NfvoException("vnf '{}' not found".format(vnf_id), httperrors.Not_Found)
1704 # change boot_data into boot-data
1706 if vm
.get("boot_data"):
1707 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
1710 data
['vnf']['VNFC'] = content
1711 #TODO: GET all the information from a VNFC and include it in the output.
1714 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
1715 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
1716 WHERE
={'vnfs.uuid': vnf_id
} )
1717 data
['vnf']['nets'] = content
1719 #GET ip-profile for each net
1720 for net
in data
['vnf']['nets']:
1721 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1722 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1723 WHERE
={'net_id': net
["uuid"]} )
1724 if len(ipprofiles
)==1:
1725 net
["ip_profile"] = ipprofiles
[0]
1726 elif len(ipprofiles
)>1:
1727 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), httperrors
.Bad_Request
)
1730 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1732 #GET External Interfaces
1733 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1734 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1735 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1736 WHERE
={'vnfs.uuid': vnf_id
, 'interfaces.external_name<>': None} )
1738 data
['vnf']['external-connections'] = content
1743 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1744 # Check tenant exist
1745 if tenant_id
!= "any":
1746 check_tenant(mydb
, tenant_id
)
1747 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1748 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1752 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1754 if tenant_id
!= "any":
1755 where_or
["tenant_id"] = tenant_id
1756 where_or
["public"] = True
1757 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1758 vnf_id
= vnf
["uuid"]
1760 # "Getting the list of flavors and tenants of the VNF"
1761 flavorList
= get_flavorlist(mydb
, vnf_id
)
1762 if len(flavorList
)==0:
1763 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1765 imageList
= get_imagelist(mydb
, vnf_id
)
1766 if len(imageList
)==0:
1767 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1769 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1771 raise NfvoException("vnf '{}' not found".format(vnf_id
), httperrors
.Not_Found
)
1774 for flavor
in flavorList
:
1775 #check if flavor is used by other vnf
1777 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1779 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1781 #flavor not used, must be deleted
1783 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id': flavor
})
1784 for flavor_vim
in c
:
1785 if not flavor_vim
['created']: # skip this flavor because not created by openmano
1789 for vim
in vims
.values():
1790 if vim
["config"]["datacenter_tenant_id"] == flavor_vim
["datacenter_vim_id"]:
1796 myvim
.delete_flavor(flavor_vim
["vim_id"])
1797 except vimconn
.vimconnNotFoundException
:
1798 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"],
1799 flavor_vim
["datacenter_vim_id"] )
1800 except vimconn
.vimconnException
as e
:
1801 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1802 flavor_vim
["vim_id"], flavor_vim
["datacenter_vim_id"], type(e
).__name
__, str(e
))
1803 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"],
1804 flavor_vim
["datacenter_vim_id"]))
1805 # delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1806 mydb
.delete_row_by_id('flavors', flavor
)
1807 except db_base_Exception
as e
:
1808 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1809 undeletedItems
.append("flavor {}".format(flavor
))
1812 for image
in imageList
:
1814 #check if image is used by other vnf
1815 c
= mydb
.get_rows(FROM
='vms', WHERE
=[{'image_id': image
}, {'image_list LIKE ': '%' + image
+ '%'}])
1817 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1819 #image not used, must be deleted
1821 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1823 if image_vim
["datacenter_vim_id"] not in vims
: # TODO change to datacenter_tenant_id
1825 if image_vim
['created']=='false': #skip this image because not created by openmano
1827 myvim
=vims
[ image_vim
["datacenter_id"] ]
1829 myvim
.delete_image(image_vim
["vim_id"])
1830 except vimconn
.vimconnNotFoundException
as e
:
1831 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1832 except vimconn
.vimconnException
as e
:
1833 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1834 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1835 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1836 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1837 mydb
.delete_row_by_id('images', image
)
1838 except db_base_Exception
as e
:
1839 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1840 undeletedItems
.append("image %s" % image
)
1842 return vnf_id
+ " " + vnf
["name"]
1844 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1847 @deprecated("Not used")
1848 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1849 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1853 return -httperrors
.Not_Found
, "datacenter '%s' not found" % datacenter_name
1854 myvim
= vims
.values()[0]
1855 result
,servers
= myvim
.get_hosts_info()
1857 return result
, servers
1858 topology
= {'name':myvim
['name'] , 'servers': servers
}
1859 return result
, topology
1862 def get_hosts(mydb
, nfvo_tenant_id
):
1863 vims
= get_vim(mydb
, nfvo_tenant_id
)
1865 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), httperrors
.Not_Found
)
1867 #print "nfvo.datacenter_action() error. Several datacenters found"
1868 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
1869 myvim
= vims
.values()[0]
1871 hosts
= myvim
.get_hosts()
1872 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1874 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1876 server
={'name':host
['name'], 'vms':[]}
1877 for vm
in host
['instances']:
1878 #get internal name and model
1880 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1881 WHERE
={'vim_vm_id':vm
['id']} )
1883 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1885 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1887 except db_base_Exception
as e
:
1888 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1889 datacenter
['Datacenters'][0]['servers'].append(server
)
1890 #return -400, "en construccion"
1892 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1894 except vimconn
.vimconnException
as e
:
1895 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1898 @deprecated("Use new_nsd_v3")
1899 def new_scenario(mydb
, tenant_id
, topo
):
1901 # result, vims = get_vim(mydb, tenant_id)
1903 # return result, vims
1905 if tenant_id
!= "any":
1906 check_tenant(mydb
, tenant_id
)
1907 if "tenant_id" in topo
:
1908 if topo
["tenant_id"] != tenant_id
:
1909 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1910 httperrors
.Unauthorized
)
1914 #1.1: get VNFs and external_networks (other_nets).
1916 other_nets
={} #external_networks, bridge_networks and data_networkds
1917 nodes
= topo
['topology']['nodes']
1918 for k
in nodes
.keys():
1919 if nodes
[k
]['type'] == 'VNF':
1921 vnfs
[k
]['ifaces'] = {}
1922 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1923 other_nets
[k
] = nodes
[k
]
1924 other_nets
[k
]['external']=True
1925 elif nodes
[k
]['type'] == 'network':
1926 other_nets
[k
] = nodes
[k
]
1927 other_nets
[k
]['external']=False
1930 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1931 for name
,vnf
in vnfs
.items():
1932 where
= {"OR": {"tenant_id": tenant_id
, 'public': "true"}}
1934 error_pos
= "'topology':'nodes':'" + name
+ "'"
1936 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1937 where
['uuid'] = vnf
['vnf_id']
1938 if 'VNF model' in vnf
:
1939 error_text
+= " 'VNF model' " + vnf
['VNF model']
1940 where
['name'] = vnf
['VNF model']
1942 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, httperrors
.Bad_Request
)
1944 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1948 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, httperrors
.Not_Found
)
1950 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", httperrors
.Conflict
)
1951 vnf
['uuid']=vnf_db
[0]['uuid']
1952 vnf
['description']=vnf_db
[0]['description']
1953 #get external interfaces
1954 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1955 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1956 WHERE
={'vnfs.uuid':vnf
['uuid'], 'external_name<>': None} )
1957 for ext_iface
in ext_ifaces
:
1958 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1960 #1.4 get list of connections
1961 conections
= topo
['topology']['connections']
1962 conections_list
= []
1963 conections_list_name
= []
1964 for k
in conections
.keys():
1965 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1966 ifaces_list
= conections
[k
]['nodes'].items()
1967 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1969 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1970 for k2
in conection_pair_list
:
1973 con_type
= conections
[k
].get("type", "link")
1974 if con_type
!= "link":
1976 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), httperrors
.Bad_Request
)
1977 other_nets
[k
] = {'external': False}
1978 if conections
[k
].get("graph"):
1979 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1980 ifaces_list
.append( (k
, None) )
1983 if con_type
== "external_network":
1984 other_nets
[k
]['external'] = True
1985 if conections
[k
].get("model"):
1986 other_nets
[k
]["model"] = conections
[k
]["model"]
1988 other_nets
[k
]["model"] = k
1989 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1990 other_nets
[k
]["model"] = con_type
1992 conections_list_name
.append(k
)
1993 conections_list
.append(set(ifaces_list
)) #from list to set to operate as a set (this conversion removes elements that are repeated in a list)
1994 #print set(ifaces_list)
1995 #check valid VNF and iface names
1996 for iface
in ifaces_list
:
1997 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1998 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1999 str(k
), iface
[0]), httperrors
.Not_Found
)
2000 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
2001 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
2002 str(k
), iface
[0], iface
[1]), httperrors
.Not_Found
)
2004 #1.5 unify connections from the pair list to a consolidated list
2006 while index
< len(conections_list
):
2008 while index2
< len(conections_list
):
2009 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
2010 conections_list
[index
] |
= conections_list
[index2
]
2011 del conections_list
[index2
]
2012 del conections_list_name
[index2
]
2015 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
2017 #for k in conections_list:
2022 #1.6 Delete non external nets
2023 # for k in other_nets.keys():
2024 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
2025 # for con in conections_list:
2027 # for index in range(0,len(con)):
2028 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
2029 # for index in delete_indexes:
2032 #1.7: Check external_ports are present at database table datacenter_nets
2033 for k
,net
in other_nets
.items():
2034 error_pos
= "'topology':'nodes':'" + k
+ "'"
2035 if net
['external']==False:
2036 if 'name' not in net
:
2038 if 'model' not in net
:
2039 raise NfvoException("needed a 'model' at " + error_pos
, httperrors
.Bad_Request
)
2040 if net
['model']=='bridge_net':
2041 net
['type']='bridge';
2042 elif net
['model']=='dataplane_net':
2045 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, httperrors
.Not_Found
)
2047 #IF we do not want to check that external network exist at datacenter
2052 # if 'net_id' in net:
2053 # error_text += " 'net_id' " + net['net_id']
2054 # WHERE_['uuid'] = net['net_id']
2055 # if 'model' in net:
2056 # error_text += " 'model' " + net['model']
2057 # WHERE_['name'] = net['model']
2058 # if len(WHERE_) == 0:
2059 # return -httperrors.Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
2060 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
2061 # FROM='datacenter_nets', WHERE=WHERE_ )
2063 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
2065 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
2066 # return -httperrors.Bad_Request, "unknown " +error_text+ " at " + error_pos
2068 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
2069 # return -httperrors.Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
2070 # other_nets[k].update(net_db[0])
2073 net_nb
=0 #Number of nets
2074 for con
in conections_list
:
2075 #check if this is connected to a external net
2079 for index
in range(0,len(con
)):
2080 #check if this is connected to a external net
2081 for net_key
in other_nets
.keys():
2082 if con
[index
][0]==net_key
:
2083 if other_net_index
>=0:
2084 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
2085 #print "nfvo.new_scenario " + error_text
2086 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2088 other_net_index
= index
2089 net_target
= net_key
2091 #print "other_net_index", other_net_index
2093 if other_net_index
>=0:
2094 del con
[other_net_index
]
2095 #IF we do not want to check that external network exist at datacenter
2096 if other_nets
[net_target
]['external'] :
2097 if "name" not in other_nets
[net_target
]:
2098 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
2099 if other_nets
[net_target
]["type"] == "external_network":
2100 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
2101 other_nets
[net_target
]["type"] = "data"
2103 other_nets
[net_target
]["type"] = "bridge"
2105 # if other_nets[net_target]['external'] :
2106 # type_='data' if len(con)>1 else 'ptp' #an external net is connected to a external port, so it is ptp if only one connection is done to this net
2107 # if type_=='data' and other_nets[net_target]['type']=="ptp":
2108 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
2109 # print "nfvo.new_scenario " + error_text
2110 # return -httperrors.Bad_Request, error_text
2113 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
2116 net_type_bridge
=False
2118 net_target
= "__-__net"+str(net_nb
)
2119 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
2120 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
2123 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
2124 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
2125 if iface_type
=='mgmt' or iface_type
=='bridge':
2126 net_type_bridge
= True
2128 net_type_data
= True
2129 if net_type_bridge
and net_type_data
:
2130 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
2131 #print "nfvo.new_scenario " + error_text
2132 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2133 elif net_type_bridge
:
2136 type_
='data' if len(con
)>2 else 'ptp'
2137 net_list
[net_target
]['type'] = type_
2140 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
2141 #print "nfvo.new_scenario " + error_text
2143 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2145 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
2146 #1.8.1 obtain management net
2147 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
2148 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
2149 #1.8.2 check all interfaces from all vnfs
2151 add_mgmt_net
= False
2152 for vnf
in vnfs
.values():
2153 for iface
in vnf
['ifaces'].values():
2154 if iface
['type']=='mgmt' and 'net_key' not in iface
:
2155 #iface not connected
2156 iface
['net_key'] = 'mgmt'
2158 if add_mgmt_net
and 'mgmt' not in net_list
:
2159 net_list
['mgmt']=mgmt_net
[0]
2160 net_list
['mgmt']['external']=True
2161 net_list
['mgmt']['graph']={'visible':False}
2163 net_list
.update(other_nets
)
2165 #print 'net_list', net_list
2170 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
2171 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
2172 'tenant_id':tenant_id
, 'name':topo
['name'],
2173 'description':topo
.get('description',topo
['name']),
2174 'public': topo
.get('public', False)
2180 @deprecated("Use new_nsd_v3")
2181 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
2182 """ This creates a new scenario for version 0.2 and 0.3"""
2183 scenario
= scenario_dict
["scenario"]
2184 if tenant_id
!= "any":
2185 check_tenant(mydb
, tenant_id
)
2186 if "tenant_id" in scenario
:
2187 if scenario
["tenant_id"] != tenant_id
:
2188 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
2189 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
2190 scenario
["tenant_id"], tenant_id
), httperrors
.Unauthorized
)
2194 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
2195 for name
,vnf
in scenario
["vnfs"].iteritems():
2196 where
= {"OR": {"tenant_id": tenant_id
, 'public': "true"}}
2198 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
2200 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
2201 where
['uuid'] = vnf
['vnf_id']
2202 if 'vnf_name' in vnf
:
2203 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
2204 where
['name'] = vnf
['vnf_name']
2206 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, httperrors
.Bad_Request
)
2207 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
2210 if len(vnf_db
) == 0:
2211 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, httperrors
.Not_Found
)
2212 elif len(vnf_db
) > 1:
2213 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", httperrors
.Conflict
)
2214 vnf
['uuid'] = vnf_db
[0]['uuid']
2215 vnf
['description'] = vnf_db
[0]['description']
2217 # get external interfaces
2218 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
2219 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
2220 WHERE
={'vnfs.uuid':vnf
['uuid'], 'external_name<>': None} )
2221 for ext_iface
in ext_ifaces
:
2222 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
2223 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
2225 # 2: Insert net_key and ip_address at every vnf interface
2226 for net_name
, net
in scenario
["networks"].items():
2227 net_type_bridge
= False
2228 net_type_data
= False
2229 for iface_dict
in net
["interfaces"]:
2230 if version
== "0.2":
2231 temp_dict
= iface_dict
2233 elif version
== "0.3":
2234 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
2235 ip_address
= iface_dict
.get('ip_address', None)
2236 for vnf
, iface
in temp_dict
.items():
2237 if vnf
not in scenario
["vnfs"]:
2238 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
2240 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2241 raise NfvoException(error_text
, httperrors
.Not_Found
)
2242 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
2243 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
2244 .format(net_name
, iface
)
2245 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2246 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2247 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
2248 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
2249 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
2250 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2251 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2252 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
2253 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
2254 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
2255 if iface_type
== 'mgmt' or iface_type
== 'bridge':
2256 net_type_bridge
= True
2258 net_type_data
= True
2260 if net_type_bridge
and net_type_data
:
2261 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
2263 # logger.debug("nfvo.new_scenario " + error_text)
2264 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2265 elif net_type_bridge
:
2268 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
2270 if net
.get("implementation"): # for v0.3
2271 if type_
== "bridge" and net
["implementation"] == "underlay":
2272 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
2273 "'network':'{}'".format(net_name
)
2274 # logger.debug(error_text)
2275 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2276 elif type_
!= "bridge" and net
["implementation"] == "overlay":
2277 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
2278 "'network':'{}'".format(net_name
)
2279 # logger.debug(error_text)
2280 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2281 net
.pop("implementation")
2282 if "type" in net
and version
== "0.3": # for v0.3
2283 if type_
== "data" and net
["type"] == "e-line":
2284 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
2285 "'e-line' at 'network':'{}'".format(net_name
)
2286 # logger.debug(error_text)
2287 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2288 elif type_
== "ptp" and net
["type"] == "e-lan":
2292 net
['name'] = net_name
2293 net
['external'] = net
.get('external', False)
2295 # 3: insert at database
2296 scenario
["nets"] = scenario
["networks"]
2297 scenario
['tenant_id'] = tenant_id
2298 scenario_id
= mydb
.new_scenario(scenario
)
2302 def new_nsd_v3(mydb
, tenant_id
, nsd_descriptor
):
2304 Parses an OSM IM nsd_catalog and insert at DB
2307 :param nsd_descriptor:
2308 :return: The list of created NSD ids
2311 mynsd
= nsd_catalog
.nsd()
2313 pybindJSONDecoder
.load_ietf_json(nsd_descriptor
, None, None, obj
=mynsd
, skip_unknown
=True)
2314 except Exception as e
:
2315 raise NfvoException("Error. Invalid NS descriptor format: " + str(e
), httperrors
.Bad_Request
)
2319 db_sce_interfaces
= []
2322 db_sce_rsp_hops
= []
2323 db_sce_classifiers
= []
2324 db_sce_classifier_matches
= []
2326 db_ip_profiles_index
= 0
2329 for nsd_yang
in mynsd
.nsd_catalog
.nsd
.itervalues():
2330 nsd
= nsd_yang
.get()
2333 scenario_uuid
= str(uuid4())
2334 uuid_list
.append(scenario_uuid
)
2335 nsd_uuid_list
.append(scenario_uuid
)
2337 "uuid": scenario_uuid
,
2338 "osm_id": get_str(nsd
, "id", 255),
2339 "name": get_str(nsd
, "name", 255),
2340 "description": get_str(nsd
, "description", 255),
2341 "tenant_id": tenant_id
,
2342 "vendor": get_str(nsd
, "vendor", 255),
2343 "short_name": get_str(nsd
, "short-name", 255),
2344 "descriptor": str(nsd_descriptor
)[:60000],
2346 db_scenarios
.append(db_scenario
)
2348 # table sce_vnfs (constituent-vnfd)
2349 vnf_index2scevnf_uuid
= {}
2350 vnf_index2vnf_uuid
= {}
2351 for vnf
in nsd
.get("constituent-vnfd").itervalues():
2352 existing_vnf
= mydb
.get_rows(FROM
="vnfs", WHERE
={'osm_id': str(vnf
["vnfd-id-ref"])[:255],
2353 'tenant_id': tenant_id
})
2354 if not existing_vnf
:
2355 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'constituent-vnfd':'vnfd-id-ref':"
2356 "'{}'. Reference to a non-existing VNFD in the catalog".format(
2357 str(nsd
["id"]), str(vnf
["vnfd-id-ref"])[:255]),
2358 httperrors
.Bad_Request
)
2359 sce_vnf_uuid
= str(uuid4())
2360 uuid_list
.append(sce_vnf_uuid
)
2362 "uuid": sce_vnf_uuid
,
2363 "scenario_id": scenario_uuid
,
2364 # "name": get_str(vnf, "member-vnf-index", 255),
2365 "name": existing_vnf
[0]["name"][:200] + "." + get_str(vnf
, "member-vnf-index", 50),
2366 "vnf_id": existing_vnf
[0]["uuid"],
2367 "member_vnf_index": str(vnf
["member-vnf-index"]),
2368 # TODO 'start-by-default': True
2370 vnf_index2scevnf_uuid
[str(vnf
['member-vnf-index'])] = sce_vnf_uuid
2371 vnf_index2vnf_uuid
[str(vnf
['member-vnf-index'])] = existing_vnf
[0]["uuid"]
2372 db_sce_vnfs
.append(db_sce_vnf
)
2374 # table ip_profiles (ip-profiles)
2375 ip_profile_name2db_table_index
= {}
2376 for ip_profile
in nsd
.get("ip-profiles").itervalues():
2378 "ip_version": str(ip_profile
["ip-profile-params"].get("ip-version", "ipv4")),
2379 "subnet_address": str(ip_profile
["ip-profile-params"].get("subnet-address")),
2380 "gateway_address": str(ip_profile
["ip-profile-params"].get("gateway-address")),
2381 "dhcp_enabled": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("enabled", True)),
2382 "dhcp_start_address": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("start-address")),
2383 "dhcp_count": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("count")),
2386 for dns
in ip_profile
["ip-profile-params"]["dns-server"].itervalues():
2387 dns_list
.append(str(dns
.get("address")))
2388 db_ip_profile
["dns_address"] = ";".join(dns_list
)
2389 if ip_profile
["ip-profile-params"].get('security-group'):
2390 db_ip_profile
["security_group"] = ip_profile
["ip-profile-params"]['security-group']
2391 ip_profile_name2db_table_index
[str(ip_profile
["name"])] = db_ip_profiles_index
2392 db_ip_profiles_index
+= 1
2393 db_ip_profiles
.append(db_ip_profile
)
2395 # table sce_nets (internal-vld)
2396 for vld
in nsd
.get("vld").itervalues():
2397 sce_net_uuid
= str(uuid4())
2398 uuid_list
.append(sce_net_uuid
)
2400 "uuid": sce_net_uuid
,
2401 "name": get_str(vld
, "name", 255),
2402 "scenario_id": scenario_uuid
,
2404 "multipoint": not vld
.get("type") == "ELINE",
2405 "osm_id": get_str(vld
, "id", 255),
2407 "description": get_str(vld
, "description", 255),
2409 # guess type of network
2410 if vld
.get("mgmt-network"):
2411 db_sce_net
["type"] = "bridge"
2412 db_sce_net
["external"] = True
2413 elif vld
.get("provider-network").get("overlay-type") == "VLAN":
2414 db_sce_net
["type"] = "data"
2416 # later on it will be fixed to bridge or data depending on the type of interfaces attached to it
2417 db_sce_net
["type"] = None
2418 db_sce_nets
.append(db_sce_net
)
2420 # ip-profile, link db_ip_profile with db_sce_net
2421 if vld
.get("ip-profile-ref"):
2422 ip_profile_name
= vld
.get("ip-profile-ref")
2423 if ip_profile_name
not in ip_profile_name2db_table_index
:
2424 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'ip-profile-ref':'{}'."
2425 " Reference to a non-existing 'ip_profiles'".format(
2426 str(nsd
["id"]), str(vld
["id"]), str(vld
["ip-profile-ref"])),
2427 httperrors
.Bad_Request
)
2428 db_ip_profiles
[ip_profile_name2db_table_index
[ip_profile_name
]]["sce_net_id"] = sce_net_uuid
2429 elif vld
.get("vim-network-name"):
2430 db_sce_net
["vim_network_name"] = get_str(vld
, "vim-network-name", 255)
2433 # table sce_interfaces (vld:vnfd-connection-point-ref)
2434 for iface
in vld
.get("vnfd-connection-point-ref").itervalues():
2435 # Check if there are VDUs in the descriptor
2436 vnf_index
= str(iface
['member-vnf-index-ref'])
2437 existing_vdus
= mydb
.get_rows(SELECT
=('vms.uuid'), FROM
="vms", WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
]})
2439 # check correct parameters
2440 if vnf_index
not in vnf_index2vnf_uuid
:
2441 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2442 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2443 "'nsd':'constituent-vnfd'".format(
2444 str(nsd
["id"]), str(vld
["id"]), str(iface
["member-vnf-index-ref"])),
2445 httperrors
.Bad_Request
)
2447 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid', 'i.type as iface_type'),
2448 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2449 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2450 'external_name': get_str(iface
, "vnfd-connection-point-ref",
2452 if not existing_ifaces
:
2453 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2454 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2455 "connection-point name at VNFD '{}'".format(
2456 str(nsd
["id"]), str(vld
["id"]), str(iface
["vnfd-connection-point-ref"]),
2457 str(iface
.get("vnfd-id-ref"))[:255]),
2458 httperrors
.Bad_Request
)
2459 interface_uuid
= existing_ifaces
[0]["uuid"]
2460 if existing_ifaces
[0]["iface_type"] == "data":
2461 db_sce_net
["type"] = "data"
2462 sce_interface_uuid
= str(uuid4())
2463 uuid_list
.append(sce_net_uuid
)
2464 iface_ip_address
= None
2465 if iface
.get("ip-address"):
2466 iface_ip_address
= str(iface
.get("ip-address"))
2467 db_sce_interface
= {
2468 "uuid": sce_interface_uuid
,
2469 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2470 "sce_net_id": sce_net_uuid
,
2471 "interface_id": interface_uuid
,
2472 "ip_address": iface_ip_address
,
2474 db_sce_interfaces
.append(db_sce_interface
)
2475 if not db_sce_net
["type"]:
2476 db_sce_net
["type"] = "bridge"
2478 # table sce_vnffgs (vnffgd)
2479 for vnffg
in nsd
.get("vnffgd").itervalues():
2480 sce_vnffg_uuid
= str(uuid4())
2481 uuid_list
.append(sce_vnffg_uuid
)
2483 "uuid": sce_vnffg_uuid
,
2484 "name": get_str(vnffg
, "name", 255),
2485 "scenario_id": scenario_uuid
,
2486 "vendor": get_str(vnffg
, "vendor", 255),
2487 "description": get_str(vld
, "description", 255),
2489 db_sce_vnffgs
.append(db_sce_vnffg
)
2492 for rsp
in vnffg
.get("rsp").itervalues():
2493 sce_rsp_uuid
= str(uuid4())
2494 uuid_list
.append(sce_rsp_uuid
)
2496 "uuid": sce_rsp_uuid
,
2497 "name": get_str(rsp
, "name", 255),
2498 "sce_vnffg_id": sce_vnffg_uuid
,
2499 "id": get_str(rsp
, "id", 255), # only useful to link with classifiers; will be removed later in the code
2501 db_sce_rsps
.append(db_sce_rsp
)
2502 for iface
in rsp
.get("vnfd-connection-point-ref").itervalues():
2503 vnf_index
= str(iface
['member-vnf-index-ref'])
2504 if_order
= int(iface
['order'])
2505 # check correct parameters
2506 if vnf_index
not in vnf_index2vnf_uuid
:
2507 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2508 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2509 "'nsd':'constituent-vnfd'".format(
2510 str(nsd
["id"]), str(rsp
["id"]), str(iface
["member-vnf-index-ref"])),
2511 httperrors
.Bad_Request
)
2513 ingress_existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2514 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2516 'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2517 'external_name': get_str(iface
, "vnfd-ingress-connection-point-ref",
2519 if not ingress_existing_ifaces
:
2520 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2521 "-ref':'vnfd-ingress-connection-point-ref':'{}'. Reference to a non-existing "
2522 "connection-point name at VNFD '{}'".format(
2523 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-ingress-connection-point-ref"]),
2524 str(iface
.get("vnfd-id-ref"))[:255]), httperrors
.Bad_Request
)
2526 egress_existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2527 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2529 'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2530 'external_name': get_str(iface
, "vnfd-egress-connection-point-ref",
2532 if not egress_existing_ifaces
:
2533 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2534 "-ref':'vnfd-egress-connection-point-ref':'{}'. Reference to a non-existing "
2535 "connection-point name at VNFD '{}'".format(
2536 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-egress-connection-point-ref"]),
2537 str(iface
.get("vnfd-id-ref"))[:255]), HTTP_Bad_Request
)
2539 ingress_interface_uuid
= ingress_existing_ifaces
[0]["uuid"]
2540 egress_interface_uuid
= egress_existing_ifaces
[0]["uuid"]
2541 sce_rsp_hop_uuid
= str(uuid4())
2542 uuid_list
.append(sce_rsp_hop_uuid
)
2544 "uuid": sce_rsp_hop_uuid
,
2545 "if_order": if_order
,
2546 "ingress_interface_id": ingress_interface_uuid
,
2547 "egress_interface_id": egress_interface_uuid
,
2548 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2549 "sce_rsp_id": sce_rsp_uuid
,
2551 db_sce_rsp_hops
.append(db_sce_rsp_hop
)
2553 # deal with classifiers
2554 for classifier
in vnffg
.get("classifier").itervalues():
2555 sce_classifier_uuid
= str(uuid4())
2556 uuid_list
.append(sce_classifier_uuid
)
2559 vnf_index
= str(classifier
['member-vnf-index-ref'])
2560 if vnf_index
not in vnf_index2vnf_uuid
:
2561 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'classifier[{}]':'vnfd-connection-point"
2562 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2563 "'nsd':'constituent-vnfd'".format(
2564 str(nsd
["id"]), str(classifier
["id"]), str(classifier
["member-vnf-index-ref"])),
2565 httperrors
.Bad_Request
)
2566 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2567 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2568 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2569 'external_name': get_str(classifier
, "vnfd-connection-point-ref",
2571 if not existing_ifaces
:
2572 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2573 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2574 "connection-point name at VNFD '{}'".format(
2575 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-connection-point-ref"]),
2576 str(iface
.get("vnfd-id-ref"))[:255]),
2577 httperrors
.Bad_Request
)
2578 interface_uuid
= existing_ifaces
[0]["uuid"]
2580 db_sce_classifier
= {
2581 "uuid": sce_classifier_uuid
,
2582 "name": get_str(classifier
, "name", 255),
2583 "sce_vnffg_id": sce_vnffg_uuid
,
2584 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2585 "interface_id": interface_uuid
,
2587 rsp_id
= get_str(classifier
, "rsp-id-ref", 255)
2588 rsp
= next((item
for item
in db_sce_rsps
if item
["id"] == rsp_id
), None)
2589 db_sce_classifier
["sce_rsp_id"] = rsp
["uuid"]
2590 db_sce_classifiers
.append(db_sce_classifier
)
2592 for match
in classifier
.get("match-attributes").itervalues():
2593 sce_classifier_match_uuid
= str(uuid4())
2594 uuid_list
.append(sce_classifier_match_uuid
)
2595 db_sce_classifier_match
= {
2596 "uuid": sce_classifier_match_uuid
,
2597 "ip_proto": get_str(match
, "ip-proto", 2),
2598 "source_ip": get_str(match
, "source-ip-address", 16),
2599 "destination_ip": get_str(match
, "destination-ip-address", 16),
2600 "source_port": get_str(match
, "source-port", 5),
2601 "destination_port": get_str(match
, "destination-port", 5),
2602 "sce_classifier_id": sce_classifier_uuid
,
2604 db_sce_classifier_matches
.append(db_sce_classifier_match
)
2607 # remove unneeded id's in sce_rsps
2608 for rsp
in db_sce_rsps
:
2612 {"scenarios": db_scenarios
},
2613 {"sce_nets": db_sce_nets
},
2614 {"ip_profiles": db_ip_profiles
},
2615 {"sce_vnfs": db_sce_vnfs
},
2616 {"sce_interfaces": db_sce_interfaces
},
2617 {"sce_vnffgs": db_sce_vnffgs
},
2618 {"sce_rsps": db_sce_rsps
},
2619 {"sce_rsp_hops": db_sce_rsp_hops
},
2620 {"sce_classifiers": db_sce_classifiers
},
2621 {"sce_classifier_matches": db_sce_classifier_matches
},
2624 logger
.debug("new_nsd_v3 done: %s",
2625 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
2626 mydb
.new_rows(db_tables
, uuid_list
)
2627 return nsd_uuid_list
2628 except NfvoException
:
2630 except Exception as e
:
2631 logger
.error("Exception {}".format(e
))
2632 raise # NfvoException("Exception {}".format(e), httperrors.Bad_Request)
2635 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
2636 data
["uuid"] = scenario_id
2637 data
["tenant_id"] = tenant_id
2638 c
= mydb
.edit_scenario( data
)
2642 @deprecated("Use create_instance")
2643 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
2644 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2645 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
2646 vims
= {datacenter_id
: myvim
}
2647 myvim_tenant
= myvim
['tenant_id']
2648 datacenter_name
= myvim
['name']
2652 #print "Checking that the scenario_id exists and getting the scenario dictionary"
2653 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
=datacenter_id
)
2654 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
2655 scenarioDict
['datacenter_id'] = datacenter_id
2656 #print '================scenarioDict======================='
2657 #print json.dumps(scenarioDict, indent=4)
2658 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
2660 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
2661 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2663 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
2664 auxNetDict
['scenario'] = {}
2666 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
2667 for sce_net
in scenarioDict
['nets']:
2668 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
2670 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
2671 myNetName
= myNetName
[0:255] #limit length
2672 myNetType
= sce_net
['type']
2674 myNetDict
["name"] = myNetName
2675 myNetDict
["type"] = myNetType
2676 myNetDict
["tenant_id"] = myvim_tenant
2677 myNetIPProfile
= sce_net
.get('ip_profile', None)
2678 myProviderNetwork
= sce_net
.get('provider_network', None)
2680 #We should use the dictionary as input parameter for new_network
2682 if not sce_net
["external"]:
2683 network_id
, _
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
, provider_network_profile
=myProviderNetwork
)
2684 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
2685 sce_net
['vim_id'] = network_id
2686 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
2687 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2688 sce_net
["created"] = True
2690 if sce_net
['vim_id'] == None:
2691 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
2692 _
, message
= rollback(mydb
, vims
, rollbackList
)
2693 logger
.error("nfvo.start_scenario: %s", error_text
)
2694 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2695 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
2696 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
2698 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
2699 #For each vnf net, we create it and we add it to instanceNetlist.
2701 for sce_vnf
in scenarioDict
['vnfs']:
2702 for net
in sce_vnf
['nets']:
2703 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
2705 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
2706 myNetName
= myNetName
[0:255] #limit length
2707 myNetType
= net
['type']
2709 myNetDict
["name"] = myNetName
2710 myNetDict
["type"] = myNetType
2711 myNetDict
["tenant_id"] = myvim_tenant
2712 myNetIPProfile
= net
.get('ip_profile', None)
2713 myProviderNetwork
= sce_net
.get('provider_network', None)
2716 #We should use the dictionary as input parameter for new_network
2717 network_id
, _
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
, provider_network_profile
=myProviderNetwork
)
2718 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
2719 net
['vim_id'] = network_id
2720 if sce_vnf
['uuid'] not in auxNetDict
:
2721 auxNetDict
[sce_vnf
['uuid']] = {}
2722 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
2723 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2724 net
["created"] = True
2726 #print "auxNetDict:"
2727 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2729 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
2730 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2732 for sce_vnf
in scenarioDict
['vnfs']:
2733 vnf_availability_zones
= []
2734 for vm
in sce_vnf
['vms']:
2735 vm_av
= vm
.get('availability_zone')
2736 if vm_av
and vm_av
not in vnf_availability_zones
:
2737 vnf_availability_zones
.append(vm_av
)
2739 # check if there is enough availability zones available at vim level.
2740 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
2741 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
2742 raise NfvoException('No enough availability zones at VIM for this deployment', httperrors
.Bad_Request
)
2744 for vm
in sce_vnf
['vms']:
2747 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
2748 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
2749 #myVMDict['description'] = vm['description']
2750 myVMDict
['description'] = myVMDict
['name'][0:99]
2752 myVMDict
['start'] = "no"
2753 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2754 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
2756 #create image at vim in case it not exist
2757 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2758 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
2759 vm
['vim_image_id'] = image_id
2761 #create flavor at vim in case it not exist
2762 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2763 if flavor_dict
['extended']!=None:
2764 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2765 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
2766 vm
['vim_flavor_id'] = flavor_id
2769 myVMDict
['imageRef'] = vm
['vim_image_id']
2770 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2771 myVMDict
['networks'] = []
2772 for iface
in vm
['interfaces']:
2774 if iface
['type']=="data":
2775 netDict
['type'] = iface
['model']
2776 elif "model" in iface
and iface
["model"]!=None:
2777 netDict
['model']=iface
['model']
2778 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2779 #discover type of interface looking at flavor
2780 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2781 for flavor_iface
in numa
.get('interfaces',[]):
2782 if flavor_iface
.get('name') == iface
['internal_name']:
2783 if flavor_iface
['dedicated'] == 'yes':
2784 netDict
['type']="PF" #passthrough
2785 elif flavor_iface
['dedicated'] == 'no':
2786 netDict
['type']="VF" #siov
2787 elif flavor_iface
['dedicated'] == 'yes:sriov':
2788 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2789 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2791 netDict
["use"]=iface
['type']
2792 if netDict
["use"]=="data" and not netDict
.get("type"):
2793 #print "netDict", netDict
2794 #print "iface", iface
2795 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'])
2796 if flavor_dict
.get('extended')==None:
2797 raise NfvoException(e_text
+ "After database migration some information is not available. \
2798 Try to delete and create the scenarios and VNFs again", httperrors
.Conflict
)
2800 raise NfvoException(e_text
, httperrors
.Internal_Server_Error
)
2801 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2802 netDict
["type"]="virtual"
2803 if "vpci" in iface
and iface
["vpci"] is not None:
2804 netDict
['vpci'] = iface
['vpci']
2805 if "mac" in iface
and iface
["mac"] is not None:
2806 netDict
['mac_address'] = iface
['mac']
2807 if "port-security" in iface
and iface
["port-security"] is not None:
2808 netDict
['port_security'] = iface
['port-security']
2809 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2810 netDict
['floating_ip'] = iface
['floating-ip']
2811 netDict
['name'] = iface
['internal_name']
2812 if iface
['net_id'] is None:
2813 for vnf_iface
in sce_vnf
["interfaces"]:
2816 if vnf_iface
['interface_id']==iface
['uuid']:
2817 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
2820 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2821 #skip bridge ifaces not connected to any net
2822 #if 'net_id' not in netDict or netDict['net_id']==None:
2824 myVMDict
['networks'].append(netDict
)
2825 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2826 #print myVMDict['name']
2827 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2828 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2829 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2831 if 'availability_zone' in myVMDict
:
2832 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
2836 vm_id
, _
= myvim
.new_vminstance(myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2837 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2838 availability_zone_index
=av_index
,
2839 availability_zone_list
=vnf_availability_zones
)
2840 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
2841 vm
['vim_id'] = vm_id
2842 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2843 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2844 for net
in myVMDict
['networks']:
2846 for iface
in vm
['interfaces']:
2847 if net
["name"]==iface
["internal_name"]:
2848 iface
["vim_id"]=net
["vim_id"]
2851 logger
.debug("start scenario Deployment done")
2852 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2853 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
2854 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
2855 return mydb
.get_instance_scenario(instance_id
)
2857 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
2858 _
, message
= rollback(mydb
, vims
, rollbackList
)
2859 if isinstance(e
, db_base_Exception
):
2860 error_text
= "Exception at database"
2862 error_text
= "Exception at VIM"
2863 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2864 #logger.error("start_scenario %s", error_text)
2865 raise NfvoException(error_text
, e
.http_code
)
2867 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
2868 """ join the cloud config information into cloud_config_preserve.
2869 In case of conflict cloud_config_preserve preserves
2872 if not cloud_config_preserve
and not cloud_config
:
2875 new_cloud_config
= {"key-pairs":[], "users":[]}
2877 if cloud_config_preserve
:
2878 for key
in cloud_config_preserve
.get("key-pairs", () ):
2879 if key
not in new_cloud_config
["key-pairs"]:
2880 new_cloud_config
["key-pairs"].append(key
)
2882 for key
in cloud_config
.get("key-pairs", () ):
2883 if key
not in new_cloud_config
["key-pairs"]:
2884 new_cloud_config
["key-pairs"].append(key
)
2885 if not new_cloud_config
["key-pairs"]:
2886 del new_cloud_config
["key-pairs"]
2890 new_cloud_config
["users"] += cloud_config
.get("users", () )
2891 if cloud_config_preserve
:
2892 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
2893 index_to_delete
= []
2894 users
= new_cloud_config
.get("users", [])
2895 for index0
in range(0,len(users
)):
2896 if index0
in index_to_delete
:
2898 for index1
in range(index0
+1,len(users
)):
2899 if index1
in index_to_delete
:
2901 if users
[index0
]["name"] == users
[index1
]["name"]:
2902 index_to_delete
.append(index1
)
2903 for key
in users
[index1
].get("key-pairs",()):
2904 if "key-pairs" not in users
[index0
]:
2905 users
[index0
]["key-pairs"] = [key
]
2906 elif key
not in users
[index0
]["key-pairs"]:
2907 users
[index0
]["key-pairs"].append(key
)
2908 index_to_delete
.sort(reverse
=True)
2909 for index
in index_to_delete
:
2911 if not new_cloud_config
["users"]:
2912 del new_cloud_config
["users"]
2915 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
2916 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
2917 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
2918 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
2921 new_cloud_config
["user-data"] = []
2922 if cloud_config
and cloud_config
.get("user-data"):
2923 if isinstance(cloud_config
["user-data"], list):
2924 new_cloud_config
["user-data"] += cloud_config
["user-data"]
2926 new_cloud_config
["user-data"].append(cloud_config
["user-data"])
2927 if cloud_config_preserve
and cloud_config_preserve
.get("user-data"):
2928 if isinstance(cloud_config_preserve
["user-data"], list):
2929 new_cloud_config
["user-data"] += cloud_config_preserve
["user-data"]
2931 new_cloud_config
["user-data"].append(cloud_config_preserve
["user-data"])
2932 if not new_cloud_config
["user-data"]:
2933 del new_cloud_config
["user-data"]
2936 new_cloud_config
["config-files"] = []
2937 if cloud_config
and cloud_config
.get("config-files") != None:
2938 new_cloud_config
["config-files"] += cloud_config
["config-files"]
2939 if cloud_config_preserve
:
2940 for file in cloud_config_preserve
.get("config-files", ()):
2941 for index
in range(0, len(new_cloud_config
["config-files"])):
2942 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
2943 new_cloud_config
["config-files"][index
] = file
2946 new_cloud_config
["config-files"].append(file)
2947 if not new_cloud_config
["config-files"]:
2948 del new_cloud_config
["config-files"]
2949 return new_cloud_config
2952 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
2953 datacenter_id
= None
2954 datacenter_name
= None
2957 if datacenter_tenant_id
:
2958 thread_id
= datacenter_tenant_id
2959 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
2961 where_
={"td.nfvo_tenant_id": tenant_id
}
2962 if datacenter_id_name
:
2963 if utils
.check_valid_uuid(datacenter_id_name
):
2964 datacenter_id
= datacenter_id_name
2965 where_
["dt.datacenter_id"] = datacenter_id
2967 datacenter_name
= datacenter_id_name
2968 where_
["d.name"] = datacenter_name
2969 if datacenter_tenant_id
:
2970 where_
["dt.uuid"] = datacenter_tenant_id
2971 datacenters
= mydb
.get_rows(
2972 SELECT
=("dt.uuid as datacenter_tenant_id",),
2973 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
2974 "join datacenters as d on d.uuid=dt.datacenter_id",
2976 if len(datacenters
) > 1:
2977 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
2979 thread_id
= datacenters
[0]["datacenter_tenant_id"]
2980 thread
= vim_threads
["running"].get(thread_id
)
2982 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
2983 return thread_id
, thread
2984 except db_base_Exception
as e
:
2985 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
2988 def get_datacenter_uuid(mydb
, tenant_id
, datacenter_id_name
):
2990 if utils
.check_valid_uuid(datacenter_id_name
):
2991 WHERE_dict
['d.uuid'] = datacenter_id_name
2993 WHERE_dict
['d.name'] = datacenter_id_name
2996 WHERE_dict
['nfvo_tenant_id'] = tenant_id
2997 from_
= "tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join datacenter_tenants as" \
2998 " dt on td.datacenter_tenant_id=dt.uuid"
3000 from_
= 'datacenters as d'
3001 vimaccounts
= mydb
.get_rows(FROM
=from_
, SELECT
=("d.uuid as uuid, d.name as name",), WHERE
=WHERE_dict
)
3002 if len(vimaccounts
) == 0:
3003 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
3004 elif len(vimaccounts
)>1:
3005 #print "nfvo.datacenter_action() error. Several datacenters found"
3006 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
3007 return vimaccounts
[0]["uuid"], vimaccounts
[0]["name"]
3010 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
3011 datacenter_id
= None
3012 datacenter_name
= None
3013 if datacenter_id_name
:
3014 if utils
.check_valid_uuid(datacenter_id_name
):
3015 datacenter_id
= datacenter_id_name
3017 datacenter_name
= datacenter_id_name
3018 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
3020 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
3022 #print "nfvo.datacenter_action() error. Several datacenters found"
3023 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
3024 return vims
.keys()[0], vims
.values()[0]
3028 """Takes dict d and updates it with the values in dict u.
3029 It merges all depth levels"""
3030 for k
, v
in u
.iteritems():
3031 if isinstance(v
, collections
.Mapping
):
3032 r
= update(d
.get(k
, {}), v
)
3039 def create_instance(mydb
, tenant_id
, instance_dict
):
3040 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
3041 # logger.debug("Creating instance...")
3043 scenario
= instance_dict
["scenario"]
3045 # find main datacenter
3047 myvim_threads_id
= {}
3048 datacenter
= instance_dict
.get("datacenter")
3049 default_wim_account
= instance_dict
.get("wim_account")
3050 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3051 myvims
[default_datacenter_id
] = vim
3052 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
3053 tenant
= mydb
.get_rows_by_id('nfvo_tenants', tenant_id
)
3054 # myvim_tenant = myvim['tenant_id']
3057 # print "Checking that the scenario exists and getting the scenario dictionary"
3058 if isinstance(scenario
, str):
3059 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, datacenter_vim_id
=myvim_threads_id
[default_datacenter_id
],
3060 datacenter_id
=default_datacenter_id
)
3062 scenarioDict
= scenario
3063 scenarioDict
["uuid"] = None
3065 # logger.debug(">>>>>> Dictionaries before merging")
3066 # logger.debug(">>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
3067 # logger.debug(">>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
3069 db_instance_vnfs
= []
3070 db_instance_vms
= []
3071 db_instance_interfaces
= []
3072 db_instance_sfis
= []
3073 db_instance_sfs
= []
3074 db_instance_classifications
= []
3075 db_instance_sfps
= []
3080 instance_name
= instance_dict
["name"]
3081 instance_uuid
= str(uuid4())
3082 uuid_list
.append(instance_uuid
)
3083 db_instance_scenario
= {
3084 "uuid": instance_uuid
,
3085 "name": instance_name
,
3086 "tenant_id": tenant_id
,
3087 "scenario_id": scenarioDict
['uuid'],
3088 "datacenter_id": default_datacenter_id
,
3089 # filled bellow 'datacenter_tenant_id'
3090 "description": instance_dict
.get("description"),
3092 if scenarioDict
.get("cloud-config"):
3093 db_instance_scenario
["cloud_config"] = yaml
.safe_dump(scenarioDict
["cloud-config"],
3094 default_flow_style
=True, width
=256)
3095 instance_action_id
= get_task_id()
3096 db_instance_action
= {
3097 "uuid": instance_action_id
, # same uuid for the instance and the action on create
3098 "tenant_id": tenant_id
,
3099 "instance_id": instance_uuid
,
3100 "description": "CREATE",
3103 # Auxiliary dictionaries from x to y
3104 sce_net2instance
= {}
3105 net2task_id
= {'scenario': {}}
3106 # Mapping between local networks and WIMs
3109 def ip_profile_IM2RO(ip_profile_im
):
3110 # translate from input format to database format
3112 if 'subnet-address' in ip_profile_im
:
3113 ip_profile_ro
['subnet_address'] = ip_profile_im
['subnet-address']
3114 if 'ip-version' in ip_profile_im
:
3115 ip_profile_ro
['ip_version'] = ip_profile_im
['ip-version']
3116 if 'gateway-address' in ip_profile_im
:
3117 ip_profile_ro
['gateway_address'] = ip_profile_im
['gateway-address']
3118 if 'dns-address' in ip_profile_im
:
3119 ip_profile_ro
['dns_address'] = ip_profile_im
['dns-address']
3120 if isinstance(ip_profile_ro
['dns_address'], (list, tuple)):
3121 ip_profile_ro
['dns_address'] = ";".join(ip_profile_ro
['dns_address'])
3122 if 'dhcp' in ip_profile_im
:
3123 ip_profile_ro
['dhcp_start_address'] = ip_profile_im
['dhcp'].get('start-address')
3124 ip_profile_ro
['dhcp_enabled'] = ip_profile_im
['dhcp'].get('enabled', True)
3125 ip_profile_ro
['dhcp_count'] = ip_profile_im
['dhcp'].get('count')
3126 return ip_profile_ro
3128 # logger.debug("Creating instance from scenario-dict:\n%s",
3129 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
3131 # 0 check correct parameters
3132 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).iteritems():
3133 for scenario_net
in scenarioDict
['nets']:
3134 if net_name
== scenario_net
.get("name") or net_name
== scenario_net
.get("osm_id") or net_name
== scenario_net
.get("uuid"):
3137 raise NfvoException("Invalid scenario network name or id '{}' at instance:networks".format(net_name
),
3138 httperrors
.Bad_Request
)
3139 if "sites" not in net_instance_desc
:
3140 net_instance_desc
["sites"] = [ {} ]
3141 site_without_datacenter_field
= False
3142 for site
in net_instance_desc
["sites"]:
3143 if site
.get("datacenter"):
3144 site
["datacenter"], _
= get_datacenter_uuid(mydb
, tenant_id
, site
["datacenter"])
3145 if site
["datacenter"] not in myvims
:
3146 # Add this datacenter to myvims
3147 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
3149 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
3150 site
["datacenter"] = d
# change name to id
3152 if site_without_datacenter_field
:
3153 raise NfvoException("Found more than one entries without datacenter field at "
3154 "instance:networks:{}:sites".format(net_name
), httperrors
.Bad_Request
)
3155 site_without_datacenter_field
= True
3156 site
["datacenter"] = default_datacenter_id
# change name to id
3158 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
3159 for scenario_vnf
in scenarioDict
['vnfs']:
3160 if vnf_name
== scenario_vnf
['member_vnf_index'] or vnf_name
== scenario_vnf
['uuid'] or vnf_name
== scenario_vnf
['name']:
3163 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_name
), httperrors
.Bad_Request
)
3164 if "datacenter" in vnf_instance_desc
:
3165 # Add this datacenter to myvims
3166 vnf_instance_desc
["datacenter"], _
= get_datacenter_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3167 if vnf_instance_desc
["datacenter"] not in myvims
:
3168 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3170 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3171 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
3173 for net_id
, net_instance_desc
in vnf_instance_desc
.get("networks", {}).iteritems():
3174 for scenario_net
in scenario_vnf
['nets']:
3175 if net_id
== scenario_net
['osm_id'] or net_id
== scenario_net
['uuid'] or net_id
== scenario_net
["name"]:
3178 raise NfvoException("Invalid net id or name '{}' at instance:vnfs:networks".format(net_id
), httperrors
.Bad_Request
)
3179 if net_instance_desc
.get("vim-network-name"):
3180 scenario_net
["vim-network-name"] = net_instance_desc
["vim-network-name"]
3181 if net_instance_desc
.get("vim-network-id"):
3182 scenario_net
["vim-network-id"] = net_instance_desc
["vim-network-id"]
3183 if net_instance_desc
.get("name"):
3184 scenario_net
["name"] = net_instance_desc
["name"]
3185 if 'ip-profile' in net_instance_desc
:
3186 ipprofile_db
= ip_profile_IM2RO(net_instance_desc
['ip-profile'])
3187 if 'ip_profile' not in scenario_net
:
3188 scenario_net
['ip_profile'] = ipprofile_db
3190 update(scenario_net
['ip_profile'], ipprofile_db
)
3192 if 'provider-network' in net_instance_desc
:
3193 provider_network_db
= net_instance_desc
['provider-network']
3194 if 'provider-network' not in scenario_net
:
3195 scenario_net
['provider-network'] = provider_network_db
3197 update(scenario_net
['provider-network'], provider_network_db
)
3199 for vdu_id
, vdu_instance_desc
in vnf_instance_desc
.get("vdus", {}).iteritems():
3200 for scenario_vm
in scenario_vnf
['vms']:
3201 if vdu_id
== scenario_vm
['osm_id'] or vdu_id
== scenario_vm
["name"]:
3204 raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id
), httperrors
.Bad_Request
)
3205 scenario_vm
["instance_parameters"] = vdu_instance_desc
3206 for iface_id
, iface_instance_desc
in vdu_instance_desc
.get("interfaces", {}).iteritems():
3207 for scenario_interface
in scenario_vm
['interfaces']:
3208 if iface_id
== scenario_interface
['internal_name'] or iface_id
== scenario_interface
["external_name"]:
3209 scenario_interface
.update(iface_instance_desc
)
3212 raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id
), httperrors
.Bad_Request
)
3214 # 0.1 parse cloud-config parameters
3215 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
3217 # 0.2 merge instance information into scenario
3218 # Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
3219 # However, this is not possible yet.
3220 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).iteritems():
3222 for scenario_net
in scenarioDict
['nets']:
3223 if net_name
== scenario_net
.get("name") or net_name
== scenario_net
.get("osm_id") or net_name
== scenario_net
.get("uuid"):
3224 if "wim_account" in net_instance_desc
and net_instance_desc
["wim_account"] is not None:
3225 scenario_net
["wim_account"] = net_instance_desc
["wim_account"]
3226 if 'ip-profile' in net_instance_desc
:
3227 ipprofile_db
= ip_profile_IM2RO(net_instance_desc
['ip-profile'])
3228 if 'ip_profile' not in scenario_net
:
3229 scenario_net
['ip_profile'] = ipprofile_db
3231 update(scenario_net
['ip_profile'], ipprofile_db
)
3232 if 'provider-network' in net_instance_desc
:
3233 provider_network_db
= net_instance_desc
['provider-network']
3235 if 'provider-network' not in scenario_net
:
3236 scenario_net
['provider_network'] = provider_network_db
3238 update(scenario_net
['provider-network'], provider_network_db
)
3240 for interface
in net_instance_desc
.get('interfaces', ()):
3241 if 'ip_address' in interface
:
3242 for vnf
in scenarioDict
['vnfs']:
3243 if interface
['vnf'] == vnf
['name']:
3244 for vnf_interface
in vnf
['interfaces']:
3245 if interface
['vnf_interface'] == vnf_interface
['external_name']:
3246 vnf_interface
['ip_address'] = interface
['ip_address']
3248 # logger.debug(">>>>>>>> Merged dictionary")
3249 # logger.debug("Creating instance scenario-dict MERGED:\n%s",
3250 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
3253 # 1. Creating new nets (sce_nets) in the VIM"
3254 number_mgmt_networks
= 0
3255 db_instance_nets
= []
3256 for sce_net
in scenarioDict
['nets']:
3258 sce_net_uuid
= sce_net
.get('uuid', sce_net
["name"])
3259 # get involved datacenters where this network need to be created
3260 involved_datacenters
= []
3261 for sce_vnf
in scenarioDict
.get("vnfs", ()):
3262 vnf_datacenter
= sce_vnf
.get("datacenter", default_datacenter_id
)
3263 if vnf_datacenter
in involved_datacenters
:
3265 if sce_vnf
.get("interfaces"):
3266 for sce_vnf_ifaces
in sce_vnf
["interfaces"]:
3267 if sce_vnf_ifaces
.get("sce_net_id") == sce_net
["uuid"]:
3268 involved_datacenters
.append(vnf_datacenter
)
3270 if not involved_datacenters
:
3271 involved_datacenters
.append(default_datacenter_id
)
3272 target_wim_account
= sce_net
.get("wim_account", default_wim_account
)
3275 # TODO: use this information during network creation
3276 wim_account_id
= wim_account_name
= None
3277 if len(involved_datacenters
) > 1 and 'uuid' in sce_net
:
3278 if target_wim_account
is None or target_wim_account
is True: # automatic selection of WIM
3279 # OBS: sce_net without uuid are used internally to VNFs
3280 # and the assumption is that VNFs will not be split among
3281 # different datacenters
3282 wim_account
= wim_engine
.find_suitable_wim_account(
3283 involved_datacenters
, tenant_id
)
3284 wim_account_id
= wim_account
['uuid']
3285 wim_account_name
= wim_account
['name']
3286 wim_usage
[sce_net
['uuid']] = wim_account_id
3287 elif isinstance(target_wim_account
, str): # manual selection of WIM
3288 wim_account
.persist
.get_wim_account_by(target_wim_account
, tenant_id
)
3289 wim_account_id
= wim_account
['uuid']
3290 wim_account_name
= wim_account
['name']
3291 wim_usage
[sce_net
['uuid']] = wim_account_id
3292 else: # not WIM usage
3293 wim_usage
[sce_net
['uuid']] = False
3297 if instance_dict
.get("networks"):
3298 if sce_net
.get("uuid") in instance_dict
["networks"]:
3299 descriptor_net
= instance_dict
["networks"][sce_net
["uuid"]]
3300 descriptor_net_name
= sce_net
["uuid"]
3301 elif sce_net
.get("osm_id") in instance_dict
["networks"]:
3302 descriptor_net
= instance_dict
["networks"][sce_net
["osm_id"]]
3303 descriptor_net_name
= sce_net
["osm_id"]
3304 elif sce_net
["name"] in instance_dict
["networks"]:
3305 descriptor_net
= instance_dict
["networks"][sce_net
["name"]]
3306 descriptor_net_name
= sce_net
["name"]
3307 net_name
= descriptor_net
.get("vim-network-name")
3308 # add datacenters from instantiation parameters
3309 if descriptor_net
.get("sites"):
3310 for site
in descriptor_net
["sites"]:
3311 if site
.get("datacenter") and site
["datacenter"] not in involved_datacenters
:
3312 involved_datacenters
.append(site
["datacenter"])
3313 sce_net2instance
[sce_net_uuid
] = {}
3314 net2task_id
['scenario'][sce_net_uuid
] = {}
3317 related_network
= None
3318 if descriptor_net
.get("use-network"):
3319 target_instance_nets
= mydb
.get_rows(
3321 FROM
="instance_nets",
3322 WHERE
={"instance_scenario_id": descriptor_net
["use-network"]["instance_scenario_id"],
3323 "osm_id": descriptor_net
["use-network"]["osm_id"]},
3325 if not target_instance_nets
:
3326 raise NfvoException(
3327 "Cannot find the target network at instance:networks[{}]:use-network".format(descriptor_net_name
),
3328 httperrors
.Bad_Request
)
3330 use_network
= target_instance_nets
[0]["related"]
3332 if sce_net
["external"]:
3333 number_mgmt_networks
+= 1
3335 for datacenter_id
in involved_datacenters
:
3337 netmap_create
= None
3338 if descriptor_net
.get("sites"):
3339 for site
in descriptor_net
["sites"]:
3340 if site
.get("datacenter") == datacenter_id
:
3341 netmap_use
= site
.get("netmap-use")
3342 netmap_create
= site
.get("netmap-create")
3345 vim
= myvims
[datacenter_id
]
3346 myvim_thread_id
= myvim_threads_id
[datacenter_id
]
3348 net_type
= sce_net
['type']
3350 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} # 'shared': True
3353 if sce_net
["external"]:
3354 net_name
= sce_net
["name"]
3356 net_name
= "{}-{}".format(instance_name
, sce_net
["name"])
3357 net_name
= net_name
[:255] # limit length
3359 if netmap_use
or netmap_create
:
3360 create_network
= False
3361 lookfor_network
= False
3363 lookfor_network
= True
3364 if utils
.check_valid_uuid(netmap_use
):
3365 lookfor_filter
["id"] = netmap_use
3367 lookfor_filter
["name"] = netmap_use
3369 create_network
= True
3370 net_vim_name
= net_name
3371 if isinstance(netmap_create
, str):
3372 net_vim_name
= netmap_create
3373 elif sce_net
.get("vim_network_name"):
3374 create_network
= False
3375 lookfor_network
= True
3376 lookfor_filter
["name"] = sce_net
.get("vim_network_name")
3377 elif sce_net
["external"]:
3378 if sce_net
.get('vim_id'):
3379 # there is a netmap at datacenter_nets database # TODO REVISE!!!!
3380 create_network
= False
3381 lookfor_network
= True
3382 lookfor_filter
["id"] = sce_net
['vim_id']
3383 elif vim
["config"].get("management_network_id") or vim
["config"].get("management_network_name"):
3384 if number_mgmt_networks
> 1:
3385 raise NfvoException("Found several VLD of type mgmt. "
3386 "You must concrete what vim-network must be use for each one",
3387 httperrors
.Bad_Request
)
3388 create_network
= False
3389 lookfor_network
= True
3390 if vim
["config"].get("management_network_id"):
3391 lookfor_filter
["id"] = vim
["config"]["management_network_id"]
3393 lookfor_filter
["name"] = vim
["config"]["management_network_name"]
3395 # There is not a netmap, look at datacenter for a net with this name and create if not found
3396 create_network
= True
3397 lookfor_network
= True
3398 lookfor_filter
["name"] = sce_net
["name"]
3399 net_vim_name
= sce_net
["name"]
3401 net_vim_name
= net_name
3402 create_network
= True
3403 lookfor_network
= False
3407 task_action
= "CREATE"
3408 task_extra
["params"] = (net_vim_name
, net_type
, sce_net
.get('ip_profile', None), None, sce_net
.get('provider_network', None), wim_account_name
)
3411 task_extra
["find"] = (lookfor_filter
,)
3412 elif lookfor_network
:
3413 task_action
= "FIND"
3414 task_extra
["params"] = (lookfor_filter
,)
3416 # fill database content
3417 net_uuid
= str(uuid4())
3418 uuid_list
.append(net_uuid
)
3419 sce_net2instance
[sce_net_uuid
][datacenter_id
] = net_uuid
3420 if not related_network
: # all db_instance_nets will have same related
3421 related_network
= use_network
or net_uuid
3424 "osm_id": sce_net
.get("osm_id") or sce_net
["name"],
3425 "related": related_network
,
3427 "vim_name": net_vim_name
,
3428 "instance_scenario_id": instance_uuid
,
3429 "sce_net_id": sce_net
.get("uuid"),
3430 "created": create_network
,
3431 'datacenter_id': datacenter_id
,
3432 'datacenter_tenant_id': myvim_thread_id
,
3433 'status': 'BUILD' # if create_network else "ACTIVE"
3435 db_instance_nets
.append(db_net
)
3437 "instance_action_id": instance_action_id
,
3438 "status": "SCHEDULED",
3439 "task_index": task_index
,
3440 "datacenter_vim_id": myvim_thread_id
,
3441 "action": task_action
,
3442 "item": "instance_nets",
3443 "item_id": net_uuid
,
3444 "related": related_network
,
3445 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
3447 net2task_id
['scenario'][sce_net_uuid
][datacenter_id
] = task_index
3449 db_vim_actions
.append(db_vim_action
)
3451 if 'ip_profile' in sce_net
:
3453 'instance_net_id': net_uuid
,
3454 'ip_version': sce_net
['ip_profile']['ip_version'],
3455 'subnet_address': sce_net
['ip_profile']['subnet_address'],
3456 'gateway_address': sce_net
['ip_profile']['gateway_address'],
3457 'dns_address': sce_net
['ip_profile']['dns_address'],
3458 'dhcp_enabled': sce_net
['ip_profile']['dhcp_enabled'],
3459 'dhcp_start_address': sce_net
['ip_profile']['dhcp_start_address'],
3460 'dhcp_count': sce_net
['ip_profile']['dhcp_count'],
3462 db_ip_profiles
.append(db_ip_profile
)
3466 "default_datacenter_id": default_datacenter_id
,
3467 "myvim_threads_id": myvim_threads_id
,
3468 "instance_uuid": instance_uuid
,
3469 "instance_name": instance_name
,
3470 "instance_action_id": instance_action_id
,
3472 "cloud_config": cloud_config
,
3473 "RO_pub_key": tenant
[0].get('RO_pub_key'),
3474 "instance_parameters": instance_dict
,
3477 "task_index": task_index
,
3478 "uuid_list": uuid_list
,
3479 "db_instance_nets": db_instance_nets
,
3480 "db_vim_actions": db_vim_actions
,
3481 "db_ip_profiles": db_ip_profiles
,
3482 "db_instance_vnfs": db_instance_vnfs
,
3483 "db_instance_vms": db_instance_vms
,
3484 "db_instance_interfaces": db_instance_interfaces
,
3485 "net2task_id": net2task_id
,
3486 "sce_net2instance": sce_net2instance
,
3488 # sce_vnf_list = sorted(scenarioDict['vnfs'], key=lambda k: k['name'])
3489 for sce_vnf
in scenarioDict
.get('vnfs', ()): # sce_vnf_list:
3490 instantiate_vnf(mydb
, sce_vnf
, vnf_params
, vnf_params_out
, rollbackList
)
3491 task_index
= vnf_params_out
["task_index"]
3492 uuid_list
= vnf_params_out
["uuid_list"]
3495 # task_depends_on = []
3496 for vnffg
in scenarioDict
.get('vnffgs', ()):
3497 for rsp
in vnffg
['rsps']:
3499 for cp
in rsp
['connection_points']:
3500 count
= mydb
.get_rows(
3502 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_rsp_hops as h "
3503 "on interfaces.uuid=h.ingress_interface_id",
3504 WHERE
={'h.uuid': cp
['uuid']})[0]['count']
3505 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == cp
['sce_vnf_id']), None)
3506 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3508 for instance_vm
in instance_vms
:
3509 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3511 dependencies
.append(action
['task_index'])
3512 # TODO: throw exception if count != len(instance_vms)
3513 # TODO: and action shouldn't ever be None
3515 for i
in range(count
):
3517 sfi_uuid
= str(uuid4())
3519 "ingress_interface_id": cp
["ingress_interface_id"],
3520 "egress_interface_id": cp
["egress_interface_id"]
3522 uuid_list
.append(sfi_uuid
)
3525 "related": sfi_uuid
,
3526 "instance_scenario_id": instance_uuid
,
3527 'sce_rsp_hop_id': cp
['uuid'],
3528 'datacenter_id': datacenter_id
,
3529 'datacenter_tenant_id': myvim_thread_id
,
3530 "vim_sfi_id": None, # vim thread will populate
3532 db_instance_sfis
.append(db_sfi
)
3534 "instance_action_id": instance_action_id
,
3535 "task_index": task_index
,
3536 "datacenter_vim_id": myvim_thread_id
,
3538 "status": "SCHEDULED",
3539 "item": "instance_sfis",
3540 "item_id": sfi_uuid
,
3541 "related": sfi_uuid
,
3542 "extra": yaml
.safe_dump({"params": extra_params
, "depends_on": [dependencies
[i
]]},
3543 default_flow_style
=True, width
=256)
3545 sfis_created
.append(task_index
)
3547 db_vim_actions
.append(db_vim_action
)
3549 sf_uuid
= str(uuid4())
3550 uuid_list
.append(sf_uuid
)
3554 "instance_scenario_id": instance_uuid
,
3555 'sce_rsp_hop_id': cp
['uuid'],
3556 'datacenter_id': datacenter_id
,
3557 'datacenter_tenant_id': myvim_thread_id
,
3558 "vim_sf_id": None, # vim thread will populate
3560 db_instance_sfs
.append(db_sf
)
3562 "instance_action_id": instance_action_id
,
3563 "task_index": task_index
,
3564 "datacenter_vim_id": myvim_thread_id
,
3566 "status": "SCHEDULED",
3567 "item": "instance_sfs",
3570 "extra": yaml
.safe_dump({"params": "", "depends_on": sfis_created
},
3571 default_flow_style
=True, width
=256)
3573 sfs_created
.append(task_index
)
3575 db_vim_actions
.append(db_vim_action
)
3576 classifier
= rsp
['classifier']
3578 # TODO the following ~13 lines can be reused for the sfi case
3579 count
= mydb
.get_rows(
3580 SELECT
=('vms.count'),
3581 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_classifiers as c on interfaces.uuid=c.interface_id",
3582 WHERE
={'c.uuid': classifier
['uuid']})[0]['count']
3583 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == classifier
['sce_vnf_id']), None)
3584 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3586 for instance_vm
in instance_vms
:
3587 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3589 dependencies
.append(action
['task_index'])
3590 # TODO: throw exception if count != len(instance_vms)
3591 # TODO: and action shouldn't ever be None
3592 classifications_created
= []
3593 for i
in range(count
):
3594 for match
in classifier
['matches']:
3595 # create classifications
3596 classification_uuid
= str(uuid4())
3597 uuid_list
.append(classification_uuid
)
3598 db_classification
= {
3599 "uuid": classification_uuid
,
3600 "related": classification_uuid
,
3601 "instance_scenario_id": instance_uuid
,
3602 'sce_classifier_match_id': match
['uuid'],
3603 'datacenter_id': datacenter_id
,
3604 'datacenter_tenant_id': myvim_thread_id
,
3605 "vim_classification_id": None, # vim thread will populate
3607 db_instance_classifications
.append(db_classification
)
3608 classification_params
= {
3609 "ip_proto": match
["ip_proto"],
3610 "source_ip": match
["source_ip"],
3611 "destination_ip": match
["destination_ip"],
3612 "source_port": match
["source_port"],
3613 "destination_port": match
["destination_port"]
3616 "instance_action_id": instance_action_id
,
3617 "task_index": task_index
,
3618 "datacenter_vim_id": myvim_thread_id
,
3620 "status": "SCHEDULED",
3621 "item": "instance_classifications",
3622 "item_id": classification_uuid
,
3623 "related": classification_uuid
,
3624 "extra": yaml
.safe_dump({"params": classification_params
, "depends_on": [dependencies
[i
]]},
3625 default_flow_style
=True, width
=256)
3627 classifications_created
.append(task_index
)
3629 db_vim_actions
.append(db_vim_action
)
3632 sfp_uuid
= str(uuid4())
3633 uuid_list
.append(sfp_uuid
)
3636 "related": sfp_uuid
,
3637 "instance_scenario_id": instance_uuid
,
3638 'sce_rsp_id': rsp
['uuid'],
3639 'datacenter_id': datacenter_id
,
3640 'datacenter_tenant_id': myvim_thread_id
,
3641 "vim_sfp_id": None, # vim thread will populate
3643 db_instance_sfps
.append(db_sfp
)
3645 "instance_action_id": instance_action_id
,
3646 "task_index": task_index
,
3647 "datacenter_vim_id": myvim_thread_id
,
3649 "status": "SCHEDULED",
3650 "item": "instance_sfps",
3651 "item_id": sfp_uuid
,
3652 "related": sfp_uuid
,
3653 "extra": yaml
.safe_dump({"params": "", "depends_on": sfs_created
+ classifications_created
},
3654 default_flow_style
=True, width
=256)
3657 db_vim_actions
.append(db_vim_action
)
3658 db_instance_action
["number_tasks"] = task_index
3661 logger
.debug('wim_usage:\n%s\n\n', pformat(wim_usage
))
3662 wan_links
= wim_engine
.derive_wan_links(wim_usage
, db_instance_nets
, tenant_id
)
3663 wim_actions
= wim_engine
.create_actions(wan_links
)
3664 wim_actions
, db_instance_action
= (
3665 wim_engine
.incorporate_actions(wim_actions
, db_instance_action
))
3668 scenarioDict
["datacenter2tenant"] = myvim_threads_id
3670 db_instance_scenario
['datacenter_tenant_id'] = myvim_threads_id
[default_datacenter_id
]
3671 db_instance_scenario
['datacenter_id'] = default_datacenter_id
3673 {"instance_scenarios": db_instance_scenario
},
3674 {"instance_vnfs": db_instance_vnfs
},
3675 {"instance_nets": db_instance_nets
},
3676 {"ip_profiles": db_ip_profiles
},
3677 {"instance_vms": db_instance_vms
},
3678 {"instance_interfaces": db_instance_interfaces
},
3679 {"instance_actions": db_instance_action
},
3680 {"instance_sfis": db_instance_sfis
},
3681 {"instance_sfs": db_instance_sfs
},
3682 {"instance_classifications": db_instance_classifications
},
3683 {"instance_sfps": db_instance_sfps
},
3684 {"instance_wim_nets": wan_links
},
3685 {"vim_wim_actions": db_vim_actions
+ wim_actions
}
3688 logger
.debug("create_instance done DB tables: %s",
3689 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
3690 mydb
.new_rows(db_tables
, uuid_list
)
3691 for myvim_thread_id
in myvim_threads_id
.values():
3692 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
3694 wim_engine
.dispatch(wim_actions
)
3696 returned_instance
= mydb
.get_instance_scenario(instance_uuid
)
3697 returned_instance
["action_id"] = instance_action_id
3698 return returned_instance
3699 except (NfvoException
, vimconn
.vimconnException
, wimconn
.WimConnectorError
, db_base_Exception
) as e
:
3700 message
= rollback(mydb
, myvims
, rollbackList
)
3701 if isinstance(e
, db_base_Exception
):
3702 error_text
= "database Exception"
3703 elif isinstance(e
, vimconn
.vimconnException
):
3704 error_text
= "VIM Exception"
3705 elif isinstance(e
, wimconn
.WimConnectorError
):
3706 error_text
= "WIM Exception"
3708 error_text
= "Exception"
3709 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
3710 # logger.error("create_instance: %s", error_text)
3712 raise NfvoException(error_text
, e
.http_code
)
3715 def instantiate_vnf(mydb
, sce_vnf
, params
, params_out
, rollbackList
):
3716 default_datacenter_id
= params
["default_datacenter_id"]
3717 myvim_threads_id
= params
["myvim_threads_id"]
3718 instance_uuid
= params
["instance_uuid"]
3719 instance_name
= params
["instance_name"]
3720 instance_action_id
= params
["instance_action_id"]
3721 myvims
= params
["myvims"]
3722 cloud_config
= params
["cloud_config"]
3723 RO_pub_key
= params
["RO_pub_key"]
3725 task_index
= params_out
["task_index"]
3726 uuid_list
= params_out
["uuid_list"]
3727 db_instance_nets
= params_out
["db_instance_nets"]
3728 db_vim_actions
= params_out
["db_vim_actions"]
3729 db_ip_profiles
= params_out
["db_ip_profiles"]
3730 db_instance_vnfs
= params_out
["db_instance_vnfs"]
3731 db_instance_vms
= params_out
["db_instance_vms"]
3732 db_instance_interfaces
= params_out
["db_instance_interfaces"]
3733 net2task_id
= params_out
["net2task_id"]
3734 sce_net2instance
= params_out
["sce_net2instance"]
3736 vnf_net2instance
= {}
3738 # 2. Creating new nets (vnf internal nets) in the VIM"
3739 # For each vnf net, we create it and we add it to instanceNetlist.
3740 if sce_vnf
.get("datacenter"):
3741 datacenter_id
= sce_vnf
["datacenter"]
3742 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
3744 datacenter_id
= default_datacenter_id
3745 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
3746 for net
in sce_vnf
['nets']:
3748 # descriptor_net = instance_dict.get("vnfs", {}).get(sce_vnf["name"], {})
3749 # net_name = descriptor_net.get("name")
3752 net_name
= "{}-{}".format(instance_name
, net
["name"])
3753 net_name
= net_name
[:255] # limit length
3754 net_type
= net
['type']
3756 if sce_vnf
['uuid'] not in vnf_net2instance
:
3757 vnf_net2instance
[sce_vnf
['uuid']] = {}
3758 if sce_vnf
['uuid'] not in net2task_id
:
3759 net2task_id
[sce_vnf
['uuid']] = {}
3760 net2task_id
[sce_vnf
['uuid']][net
['uuid']] = task_index
3762 # fill database content
3763 net_uuid
= str(uuid4())
3764 uuid_list
.append(net_uuid
)
3765 vnf_net2instance
[sce_vnf
['uuid']][net
['uuid']] = net_uuid
3768 "related": net_uuid
,
3770 "vim_name": net_name
,
3771 "instance_scenario_id": instance_uuid
,
3772 "net_id": net
["uuid"],
3774 'datacenter_id': datacenter_id
,
3775 'datacenter_tenant_id': myvim_thread_id
,
3777 db_instance_nets
.append(db_net
)
3780 if net
.get("vim-network-name"):
3781 lookfor_filter
["name"] = net
["vim-network-name"]
3782 if net
.get("vim-network-id"):
3783 lookfor_filter
["id"] = net
["vim-network-id"]
3785 task_action
= "FIND"
3786 task_extra
= {"params": (lookfor_filter
,)}
3788 task_action
= "CREATE"
3789 task_extra
= {"params": (net_name
, net_type
, net
.get('ip_profile', None))}
3792 "instance_action_id": instance_action_id
,
3793 "task_index": task_index
,
3794 "datacenter_vim_id": myvim_thread_id
,
3795 "status": "SCHEDULED",
3796 "action": task_action
,
3797 "item": "instance_nets",
3798 "item_id": net_uuid
,
3799 "related": net_uuid
,
3800 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
3803 db_vim_actions
.append(db_vim_action
)
3805 if 'ip_profile' in net
:
3807 'instance_net_id': net_uuid
,
3808 'ip_version': net
['ip_profile']['ip_version'],
3809 'subnet_address': net
['ip_profile']['subnet_address'],
3810 'gateway_address': net
['ip_profile']['gateway_address'],
3811 'dns_address': net
['ip_profile']['dns_address'],
3812 'dhcp_enabled': net
['ip_profile']['dhcp_enabled'],
3813 'dhcp_start_address': net
['ip_profile']['dhcp_start_address'],
3814 'dhcp_count': net
['ip_profile']['dhcp_count'],
3816 db_ip_profiles
.append(db_ip_profile
)
3818 # print "vnf_net2instance:"
3819 # print yaml.safe_dump(vnf_net2instance, indent=4, default_flow_style=False)
3821 # 3. Creating new vm instances in the VIM
3822 # myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
3824 if sce_vnf
.get('mgmt_access'):
3825 ssh_access
= sce_vnf
['mgmt_access'].get('config-access', {}).get('ssh-access')
3826 vnf_availability_zones
= []
3827 for vm
in sce_vnf
.get('vms'):
3828 vm_av
= vm
.get('availability_zone')
3829 if vm_av
and vm_av
not in vnf_availability_zones
:
3830 vnf_availability_zones
.append(vm_av
)
3832 # check if there is enough availability zones available at vim level.
3833 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
3834 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
3835 raise NfvoException('No enough availability zones at VIM for this deployment', httperrors
.Bad_Request
)
3837 if sce_vnf
.get("datacenter"):
3838 vim
= myvims
[sce_vnf
["datacenter"]]
3839 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
3840 datacenter_id
= sce_vnf
["datacenter"]
3842 vim
= myvims
[default_datacenter_id
]
3843 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
3844 datacenter_id
= default_datacenter_id
3845 sce_vnf
["datacenter_id"] = datacenter_id
3848 vnf_uuid
= str(uuid4())
3849 uuid_list
.append(vnf_uuid
)
3852 'instance_scenario_id': instance_uuid
,
3853 'vnf_id': sce_vnf
['vnf_id'],
3854 'sce_vnf_id': sce_vnf
['uuid'],
3855 'datacenter_id': datacenter_id
,
3856 'datacenter_tenant_id': myvim_thread_id
,
3858 db_instance_vnfs
.append(db_instance_vnf
)
3860 for vm
in sce_vnf
['vms']:
3862 if vm
.get("pdu_type"):
3866 sce_vnf_name
= sce_vnf
['member_vnf_index'] if sce_vnf
['member_vnf_index'] else sce_vnf
['name']
3867 myVMDict
['name'] = "{}-{}-{}".format(instance_name
[:64], sce_vnf_name
[:64], vm
["name"][:64])
3868 myVMDict
['description'] = myVMDict
['name'][0:99]
3870 # myVMDict['start'] = "no"
3871 if vm
.get("instance_parameters") and vm
["instance_parameters"].get("name"):
3872 myVMDict
['name'] = vm
["instance_parameters"].get("name")
3873 myVMDict
['name'] = myVMDict
['name'][0:255] # limit name length
3874 # create image at vim in case it not exist
3875 image_uuid
= vm
['image_id']
3876 if vm
.get("image_list"):
3877 for alternative_image
in vm
["image_list"]:
3878 if alternative_image
["vim_type"] == vim
["config"]["_vim_type_internal"]:
3879 image_uuid
= alternative_image
['image_id']
3881 image_dict
= mydb
.get_table_by_uuid_name("images", image_uuid
)
3882 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
3883 vm
['vim_image_id'] = image_id
3885 # create flavor at vim in case it not exist
3886 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
3887 if flavor_dict
['extended'] != None:
3888 flavor_dict
['extended'] = yaml
.load(flavor_dict
['extended'])
3889 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
3891 # Obtain information for additional disks
3892 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',),
3893 WHERE
={'vim_id': flavor_id
})
3894 if not extended_flavor_dict
:
3895 raise NfvoException("flavor '{}' not found".format(flavor_id
), httperrors
.Not_Found
)
3897 # extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
3898 myVMDict
['disks'] = None
3899 extended_info
= extended_flavor_dict
[0]['extended']
3900 if extended_info
!= None:
3901 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
3902 if 'disks' in extended_flavor_dict_yaml
:
3903 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
3904 if vm
.get("instance_parameters") and vm
["instance_parameters"].get("devices"):
3905 for disk
in myVMDict
['disks']:
3906 if disk
.get("name") in vm
["instance_parameters"]["devices"]:
3907 disk
.update(vm
["instance_parameters"]["devices"][disk
.get("name")])
3909 vm
['vim_flavor_id'] = flavor_id
3910 myVMDict
['imageRef'] = vm
['vim_image_id']
3911 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
3912 myVMDict
['availability_zone'] = vm
.get('availability_zone')
3913 myVMDict
['networks'] = []
3914 task_depends_on
= []
3915 # TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
3916 is_management_vm
= False
3918 for iface
in vm
['interfaces']:
3920 if iface
['type'] == "data":
3921 netDict
['type'] = iface
['model']
3922 elif "model" in iface
and iface
["model"] != None:
3923 netDict
['model'] = iface
['model']
3924 # TODO in future, remove this because mac_address will not be set, and the type of PV,VF
3925 # is obtained from iterface table model
3926 # discover type of interface looking at flavor
3927 for numa
in flavor_dict
.get('extended', {}).get('numas', []):
3928 for flavor_iface
in numa
.get('interfaces', []):
3929 if flavor_iface
.get('name') == iface
['internal_name']:
3930 if flavor_iface
['dedicated'] == 'yes':
3931 netDict
['type'] = "PF" # passthrough
3932 elif flavor_iface
['dedicated'] == 'no':
3933 netDict
['type'] = "VF" # siov
3934 elif flavor_iface
['dedicated'] == 'yes:sriov':
3935 netDict
['type'] = "VFnotShared" # sriov but only one sriov on the PF
3936 netDict
["mac_address"] = flavor_iface
.get("mac_address")
3938 netDict
["use"] = iface
['type']
3939 if netDict
["use"] == "data" and not netDict
.get("type"):
3940 # print "netDict", netDict
3941 # print "iface", iface
3942 e_text
= "Cannot determine the interface type PF or VF of VNF '{}' VM '{}' iface '{}'".fromat(
3943 sce_vnf
['name'], vm
['name'], iface
['internal_name'])
3944 if flavor_dict
.get('extended') == None:
3945 raise NfvoException(e_text
+ "After database migration some information is not available. \
3946 Try to delete and create the scenarios and VNFs again", httperrors
.Conflict
)
3948 raise NfvoException(e_text
, httperrors
.Internal_Server_Error
)
3949 if netDict
["use"] == "mgmt":
3950 is_management_vm
= True
3951 netDict
["type"] = "virtual"
3952 if netDict
["use"] == "bridge":
3953 netDict
["type"] = "virtual"
3954 if iface
.get("vpci"):
3955 netDict
['vpci'] = iface
['vpci']
3956 if iface
.get("mac"):
3957 netDict
['mac_address'] = iface
['mac']
3958 if iface
.get("mac_address"):
3959 netDict
['mac_address'] = iface
['mac_address']
3960 if iface
.get("ip_address"):
3961 netDict
['ip_address'] = iface
['ip_address']
3962 if iface
.get("port-security") is not None:
3963 netDict
['port_security'] = iface
['port-security']
3964 if iface
.get("floating-ip") is not None:
3965 netDict
['floating_ip'] = iface
['floating-ip']
3966 netDict
['name'] = iface
['internal_name']
3967 if iface
['net_id'] is None:
3968 for vnf_iface
in sce_vnf
["interfaces"]:
3971 if vnf_iface
['interface_id'] == iface
['uuid']:
3972 netDict
['net_id'] = "TASK-{}".format(
3973 net2task_id
['scenario'][vnf_iface
['sce_net_id']][datacenter_id
])
3974 instance_net_id
= sce_net2instance
[vnf_iface
['sce_net_id']][datacenter_id
]
3975 task_depends_on
.append(net2task_id
['scenario'][vnf_iface
['sce_net_id']][datacenter_id
])
3978 netDict
['net_id'] = "TASK-{}".format(net2task_id
[sce_vnf
['uuid']][iface
['net_id']])
3979 instance_net_id
= vnf_net2instance
[sce_vnf
['uuid']][iface
['net_id']]
3980 task_depends_on
.append(net2task_id
[sce_vnf
['uuid']][iface
['net_id']])
3981 # skip bridge ifaces not connected to any net
3982 if 'net_id' not in netDict
or netDict
['net_id'] == None:
3984 myVMDict
['networks'].append(netDict
)
3987 # 'instance_vm_id': instance_vm_uuid,
3988 "instance_net_id": instance_net_id
,
3989 'interface_id': iface
['uuid'],
3990 # 'vim_interface_id': ,
3991 'type': 'external' if iface
['external_name'] is not None else 'internal',
3992 'ip_address': iface
.get('ip_address'),
3993 'mac_address': iface
.get('mac'),
3994 'floating_ip': int(iface
.get('floating-ip', False)),
3995 'port_security': int(iface
.get('port-security', True))
3997 db_vm_ifaces
.append(db_vm_iface
)
3998 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3999 # print myVMDict['name']
4000 # print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
4001 # print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
4002 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
4004 # We add the RO key to cloud_config if vnf will need ssh access
4005 cloud_config_vm
= cloud_config
4006 if is_management_vm
and params
["instance_parameters"].get("mgmt_keys"):
4007 cloud_config_vm
= unify_cloud_config({"key-pairs": params
["instance_parameters"]["mgmt_keys"]},
4010 if vm
.get("instance_parameters") and "mgmt_keys" in vm
["instance_parameters"]:
4011 if vm
["instance_parameters"]["mgmt_keys"]:
4012 cloud_config_vm
= unify_cloud_config({"key-pairs": vm
["instance_parameters"]["mgmt_keys"]},
4015 cloud_config_vm
= unify_cloud_config(cloud_config_vm
, {"key-pairs": [RO_pub_key
]})
4016 if vm
.get("boot_data"):
4017 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config_vm
)
4019 if myVMDict
.get('availability_zone'):
4020 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
4023 for vm_index
in range(0, vm
.get('count', 1)):
4024 vm_name
= myVMDict
['name'] + "-" + str(vm_index
+1)
4025 task_params
= (vm_name
, myVMDict
['description'], myVMDict
.get('start', None),
4026 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'], cloud_config_vm
,
4027 myVMDict
['disks'], av_index
, vnf_availability_zones
)
4028 # put interface uuid back to scenario[vnfs][vms[[interfaces]
4029 for net
in myVMDict
['networks']:
4031 for iface
in vm
['interfaces']:
4032 if net
["name"] == iface
["internal_name"]:
4033 iface
["vim_id"] = net
["vim_id"]
4035 vm_uuid
= str(uuid4())
4036 uuid_list
.append(vm_uuid
)
4040 'instance_vnf_id': vnf_uuid
,
4041 # TODO delete "vim_vm_id": vm_id,
4042 "vm_id": vm
["uuid"],
4043 "vim_name": vm_name
,
4046 db_instance_vms
.append(db_vm
)
4049 for db_vm_iface
in db_vm_ifaces
:
4050 iface_uuid
= str(uuid4())
4051 uuid_list
.append(iface_uuid
)
4052 db_vm_iface_instance
= {
4054 "instance_vm_id": vm_uuid
4056 db_vm_iface_instance
.update(db_vm_iface
)
4057 if db_vm_iface_instance
.get("ip_address"): # increment ip_address
4058 ip
= db_vm_iface_instance
.get("ip_address")
4063 ip
= ip
[i
:] + str(int(ip
[:i
]) + 1)
4064 db_vm_iface_instance
["ip_address"] = ip
4066 db_vm_iface_instance
["ip_address"] = None
4067 db_instance_interfaces
.append(db_vm_iface_instance
)
4068 myVMDict
['networks'][iface_index
]["uuid"] = iface_uuid
4072 "instance_action_id": instance_action_id
,
4073 "task_index": task_index
,
4074 "datacenter_vim_id": myvim_thread_id
,
4076 "status": "SCHEDULED",
4077 "item": "instance_vms",
4080 "extra": yaml
.safe_dump({"params": task_params
, "depends_on": task_depends_on
},
4081 default_flow_style
=True, width
=256)
4084 db_vim_actions
.append(db_vim_action
)
4085 params_out
["task_index"] = task_index
4086 params_out
["uuid_list"] = uuid_list
4089 def delete_instance(mydb
, tenant_id
, instance_id
):
4090 # print "Checking that the instance_id exists and getting the instance dictionary"
4091 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
4092 # print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
4093 tenant_id
= instanceDict
["tenant_id"]
4096 # We need to retrieve the WIM Actions now, before the instance_scenario is
4097 # deleted. The reason for that is that: ON CASCADE rules will delete the
4098 # instance_wim_nets record in the database
4099 wim_actions
= wim_engine
.delete_actions(instance_scenario_id
=instance_id
)
4102 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
4103 # 1. Delete from Database
4104 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
4106 # 2. delete from VIM
4110 vimthread_affected
= {}
4111 net2vm_dependencies
= {}
4114 instance_action_id
= get_task_id()
4116 db_instance_action
= {
4117 "uuid": instance_action_id
, # same uuid for the instance and the action on create
4118 "tenant_id": tenant_id
,
4119 "instance_id": instance_id
,
4120 "description": "DELETE",
4121 # "number_tasks": 0 # filled bellow
4124 # 2.1 deleting VNFFGs
4125 for sfp
in instanceDict
.get('sfps', ()):
4126 vimthread_affected
[sfp
["datacenter_tenant_id"]] = None
4127 datacenter_key
= (sfp
["datacenter_id"], sfp
["datacenter_tenant_id"])
4128 if datacenter_key
not in myvims
:
4130 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sfp
["datacenter_id"], sfp
["datacenter_tenant_id"])
4131 except NfvoException
as e
:
4132 logger
.error(str(e
))
4134 myvim_threads
[datacenter_key
] = myvim_thread
4135 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sfp
["datacenter_id"],
4136 datacenter_tenant_id
=sfp
["datacenter_tenant_id"])
4138 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfp
["datacenter_id"], sfp
["datacenter_tenant_id"]))
4139 myvims
[datacenter_key
] = None
4141 myvims
[datacenter_key
] = vims
.values()[0]
4142 myvim
= myvims
[datacenter_key
]
4143 myvim_thread
= myvim_threads
[datacenter_key
]
4146 error_msg
+= "\n vim_sfp_id={} cannot be deleted because datacenter={} not found".format(sfp
['vim_sfp_id'], sfp
["datacenter_id"])
4148 extra
= {"params": (sfp
['vim_sfp_id'])}
4150 "instance_action_id": instance_action_id
,
4151 "task_index": task_index
,
4152 "datacenter_vim_id": sfp
["datacenter_tenant_id"],
4154 "status": "SCHEDULED",
4155 "item": "instance_sfps",
4156 "item_id": sfp
["uuid"],
4157 "related": sfp
["related"],
4158 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4161 db_vim_actions
.append(db_vim_action
)
4163 for classification
in instanceDict
['classifications']:
4164 vimthread_affected
[classification
["datacenter_tenant_id"]] = None
4165 datacenter_key
= (classification
["datacenter_id"], classification
["datacenter_tenant_id"])
4166 if datacenter_key
not in myvims
:
4168 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, classification
["datacenter_id"], classification
["datacenter_tenant_id"])
4169 except NfvoException
as e
:
4170 logger
.error(str(e
))
4172 myvim_threads
[datacenter_key
] = myvim_thread
4173 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=classification
["datacenter_id"],
4174 datacenter_tenant_id
=classification
["datacenter_tenant_id"])
4176 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(classification
["datacenter_id"],
4177 classification
["datacenter_tenant_id"]))
4178 myvims
[datacenter_key
] = None
4180 myvims
[datacenter_key
] = vims
.values()[0]
4181 myvim
= myvims
[datacenter_key
]
4182 myvim_thread
= myvim_threads
[datacenter_key
]
4185 error_msg
+= "\n vim_classification_id={} cannot be deleted because datacenter={} not found".format(classification
['vim_classification_id'],
4186 classification
["datacenter_id"])
4188 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfps"]
4189 extra
= {"params": (classification
['vim_classification_id']), "depends_on": depends_on
}
4191 "instance_action_id": instance_action_id
,
4192 "task_index": task_index
,
4193 "datacenter_vim_id": classification
["datacenter_tenant_id"],
4195 "status": "SCHEDULED",
4196 "item": "instance_classifications",
4197 "item_id": classification
["uuid"],
4198 "related": classification
["related"],
4199 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4202 db_vim_actions
.append(db_vim_action
)
4204 for sf
in instanceDict
.get('sfs', ()):
4205 vimthread_affected
[sf
["datacenter_tenant_id"]] = None
4206 datacenter_key
= (sf
["datacenter_id"], sf
["datacenter_tenant_id"])
4207 if datacenter_key
not in myvims
:
4209 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sf
["datacenter_id"], sf
["datacenter_tenant_id"])
4210 except NfvoException
as e
:
4211 logger
.error(str(e
))
4213 myvim_threads
[datacenter_key
] = myvim_thread
4214 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sf
["datacenter_id"],
4215 datacenter_tenant_id
=sf
["datacenter_tenant_id"])
4217 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sf
["datacenter_id"], sf
["datacenter_tenant_id"]))
4218 myvims
[datacenter_key
] = None
4220 myvims
[datacenter_key
] = vims
.values()[0]
4221 myvim
= myvims
[datacenter_key
]
4222 myvim_thread
= myvim_threads
[datacenter_key
]
4225 error_msg
+= "\n vim_sf_id={} cannot be deleted because datacenter={} not found".format(sf
['vim_sf_id'], sf
["datacenter_id"])
4227 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfps"]
4228 extra
= {"params": (sf
['vim_sf_id']), "depends_on": depends_on
}
4230 "instance_action_id": instance_action_id
,
4231 "task_index": task_index
,
4232 "datacenter_vim_id": sf
["datacenter_tenant_id"],
4234 "status": "SCHEDULED",
4235 "item": "instance_sfs",
4236 "item_id": sf
["uuid"],
4237 "related": sf
["related"],
4238 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4241 db_vim_actions
.append(db_vim_action
)
4243 for sfi
in instanceDict
.get('sfis', ()):
4244 vimthread_affected
[sfi
["datacenter_tenant_id"]] = None
4245 datacenter_key
= (sfi
["datacenter_id"], sfi
["datacenter_tenant_id"])
4246 if datacenter_key
not in myvims
:
4248 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sfi
["datacenter_id"], sfi
["datacenter_tenant_id"])
4249 except NfvoException
as e
:
4250 logger
.error(str(e
))
4252 myvim_threads
[datacenter_key
] = myvim_thread
4253 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sfi
["datacenter_id"],
4254 datacenter_tenant_id
=sfi
["datacenter_tenant_id"])
4256 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfi
["datacenter_id"], sfi
["datacenter_tenant_id"]))
4257 myvims
[datacenter_key
] = None
4259 myvims
[datacenter_key
] = vims
.values()[0]
4260 myvim
= myvims
[datacenter_key
]
4261 myvim_thread
= myvim_threads
[datacenter_key
]
4264 error_msg
+= "\n vim_sfi_id={} cannot be deleted because datacenter={} not found".format(sfi
['vim_sfi_id'], sfi
["datacenter_id"])
4266 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfs"]
4267 extra
= {"params": (sfi
['vim_sfi_id']), "depends_on": depends_on
}
4269 "instance_action_id": instance_action_id
,
4270 "task_index": task_index
,
4271 "datacenter_vim_id": sfi
["datacenter_tenant_id"],
4273 "status": "SCHEDULED",
4274 "item": "instance_sfis",
4275 "item_id": sfi
["uuid"],
4276 "related": sfi
["related"],
4277 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4280 db_vim_actions
.append(db_vim_action
)
4284 for sce_vnf
in instanceDict
.get('vnfs', ()):
4285 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
4286 vimthread_affected
[sce_vnf
["datacenter_tenant_id"]] = None
4287 if datacenter_key
not in myvims
:
4289 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
4290 except NfvoException
as e
:
4291 logger
.error(str(e
))
4293 myvim_threads
[datacenter_key
] = myvim_thread
4294 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
4295 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
4297 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
4298 sce_vnf
["datacenter_tenant_id"]))
4299 myvims
[datacenter_key
] = None
4301 myvims
[datacenter_key
] = vims
.values()[0]
4302 myvim
= myvims
[datacenter_key
]
4303 myvim_thread
= myvim_threads
[datacenter_key
]
4305 for vm
in sce_vnf
['vms']:
4307 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
4309 sfi_dependencies
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfis"]
4311 "instance_action_id": instance_action_id
,
4312 "task_index": task_index
,
4313 "datacenter_vim_id": sce_vnf
["datacenter_tenant_id"],
4315 "status": "SCHEDULED",
4316 "item": "instance_vms",
4317 "item_id": vm
["uuid"],
4318 "related": vm
["related"],
4319 "extra": yaml
.safe_dump({"params": vm
["interfaces"], "depends_on": sfi_dependencies
},
4320 default_flow_style
=True, width
=256)
4322 db_vim_actions
.append(db_vim_action
)
4323 for interface
in vm
["interfaces"]:
4324 if not interface
.get("instance_net_id"):
4326 if interface
["instance_net_id"] not in net2vm_dependencies
:
4327 net2vm_dependencies
[interface
["instance_net_id"]] = []
4328 net2vm_dependencies
[interface
["instance_net_id"]].append(task_index
)
4333 for net
in instanceDict
['nets']:
4334 vimthread_affected
[net
["datacenter_tenant_id"]] = None
4335 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
4336 if datacenter_key
not in myvims
:
4338 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, net
["datacenter_id"], net
["datacenter_tenant_id"])
4339 except NfvoException
as e
:
4340 logger
.error(str(e
))
4342 myvim_threads
[datacenter_key
] = myvim_thread
4343 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
4344 datacenter_tenant_id
=net
["datacenter_tenant_id"])
4346 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
4347 myvims
[datacenter_key
] = None
4349 myvims
[datacenter_key
] = vims
.values()[0]
4350 myvim
= myvims
[datacenter_key
]
4351 myvim_thread
= myvim_threads
[datacenter_key
]
4354 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
4356 extra
= {"params": (net
['vim_net_id'], net
['sdn_net_id'])}
4357 if net2vm_dependencies
.get(net
["uuid"]):
4358 extra
["depends_on"] = net2vm_dependencies
[net
["uuid"]]
4359 sfi_dependencies
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfis"]
4360 if len(sfi_dependencies
) > 0:
4361 if "depends_on" in extra
:
4362 extra
["depends_on"] += sfi_dependencies
4364 extra
["depends_on"] = sfi_dependencies
4366 "instance_action_id": instance_action_id
,
4367 "task_index": task_index
,
4368 "datacenter_vim_id": net
["datacenter_tenant_id"],
4370 "status": "SCHEDULED",
4371 "item": "instance_nets",
4372 "item_id": net
["uuid"],
4373 "related": net
["related"],
4374 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4377 db_vim_actions
.append(db_vim_action
)
4379 db_instance_action
["number_tasks"] = task_index
4382 wim_actions
, db_instance_action
= (
4383 wim_engine
.incorporate_actions(wim_actions
, db_instance_action
))
4387 {"instance_actions": db_instance_action
},
4388 {"vim_wim_actions": db_vim_actions
+ wim_actions
}
4391 logger
.debug("delete_instance done DB tables: %s",
4392 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
4393 mydb
.new_rows(db_tables
, ())
4394 for myvim_thread_id
in vimthread_affected
.keys():
4395 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
4397 wim_engine
.dispatch(wim_actions
)
4399 if len(error_msg
) > 0:
4400 return 'action_id={} instance {} deleted but some elements could not be deleted, or already deleted '\
4401 '(error: 404) from VIM: {}'.format(instance_action_id
, message
, error_msg
)
4403 return "action_id={} instance {} deleted".format(instance_action_id
, message
)
4405 def get_instance_id(mydb
, tenant_id
, instance_id
):
4407 #check valid tenant_id
4408 check_tenant(mydb
, tenant_id
)
4411 instance_dict
= mydb
.get_instance_scenario(instance_id
, tenant_id
, verbose
=True)
4412 for net
in instance_dict
["nets"]:
4413 if net
.get("sdn_net_id"):
4414 net_sdn
= ovim
.show_network(net
["sdn_net_id"])
4416 "admin_state_up": net_sdn
.get("admin_state_up"),
4417 "flows": net_sdn
.get("flows"),
4418 "last_error": net_sdn
.get("last_error"),
4419 "ports": net_sdn
.get("ports"),
4420 "type": net_sdn
.get("type"),
4421 "status": net_sdn
.get("status"),
4422 "vlan": net_sdn
.get("vlan"),
4424 return instance_dict
4426 @deprecated("Instance is automatically refreshed by vim_threads")
4427 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
4428 '''Refreshes a scenario instance. It modifies instanceDict'''
4430 - 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
4433 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
4434 # #print "nfvo.refresh_instance begins"
4435 # #print json.dumps(instanceDict, indent=4)
4437 # #print "Getting the VIM URL and the VIM tenant_id"
4440 # # 1. Getting VIM vm and net list
4441 # vms_updated = [] #List of VM instance uuids in openmano that were updated
4444 # for sce_vnf in instanceDict['vnfs']:
4445 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
4446 # if datacenter_key not in vm_list:
4447 # vm_list[datacenter_key] = []
4448 # if datacenter_key not in myvims:
4449 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
4450 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
4451 # if len(vims) == 0:
4452 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
4453 # myvims[datacenter_key] = None
4455 # myvims[datacenter_key] = vims.values()[0]
4456 # for vm in sce_vnf['vms']:
4457 # vm_list[datacenter_key].append(vm['vim_vm_id'])
4458 # vms_notupdated.append(vm["uuid"])
4460 # nets_updated = [] #List of VM instance uuids in openmano that were updated
4461 # nets_notupdated=[]
4463 # for net in instanceDict['nets']:
4464 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
4465 # if datacenter_key not in net_list:
4466 # net_list[datacenter_key] = []
4467 # if datacenter_key not in myvims:
4468 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
4469 # datacenter_tenant_id=net["datacenter_tenant_id"])
4470 # if len(vims) == 0:
4471 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
4472 # myvims[datacenter_key] = None
4474 # myvims[datacenter_key] = vims.values()[0]
4476 # net_list[datacenter_key].append(net['vim_net_id'])
4477 # nets_notupdated.append(net["uuid"])
4479 # # 1. Getting the status of all VMs
4481 # for datacenter_key in myvims:
4482 # if not vm_list.get(datacenter_key):
4486 # if not myvims[datacenter_key]:
4487 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
4490 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
4492 # except vimconn.vimconnException as e:
4493 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
4494 # failed_message = str(e)
4496 # for vm in vm_list[datacenter_key]:
4497 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
4499 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
4500 # for sce_vnf in instanceDict['vnfs']:
4501 # for vm in sce_vnf['vms']:
4502 # vm_id = vm['vim_vm_id']
4503 # interfaces = vm_dict[vm_id].pop('interfaces', [])
4504 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
4505 # has_mgmt_iface = False
4506 # for iface in vm["interfaces"]:
4507 # if iface["type"]=="mgmt":
4508 # has_mgmt_iface = True
4509 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
4510 # vm_dict[vm_id]['status'] = "ACTIVE"
4511 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
4512 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
4513 # 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'):
4514 # vm['status'] = vm_dict[vm_id]['status']
4515 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
4516 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
4517 # # 2.1. Update in openmano DB the VMs whose status changed
4519 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
4520 # vms_notupdated.remove(vm["uuid"])
4522 # vms_updated.append(vm["uuid"])
4523 # except db_base_Exception as e:
4524 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
4525 # # 2.2. Update in openmano DB the interface VMs
4526 # for interface in interfaces:
4527 # #translate from vim_net_id to instance_net_id
4528 # network_id_list=[]
4529 # for net in instanceDict['nets']:
4530 # if net["vim_net_id"] == interface["vim_net_id"]:
4531 # network_id_list.append(net["uuid"])
4532 # if not network_id_list:
4534 # del interface["vim_net_id"]
4536 # for network_id in network_id_list:
4537 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
4538 # except db_base_Exception as e:
4539 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
4541 # # 3. Getting the status of all nets
4543 # for datacenter_key in myvims:
4544 # if not net_list.get(datacenter_key):
4547 # failed_message = ""
4548 # if not myvims[datacenter_key]:
4549 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
4552 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
4554 # except vimconn.vimconnException as e:
4555 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
4556 # failed_message = str(e)
4558 # for net in net_list[datacenter_key]:
4559 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
4561 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
4562 # # TODO: update nets inside a vnf
4563 # for net in instanceDict['nets']:
4564 # net_id = net['vim_net_id']
4565 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
4566 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
4567 # 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'):
4568 # net['status'] = net_dict[net_id]['status']
4569 # net['error_msg'] = net_dict[net_id].get('error_msg')
4570 # net['vim_info'] = net_dict[net_id].get('vim_info')
4571 # # 5.1. Update in openmano DB the nets whose status changed
4573 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
4574 # nets_notupdated.remove(net["uuid"])
4576 # nets_updated.append(net["uuid"])
4577 # except db_base_Exception as e:
4578 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
4580 # # Returns appropriate output
4581 # #print "nfvo.refresh_instance finishes"
4582 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
4583 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
4584 instance_id
= instanceDict
['uuid']
4585 # if len(vms_notupdated)+len(nets_notupdated)>0:
4586 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
4587 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
4589 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
4591 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
4592 #print "Checking that the instance_id exists and getting the instance dictionary"
4593 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
4594 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
4596 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
4597 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
4599 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), httperrors
.Not_Found
)
4600 myvim
= vims
.values()[0]
4605 myvim_threads_id
= {}
4606 if action_dict
.get("vdu-scaling"):
4607 db_instance_vms
= []
4609 db_instance_interfaces
= []
4610 instance_action_id
= get_task_id()
4611 db_instance_action
= {
4612 "uuid": instance_action_id
, # same uuid for the instance and the action on create
4613 "tenant_id": nfvo_tenant
,
4614 "instance_id": instance_id
,
4615 "description": "SCALE",
4617 vm_result
["instance_action_id"] = instance_action_id
4618 vm_result
["created"] = []
4619 vm_result
["deleted"] = []
4621 for vdu
in action_dict
["vdu-scaling"]:
4622 vdu_id
= vdu
.get("vdu-id")
4623 osm_vdu_id
= vdu
.get("osm_vdu_id")
4624 member_vnf_index
= vdu
.get("member-vnf-index")
4625 vdu_count
= vdu
.get("count", 1)
4627 target_vms
= mydb
.get_rows(
4628 FROM
="instance_vms as vms join instance_vnfs as vnfs on vms.instance_vnf_id=vnfs.uuid",
4629 WHERE
={"vms.uuid": vdu_id
},
4630 ORDER_BY
="vms.created_at"
4633 raise NfvoException("Cannot find the vdu with id {}".format(vdu_id
), httperrors
.Not_Found
)
4635 if not osm_vdu_id
and not member_vnf_index
:
4636 raise NfvoException("Invalid input vdu parameters. Must supply either 'vdu-id' of 'osm_vdu_id','member-vnf-index'")
4637 target_vms
= mydb
.get_rows(
4638 # SELECT=("ivms.uuid", "ivnfs.datacenter_id", "ivnfs.datacenter_tenant_id"),
4639 FROM
="instance_vms as ivms join instance_vnfs as ivnfs on ivms.instance_vnf_id=ivnfs.uuid"\
4640 " join sce_vnfs as svnfs on ivnfs.sce_vnf_id=svnfs.uuid"\
4641 " join vms on ivms.vm_id=vms.uuid",
4642 WHERE
={"vms.osm_id": osm_vdu_id
, "svnfs.member_vnf_index": member_vnf_index
,
4643 "ivnfs.instance_scenario_id": instance_id
},
4644 ORDER_BY
="ivms.created_at"
4647 raise NfvoException("Cannot find the vdu with osm_vdu_id {} and member-vnf-index {}".format(osm_vdu_id
, member_vnf_index
), httperrors
.Not_Found
)
4648 vdu_id
= target_vms
[-1]["uuid"]
4649 target_vm
= target_vms
[-1]
4650 datacenter
= target_vm
["datacenter_id"]
4651 myvim_threads_id
[datacenter
], _
= get_vim_thread(mydb
, nfvo_tenant
, datacenter
)
4653 if vdu
["type"] == "delete":
4654 for index
in range(0, vdu_count
):
4655 target_vm
= target_vms
[-1-index
]
4656 vdu_id
= target_vm
["uuid"]
4658 vm_interfaces
= None
4659 for sce_vnf
in instanceDict
['vnfs']:
4660 for vm
in sce_vnf
['vms']:
4661 if vm
["uuid"] == vdu_id
:
4662 # TODO revise this should not be vm["uuid"] instance_vms["vm_id"]
4663 vm_interfaces
= vm
["interfaces"]
4667 "instance_action_id": instance_action_id
,
4668 "task_index": task_index
,
4669 "datacenter_vim_id": target_vm
["datacenter_tenant_id"],
4671 "status": "SCHEDULED",
4672 "item": "instance_vms",
4674 "related": target_vm
["related"],
4675 "extra": yaml
.safe_dump({"params": vm_interfaces
},
4676 default_flow_style
=True, width
=256)
4679 db_vim_actions
.append(db_vim_action
)
4680 vm_result
["deleted"].append(vdu_id
)
4681 # delete from database
4682 db_instance_vms
.append({"TO-DELETE": vdu_id
})
4684 else: # vdu["type"] == "create":
4686 where
= {"item": "instance_vms", "item_id": target_vm
["uuid"], "action": "CREATE"}
4688 vim_action_to_clone
= mydb
.get_rows(FROM
="vim_wim_actions", WHERE
=where
)
4689 if not vim_action_to_clone
:
4690 raise NfvoException("Cannot find the vim_action at database with {}".format(where
), httperrors
.Internal_Server_Error
)
4691 vim_action_to_clone
= vim_action_to_clone
[0]
4692 extra
= yaml
.safe_load(vim_action_to_clone
["extra"])
4694 # generate a new depends_on. Convert format TASK-Y into new format TASK-ACTION-XXXX.XXXX.Y
4695 # TODO do the same for flavor and image when available
4696 task_depends_on
= []
4697 task_params
= extra
["params"]
4698 task_params_networks
= deepcopy(task_params
[5])
4699 for iface
in task_params
[5]:
4700 if iface
["net_id"].startswith("TASK-"):
4701 if "." not in iface
["net_id"]:
4702 task_depends_on
.append("{}.{}".format(vim_action_to_clone
["instance_action_id"],
4703 iface
["net_id"][5:]))
4704 iface
["net_id"] = "TASK-{}.{}".format(vim_action_to_clone
["instance_action_id"],
4705 iface
["net_id"][5:])
4707 task_depends_on
.append(iface
["net_id"][5:])
4708 if "mac_address" in iface
:
4709 del iface
["mac_address"]
4711 vm_ifaces_to_clone
= mydb
.get_rows(FROM
="instance_interfaces", WHERE
={"instance_vm_id": target_vm
["uuid"]})
4712 for index
in range(0, vdu_count
):
4713 vm_uuid
= str(uuid4())
4714 vm_name
= target_vm
.get('vim_name')
4716 suffix
= vm_name
.rfind("-")
4717 vm_name
= vm_name
[:suffix
+1] + str(index
+ 1 + int(vm_name
[suffix
+1:]))
4723 'instance_vnf_id': target_vm
['instance_vnf_id'],
4724 'vm_id': target_vm
['vm_id'],
4725 'vim_name': vm_name
,
4727 db_instance_vms
.append(db_instance_vm
)
4729 for vm_iface
in vm_ifaces_to_clone
:
4730 iface_uuid
= str(uuid4())
4731 iface2iface
[vm_iface
["uuid"]] = iface_uuid
4734 'instance_vm_id': vm_uuid
,
4735 "instance_net_id": vm_iface
["instance_net_id"],
4736 'interface_id': vm_iface
['interface_id'],
4737 'type': vm_iface
['type'],
4738 'floating_ip': vm_iface
['floating_ip'],
4739 'port_security': vm_iface
['port_security']
4741 db_instance_interfaces
.append(db_vm_iface
)
4742 task_params_copy
= deepcopy(task_params
)
4743 for iface
in task_params_copy
[5]:
4744 iface
["uuid"] = iface2iface
[iface
["uuid"]]
4745 # increment ip_address
4746 if "ip_address" in iface
:
4747 ip
= iface
.get("ip_address")
4752 ip
= ip
[i
:] + str(int(ip
[:i
]) + 1)
4753 iface
["ip_address"] = ip
4755 iface
["ip_address"] = None
4757 task_params_copy
[0] = vm_name
4759 "instance_action_id": instance_action_id
,
4760 "task_index": task_index
,
4761 "datacenter_vim_id": vim_action_to_clone
["datacenter_vim_id"],
4763 "status": "SCHEDULED",
4764 "item": "instance_vms",
4769 # TODO examinar parametros, quitar MAC o incrementar. Incrementar IP y colocar las dependencias con ACTION-asdfasd.
4772 "extra": yaml
.safe_dump({"params": task_params_copy
, "depends_on": task_depends_on
}, default_flow_style
=True, width
=256)
4775 db_vim_actions
.append(db_vim_action
)
4776 vm_result
["created"].append(vm_uuid
)
4778 db_instance_action
["number_tasks"] = task_index
4780 {"instance_vms": db_instance_vms
},
4781 {"instance_interfaces": db_instance_interfaces
},
4782 {"instance_actions": db_instance_action
},
4784 # {"instance_sfis": db_instance_sfis},
4785 # {"instance_sfs": db_instance_sfs},
4786 # {"instance_classifications": db_instance_classifications},
4787 # {"instance_sfps": db_instance_sfps},
4788 {"vim_wim_actions": db_vim_actions
}
4790 logger
.debug("create_vdu done DB tables: %s",
4791 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
4792 mydb
.new_rows(db_tables
, [])
4793 for myvim_thread
in myvim_threads_id
.values():
4794 vim_threads
["running"][myvim_thread
].insert_task(db_vim_actions
)
4798 input_vnfs
= action_dict
.pop("vnfs", [])
4799 input_vms
= action_dict
.pop("vms", [])
4800 action_over_all
= True if not input_vnfs
and not input_vms
else False
4801 for sce_vnf
in instanceDict
['vnfs']:
4802 for vm
in sce_vnf
['vms']:
4803 if not action_over_all
and sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
4804 sce_vnf
['member_vnf_index'] not in input_vnfs
and \
4805 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
and \
4806 sce_vnf
['member_vnf_index'] + "-" + vm
['vdu_osm_id'] not in input_vms
: # TODO conside vm_count_index
4809 if "add_public_key" in action_dict
:
4810 if sce_vnf
.get('mgmt_access'):
4811 mgmt_access
= yaml
.load(sce_vnf
['mgmt_access'])
4812 if not input_vms
and mgmt_access
.get("vdu-id") != vm
['vdu_osm_id']:
4814 default_user
= mgmt_access
.get("default-user")
4815 password
= mgmt_access
.get("password")
4816 if mgmt_access
.get(vm
['vdu_osm_id']):
4817 default_user
= mgmt_access
[vm
['vdu_osm_id']].get("default-user", default_user
)
4818 password
= mgmt_access
[vm
['vdu_osm_id']].get("password", password
)
4820 tenant
= mydb
.get_rows_by_id('nfvo_tenants', nfvo_tenant
)
4822 if 'ip_address' in vm
:
4823 mgmt_ip
= vm
['ip_address'].split(';')
4824 priv_RO_key
= decrypt_key(tenant
[0]['encrypted_RO_priv_key'], tenant
[0]['uuid'])
4825 data
= myvim
.inject_user_key(mgmt_ip
[0], action_dict
.get('user', default_user
),
4826 action_dict
['add_public_key'],
4827 password
=password
, ro_key
=priv_RO_key
)
4828 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4829 "description": "Public key injected",
4833 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4834 httperrors
.Internal_Server_Error
)
4836 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4837 httperrors
.Internal_Server_Error
)
4839 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
4840 if "console" in action_dict
:
4841 if not global_config
["http_console_proxy"]:
4842 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4843 "description": "{protocol}//{ip}:{port}/{suffix}".format(
4844 protocol
=data
["protocol"],
4845 ip
= data
["server"],
4846 port
= data
["port"],
4847 suffix
= data
["suffix"]),
4851 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
4852 vm_result
[ vm
['uuid'] ] = {"vim_result": -httperrors
.Unauthorized
,
4853 "description": "this console is only reachable by local interface",
4858 #print "console data", data
4860 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
4861 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4862 "description": "{protocol}//{ip}:{port}/{suffix}".format(
4863 protocol
=data
["protocol"],
4864 ip
= global_config
["http_console_host"],
4865 port
= console_thread
.port
,
4866 suffix
= data
["suffix"]),
4870 except NfvoException
as e
:
4871 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
4875 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
4877 except vimconn
.vimconnException
as e
:
4878 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
4881 if vm_ok
==0: #all goes wrong
4886 def instance_action_get(mydb
, nfvo_tenant
, instance_id
, action_id
):
4888 if nfvo_tenant
and nfvo_tenant
!= "any":
4889 filter["tenant_id"] = nfvo_tenant
4890 if instance_id
and instance_id
!= "any":
4891 filter["instance_id"] = instance_id
4893 filter["uuid"] = action_id
4894 rows
= mydb
.get_rows(FROM
="instance_actions", WHERE
=filter)
4897 raise NfvoException("Not found any action with this criteria", httperrors
.Not_Found
)
4898 vim_wim_actions
= mydb
.get_rows(FROM
="vim_wim_actions", WHERE
={"instance_action_id": action_id
})
4899 rows
[0]["vim_wim_actions"] = vim_wim_actions
4900 # for backward compatibility set vim_actions = vim_wim_actions
4901 rows
[0]["vim_actions"] = vim_wim_actions
4902 return {"actions": rows
}
4905 def create_or_use_console_proxy_thread(console_server
, console_port
):
4906 #look for a non-used port
4907 console_thread_key
= console_server
+ ":" + str(console_port
)
4908 if console_thread_key
in global_config
["console_thread"]:
4909 #global_config["console_thread"][console_thread_key].start_timeout()
4910 return global_config
["console_thread"][console_thread_key
]
4912 for port
in global_config
["console_port_iterator"]():
4913 #print "create_or_use_console_proxy_thread() port:", port
4914 if port
in global_config
["console_ports"]:
4917 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
4919 global_config
["console_thread"][console_thread_key
] = clithread
4920 global_config
["console_ports"][port
] = console_thread_key
4922 except cli
.ConsoleProxyExceptionPortUsed
as e
:
4923 #port used, try with onoher
4925 except cli
.ConsoleProxyException
as e
:
4926 raise NfvoException(str(e
), httperrors
.Bad_Request
)
4927 raise NfvoException("Not found any free 'http_console_ports'", httperrors
.Conflict
)
4930 def check_tenant(mydb
, tenant_id
):
4931 '''check that tenant exists at database'''
4932 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
4934 raise NfvoException("tenant '{}' not found".format(tenant_id
), httperrors
.Not_Found
)
4937 def new_tenant(mydb
, tenant_dict
):
4939 tenant_uuid
= str(uuid4())
4940 tenant_dict
['uuid'] = tenant_uuid
4942 pub_key
, priv_key
= create_RO_keypair(tenant_uuid
)
4943 tenant_dict
['RO_pub_key'] = pub_key
4944 tenant_dict
['encrypted_RO_priv_key'] = priv_key
4945 mydb
.new_row("nfvo_tenants", tenant_dict
, confidential_data
=True)
4946 except db_base_Exception
as e
:
4947 raise NfvoException("Error creating the new tenant: {} ".format(tenant_dict
['name']) + str(e
), e
.http_code
)
4950 def delete_tenant(mydb
, tenant
):
4951 #get nfvo_tenant info
4953 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
4954 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
4955 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
4958 def new_datacenter(mydb
, datacenter_descriptor
):
4959 sdn_port_mapping
= None
4960 if "config" in datacenter_descriptor
:
4961 sdn_port_mapping
= datacenter_descriptor
["config"].pop("sdn-port-mapping", None)
4962 datacenter_descriptor
["config"] = yaml
.safe_dump(datacenter_descriptor
["config"], default_flow_style
=True,
4964 # Check that datacenter-type is correct
4965 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
4966 # module_info = None
4968 module
= "vimconn_" + datacenter_type
4969 pkg
= __import__("osm_ro." + module
)
4970 # vim_conn = getattr(pkg, module)
4971 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
4972 except (IOError, ImportError):
4973 # if module_info and module_info[0]:
4974 # file.close(module_info[0])
4975 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}.py' not installed".format(datacenter_type
,
4977 httperrors
.Bad_Request
)
4979 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True, confidential_data
=True)
4980 if sdn_port_mapping
:
4982 datacenter_sdn_port_mapping_set(mydb
, None, datacenter_id
, sdn_port_mapping
)
4983 except Exception as e
:
4984 mydb
.delete_row_by_id("datacenters", datacenter_id
) # Rollback
4986 return datacenter_id
4989 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
4990 # obtain data, check that only one exist
4991 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
4994 datacenter_id
= datacenter
['uuid']
4995 where
= {'uuid': datacenter
['uuid']}
4996 remove_port_mapping
= False
4997 new_sdn_port_mapping
= None
4998 if "config" in datacenter_descriptor
:
4999 if datacenter_descriptor
['config'] != None:
5001 new_config_dict
= datacenter_descriptor
["config"]
5002 if "sdn-port-mapping" in new_config_dict
:
5003 remove_port_mapping
= True
5004 new_sdn_port_mapping
= new_config_dict
.pop("sdn-port-mapping")
5005 # delete null fields
5007 for k
in new_config_dict
:
5008 if new_config_dict
[k
] is None:
5010 if k
== 'sdn-controller':
5011 remove_port_mapping
= True
5013 config_text
= datacenter
.get("config")
5016 config_dict
= yaml
.load(config_text
)
5017 config_dict
.update(new_config_dict
)
5018 # delete null fields
5021 except Exception as e
:
5022 raise NfvoException("Bad format at datacenter:config " + str(e
), httperrors
.Bad_Request
)
5024 datacenter_descriptor
["config"] = yaml
.safe_dump(config_dict
, default_flow_style
=True, width
=256)
5026 datacenter_descriptor
["config"] = None
5027 if remove_port_mapping
:
5029 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_id
)
5030 except ovimException
as e
:
5031 raise NfvoException("Error deleting datacenter-port-mapping " + str(e
), httperrors
.Conflict
)
5033 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
5034 if new_sdn_port_mapping
:
5036 datacenter_sdn_port_mapping_set(mydb
, None, datacenter_id
, new_sdn_port_mapping
)
5037 except ovimException
as e
:
5039 mydb
.update_rows('datacenters', datacenter
, where
)
5040 raise NfvoException("Error adding datacenter-port-mapping " + str(e
), httperrors
.Conflict
)
5041 return datacenter_id
5044 def delete_datacenter(mydb
, datacenter
):
5045 #get nfvo_tenant info
5046 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
5047 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
5049 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_dict
['uuid'])
5050 except ovimException
as e
:
5051 raise NfvoException("Error deleting datacenter-port-mapping " + str(e
))
5052 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
5055 def create_vim_account(mydb
, nfvo_tenant
, datacenter_id
, name
=None, vim_id
=None, vim_tenant
=None, vim_tenant_name
=None,
5056 vim_username
=None, vim_password
=None, config
=None):
5057 # get datacenter info
5059 if not datacenter_id
:
5061 raise NfvoException("You must provide 'vim_id", http_code
=httperrors
.Bad_Request
)
5062 datacenter_id
= vim_id
5063 datacenter_id
, datacenter_name
= get_datacenter_uuid(mydb
, None, datacenter_id
)
5065 create_vim_tenant
= True if not vim_tenant
and not vim_tenant_name
else False
5067 # get nfvo_tenant info
5068 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
5069 if vim_tenant_name
==None:
5070 vim_tenant_name
=tenant_dict
['name']
5072 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
5073 # #check that this association does not exist before
5074 # tenants_datacenters = mydb.get_rows(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict)
5075 # if len(tenants_datacenters)>0:
5076 # raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id, tenant_dict['uuid']), httperrors.Conflict)
5078 vim_tenant_id_exist_atdb
=False
5079 if not create_vim_tenant
:
5080 where_
={"datacenter_id": datacenter_id
}
5081 if vim_tenant
!=None:
5082 where_
["vim_tenant_id"] = vim_tenant
5083 if vim_tenant_name
!=None:
5084 where_
["vim_tenant_name"] = vim_tenant_name
5085 #check if vim_tenant_id is already at database
5086 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
5087 if len(datacenter_tenants_dict
)>=1:
5088 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
5089 vim_tenant_id_exist_atdb
=True
5090 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
5092 datacenter_tenants_dict
= {}
5093 #insert at table datacenter_tenants
5094 else: #if vim_tenant==None:
5095 #create tenant at VIM if not provided
5097 _
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
, vim_user
=vim_username
,
5098 vim_passwd
=vim_password
)
5099 datacenter_name
= myvim
["name"]
5100 vim_tenant
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
5101 except vimconn
.vimconnException
as e
:
5102 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), httperrors
.Internal_Server_Error
)
5103 datacenter_tenants_dict
= {}
5104 datacenter_tenants_dict
["created"]="true"
5106 #fill datacenter_tenants table
5107 if not vim_tenant_id_exist_atdb
:
5108 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant
5109 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
5110 datacenter_tenants_dict
["user"] = vim_username
5111 datacenter_tenants_dict
["passwd"] = vim_password
5112 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
5114 datacenter_tenants_dict
["name"] = name
5116 datacenter_tenants_dict
["name"] = datacenter_name
5118 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
5119 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True, confidential_data
=True)
5120 datacenter_tenants_dict
["uuid"] = id_
5122 #fill tenants_datacenters table
5123 datacenter_tenant_id
= datacenter_tenants_dict
["uuid"]
5124 tenants_datacenter_dict
["datacenter_tenant_id"] = datacenter_tenant_id
5125 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
5128 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
5129 new_thread
= vim_thread
.vim_thread(task_lock
, thread_name
, datacenter_name
, datacenter_tenant_id
,
5130 db
=db
, db_lock
=db_lock
, ovim
=ovim
)
5132 thread_id
= datacenter_tenants_dict
["uuid"]
5133 vim_threads
["running"][thread_id
] = new_thread
5135 except vimconn
.vimconnException
as e
:
5136 raise NfvoException(str(e
), httperrors
.Bad_Request
)
5139 def edit_vim_account(mydb
, nfvo_tenant
, datacenter_tenant_id
, datacenter_id
=None, name
=None, vim_tenant
=None,
5140 vim_tenant_name
=None, vim_username
=None, vim_password
=None, config
=None):
5142 # get vim_account; check is valid for this tenant
5143 from_
= "datacenter_tenants as dt JOIN tenants_datacenters as td ON dt.uuid=td.datacenter_tenant_id"
5144 where_
= {"td.nfvo_tenant_id": nfvo_tenant
}
5145 if datacenter_tenant_id
:
5146 where_
["dt.uuid"] = datacenter_tenant_id
5148 where_
["dt.datacenter_id"] = datacenter_id
5149 vim_accounts
= mydb
.get_rows(SELECT
="dt.uuid as uuid, config", FROM
=from_
, WHERE
=where_
)
5150 if not vim_accounts
:
5151 raise NfvoException("vim_account not found for this tenant", http_code
=httperrors
.Not_Found
)
5152 elif len(vim_accounts
) > 1:
5153 raise NfvoException("found more than one vim_account for this tenant", http_code
=httperrors
.Conflict
)
5154 datacenter_tenant_id
= vim_accounts
[0]["uuid"]
5155 original_config
= vim_accounts
[0]["config"]
5159 original_config_dict
= yaml
.load(original_config
)
5160 original_config_dict
.update(config
)
5161 update
["config"] = yaml
.safe_dump(original_config_dict
, default_flow_style
=True, width
=256)
5163 update_
['name'] = name
5165 update_
['vim_tenant_id'] = vim_tenant
5167 update_
['vim_tenant_name'] = vim_tenant_name
5169 update_
['user'] = vim_username
5171 update_
['passwd'] = vim_password
5173 mydb
.update_rows("datacenter_tenants", UPDATE
=update_
, WHERE
={"uuid": datacenter_tenant_id
})
5175 vim_threads
["running"][datacenter_tenant_id
].insert_task("reload")
5176 return datacenter_tenant_id
5178 def delete_vim_account(mydb
, tenant_id
, vim_account_id
, datacenter
=None):
5179 #get nfvo_tenant info
5180 if not tenant_id
or tenant_id
=="any":
5183 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
5184 tenant_uuid
= tenant_dict
['uuid']
5186 #check that this association exist before
5187 tenants_datacenter_dict
= {}
5189 datacenter_id
, _
= get_datacenter_uuid(mydb
, tenant_uuid
, datacenter
)
5190 tenants_datacenter_dict
["datacenter_id"] = datacenter_id
5191 elif vim_account_id
:
5192 tenants_datacenter_dict
["datacenter_tenant_id"] = vim_account_id
5194 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
5195 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
5196 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
5197 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), httperrors
.Not_Found
)
5199 #delete this association
5200 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
5202 #get vim_tenant info and deletes
5204 for tenant_datacenter_item
in tenant_datacenter_list
:
5205 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
5206 #try to delete vim:tenant
5208 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
5209 if vim_tenant_dict
['created']=='true':
5210 #delete tenant at VIM if created by NFVO
5212 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5213 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
5214 except vimconn
.vimconnException
as e
:
5215 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
5216 logger
.warn(warning
)
5217 except db_base_Exception
as e
:
5218 logger
.error("Cannot delete datacenter_tenants " + str(e
))
5219 pass # the error will be caused because dependencies, vim_tenant can not be deleted
5220 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
5221 thread
= vim_threads
["running"].get(thread_id
)
5223 thread
.insert_task("exit")
5224 vim_threads
["deleting"][thread_id
] = thread
5225 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
5228 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
5230 #get datacenter info
5231 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5233 if 'check-connectivity' in action_dict
:
5235 myvim
.check_vim_connectivity()
5236 except vimconn
.vimconnException
as e
:
5237 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
5238 raise NfvoException(str(e
), e
.http_code
)
5239 elif 'net-update' in action_dict
:
5241 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
5243 except vimconn
.vimconnException
as e
:
5244 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
5245 raise NfvoException(str(e
), httperrors
.Internal_Server_Error
)
5246 #update nets Change from VIM format to NFVO format
5249 net_nfvo
={'datacenter_id': datacenter_id
}
5250 net_nfvo
['name'] = net
['name']
5251 #net_nfvo['description']= net['name']
5252 net_nfvo
['vim_net_id'] = net
['id']
5253 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
5254 net_nfvo
['shared'] = net
['shared']
5255 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
5256 net_list
.append(net_nfvo
)
5257 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
5258 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
5260 elif 'net-edit' in action_dict
:
5261 net
= action_dict
['net-edit'].pop('net')
5262 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
5263 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
5264 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
5266 elif 'net-delete' in action_dict
:
5267 net
= action_dict
['net-deelte'].get('net')
5268 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
5269 result
= mydb
.delete_row(FROM
='datacenter_nets',
5270 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
5274 raise NfvoException("Unknown action " + str(action_dict
), httperrors
.Bad_Request
)
5277 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
5278 #get datacenter info
5279 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5281 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
5282 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
5283 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
5287 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
5288 #get datacenter info
5289 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5292 action_dict
= action_dict
["netmap"]
5293 if 'vim_id' in action_dict
:
5294 filter_dict
["id"] = action_dict
['vim_id']
5295 if 'vim_name' in action_dict
:
5296 filter_dict
["name"] = action_dict
['vim_name']
5298 filter_dict
["shared"] = True
5301 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
5302 except vimconn
.vimconnException
as e
:
5303 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
5304 raise NfvoException(str(e
), httperrors
.Internal_Server_Error
)
5305 if len(vim_nets
)>1 and action_dict
:
5306 raise NfvoException("more than two networks found, specify with vim_id", httperrors
.Conflict
)
5307 elif len(vim_nets
)==0: # and action_dict:
5308 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), httperrors
.Not_Found
)
5310 for net
in vim_nets
:
5311 net_nfvo
={'datacenter_id': datacenter_id
}
5312 if action_dict
and "name" in action_dict
:
5313 net_nfvo
['name'] = action_dict
['name']
5315 net_nfvo
['name'] = net
['name']
5316 #net_nfvo['description']= net['name']
5317 net_nfvo
['vim_net_id'] = net
['id']
5318 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
5319 net_nfvo
['shared'] = net
['shared']
5320 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
5322 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
5323 net_nfvo
["status"] = "OK"
5324 net_nfvo
["uuid"] = net_id
5325 except db_base_Exception
as e
:
5329 net_nfvo
["status"] = "FAIL: " + str(e
)
5330 net_list
.append(net_nfvo
)
5333 def get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
):
5334 # obtain all network data
5336 if utils
.check_valid_uuid(network_id
):
5337 filter_dict
= {"id": network_id
}
5339 filter_dict
= {"name": network_id
}
5341 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5342 network
= myvim
.get_network_list(filter_dict
=filter_dict
)
5343 except vimconn
.vimconnException
as e
:
5344 raise NfvoException("Not possible to get_sdn_net_id from VIM: {}".format(str(e
)), e
.http_code
)
5346 # ensure the network is defined
5347 if len(network
) == 0:
5348 raise NfvoException("Network {} is not present in the system".format(network_id
),
5349 httperrors
.Bad_Request
)
5351 # ensure there is only one network with the provided name
5352 if len(network
) > 1:
5353 raise NfvoException("Multiple networks present in vim identified by {}".format(network_id
), httperrors
.Bad_Request
)
5355 # ensure it is a dataplane network
5356 if network
[0]['type'] != 'data':
5359 # ensure we use the id
5360 network_id
= network
[0]['id']
5362 # search in dabase mano_db in table instance nets for the sdn_net_id that corresponds to the vim_net_id==network_id
5363 # and with instance_scenario_id==NULL
5364 #search_dict = {'vim_net_id': network_id, 'instance_scenario_id': None}
5365 search_dict
= {'vim_net_id': network_id
}
5368 #sdn_network_id = mydb.get_rows(SELECT=('sdn_net_id',), FROM='instance_nets', WHERE=search_dict)[0]['sdn_net_id']
5369 result
= mydb
.get_rows(SELECT
=('sdn_net_id',), FROM
='instance_nets', WHERE
=search_dict
)
5370 except db_base_Exception
as e
:
5371 raise NfvoException("db_base_Exception obtaining SDN network to associated to vim network {}".format(
5372 network_id
) + str(e
), e
.http_code
)
5376 if net
['sdn_net_id'] != None:
5378 sdn_net_id
= net
['sdn_net_id']
5380 if sdn_net_counter
== 0:
5382 elif sdn_net_counter
== 1:
5385 raise NfvoException("More than one SDN network is associated to vim network {}".format(
5386 network_id
), httperrors
.Internal_Server_Error
)
5388 def get_sdn_controller_id(mydb
, datacenter
):
5389 # Obtain sdn controller id
5390 config
= mydb
.get_rows(SELECT
=('config',), FROM
='datacenters', WHERE
={'uuid': datacenter
})[0].get('config', '{}')
5394 return yaml
.load(config
).get('sdn-controller')
5396 def vim_net_sdn_attach(mydb
, tenant_id
, datacenter
, network_id
, descriptor
):
5398 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
5399 if not sdn_network_id
:
5400 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
), httperrors
.Internal_Server_Error
)
5402 #Obtain sdn controller id
5403 controller_id
= get_sdn_controller_id(mydb
, datacenter
)
5404 if not controller_id
:
5405 raise NfvoException("No SDN controller is set for datacenter {}".format(datacenter
), httperrors
.Internal_Server_Error
)
5407 #Obtain sdn controller info
5408 sdn_controller
= ovim
.show_of_controller(controller_id
)
5411 'name': 'external_port',
5412 'net_id': sdn_network_id
,
5413 'ofc_id': controller_id
,
5414 'switch_dpid': sdn_controller
['dpid'],
5415 'switch_port': descriptor
['port']
5418 if 'vlan' in descriptor
:
5419 port_data
['vlan'] = descriptor
['vlan']
5420 if 'mac' in descriptor
:
5421 port_data
['mac'] = descriptor
['mac']
5423 result
= ovim
.new_port(port_data
)
5424 except ovimException
as e
:
5425 raise NfvoException("ovimException attaching SDN network {} to vim network {}".format(
5426 sdn_network_id
, network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5427 except db_base_Exception
as e
:
5428 raise NfvoException("db_base_Exception attaching SDN network to vim network {}".format(
5429 network_id
) + str(e
), e
.http_code
)
5431 return 'Port uuid: '+ result
5433 def vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, network_id
, port_id
=None):
5435 filter = {'uuid': port_id
}
5437 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
5438 if not sdn_network_id
:
5439 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
),
5440 httperrors
.Internal_Server_Error
)
5441 #in case no port_id is specified only ports marked as 'external_port' will be detached
5442 filter = {'name': 'external_port', 'net_id': sdn_network_id
}
5445 port_list
= ovim
.get_ports(columns
={'uuid'}, filter=filter)
5446 except ovimException
as e
:
5447 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
5448 httperrors
.Internal_Server_Error
)
5450 if len(port_list
) == 0:
5451 raise NfvoException("No ports attached to the network {} were found with the requested criteria".format(network_id
),
5452 httperrors
.Bad_Request
)
5455 for port
in port_list
:
5457 port_uuid_list
.append(port
['uuid'])
5458 ovim
.delete_port(port
['uuid'])
5459 except ovimException
as e
:
5460 raise NfvoException("ovimException deleting port {} for net {}. ".format(port
['uuid'], network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5462 return 'Detached ports uuid: {}'.format(','.join(port_uuid_list
))
5464 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
5465 #get datacenter info
5466 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5469 if utils
.check_valid_uuid(name
):
5470 filter_dict
["id"] = name
5472 filter_dict
["name"] = name
5474 if item
=="networks":
5475 #filter_dict['tenant_id'] = myvim['tenant_id']
5476 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
5478 if len(content
) == 0:
5479 raise NfvoException("Network {} is not present in the system. ".format(name
),
5480 httperrors
.Bad_Request
)
5482 #Update the networks with the attached ports
5484 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, net
['id'])
5485 if sdn_network_id
!= None:
5487 #port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan'}, filter={'name': 'external_port', 'net_id': sdn_network_id})
5488 port_list
= ovim
.get_ports(columns
={'uuid', 'switch_port', 'vlan','name'}, filter={'net_id': sdn_network_id
})
5489 except ovimException
as e
:
5490 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5491 #Remove field name and if port name is external_port save it as 'type'
5492 for port
in port_list
:
5493 if port
['name'] == 'external_port':
5494 port
['type'] = "External"
5496 net
['sdn_network_id'] = sdn_network_id
5497 net
['sdn_attached_ports'] = port_list
5499 elif item
=="tenants":
5500 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
5501 elif item
== "images":
5503 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
5505 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5506 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
5507 if name
and len(content
)==1:
5508 return {item
[:-1]: content
[0]}
5509 elif name
and len(content
)==0:
5510 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
5513 return {item
: content
}
5514 except vimconn
.vimconnException
as e
:
5515 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
5516 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
5519 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
5520 #get datacenter info
5521 if tenant_id
== "any":
5524 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5526 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
5527 logger
.debug("vim_action_delete vim response: " + str(content
))
5528 items
= content
.values()[0]
5529 if type(items
)==list and len(items
)==0:
5530 raise NfvoException("Not found " + item
, httperrors
.Not_Found
)
5531 elif type(items
)==list and len(items
)>1:
5532 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), httperrors
.Not_Found
)
5533 else: # it is a dict
5534 item_id
= items
["id"]
5535 item_name
= str(items
.get("name"))
5538 if item
=="networks":
5539 # If there is a SDN network associated to the vim-network, proceed to clear the relationship and delete it
5540 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, item_id
)
5541 if sdn_network_id
!= None:
5542 #Delete any port attachment to this network
5544 port_list
= ovim
.get_ports(columns
={'uuid'}, filter={'net_id': sdn_network_id
})
5545 except ovimException
as e
:
5546 raise NfvoException(
5547 "ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
5548 httperrors
.Internal_Server_Error
)
5550 # By calling one by one all ports to be detached we ensure that not only the external_ports get detached
5551 for port
in port_list
:
5552 vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, item_id
, port
['uuid'])
5554 #Delete from 'instance_nets' the correspondence between the vim-net-id and the sdn-net-id
5556 mydb
.delete_row(FROM
='instance_nets', WHERE
={'instance_scenario_id': None, 'sdn_net_id': sdn_network_id
, 'vim_net_id': item_id
})
5557 except db_base_Exception
as e
:
5558 raise NfvoException("Error deleting correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
5559 str(e
), e
.http_code
)
5561 #Delete the SDN network
5563 ovim
.delete_network(sdn_network_id
)
5564 except ovimException
as e
:
5565 logger
.error("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
), exc_info
=True)
5566 raise NfvoException("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
),
5567 httperrors
.Internal_Server_Error
)
5569 content
= myvim
.delete_network(item_id
)
5570 elif item
=="tenants":
5571 content
= myvim
.delete_tenant(item_id
)
5572 elif item
== "images":
5573 content
= myvim
.delete_image(item_id
)
5575 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5576 except vimconn
.vimconnException
as e
:
5577 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
5578 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
5580 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
5583 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
5584 #get datacenter info
5585 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
5586 if tenant_id
== "any":
5588 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5590 if item
=="networks":
5591 net
= descriptor
["network"]
5592 net_name
= net
.pop("name")
5593 net_type
= net
.pop("type", "bridge")
5594 net_public
= net
.pop("shared", False)
5595 net_ipprofile
= net
.pop("ip_profile", None)
5596 net_vlan
= net
.pop("vlan", None)
5597 net_provider_network_profile
= None
5599 net_provider_network_profile
= {"segmentation-id": net_vlan
}
5600 content
, _
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, provider_network_profile
=net_provider_network_profile
) #, **net)
5602 #If the datacenter has a SDN controller defined and the network is of dataplane type, then create the sdn network
5603 if get_sdn_controller_id(mydb
, datacenter
) != None and (net_type
== 'data' or net_type
== 'ptp'):
5604 #obtain datacenter_tenant_id
5605 datacenter_tenant_id
= mydb
.get_rows(SELECT
=('uuid',),
5606 FROM
='datacenter_tenants',
5607 WHERE
={'datacenter_id': datacenter
})[0]['uuid']
5610 sdn_network
['vlan'] = net_vlan
5611 sdn_network
['type'] = net_type
5612 sdn_network
['name'] = net_name
5613 sdn_network
['region'] = datacenter_tenant_id
5614 ovim_content
= ovim
.new_network(sdn_network
)
5615 except ovimException
as e
:
5616 logger
.error("ovimException creating SDN network={} ".format(
5617 sdn_network
) + str(e
), exc_info
=True)
5618 raise NfvoException("ovimException creating SDN network={} ".format(sdn_network
) + str(e
),
5619 httperrors
.Internal_Server_Error
)
5621 # Save entry in in dabase mano_db in table instance_nets to stablish a dictionary vim_net_id <->sdn_net_id
5622 # use instance_scenario_id=None to distinguish from real instaces of nets
5623 correspondence
= {'instance_scenario_id': None,
5624 'sdn_net_id': ovim_content
,
5625 'vim_net_id': content
,
5626 'datacenter_tenant_id': datacenter_tenant_id
5629 mydb
.new_row('instance_nets', correspondence
, add_uuid
=True)
5630 except db_base_Exception
as e
:
5631 raise NfvoException("Error saving correspondence for VIM/SDN dataplane networks{}: {}".format(
5632 correspondence
, e
), e
.http_code
)
5633 elif item
=="tenants":
5634 tenant
= descriptor
["tenant"]
5635 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
5637 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5638 except vimconn
.vimconnException
as e
:
5639 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
5641 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
5643 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
5644 data
= ovim
.new_of_controller(sdn_controller
)
5645 logger
.debug('New SDN controller created with uuid {}'.format(data
))
5648 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
5649 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
5650 msg
= 'SDN controller {} updated'.format(data
)
5654 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
5655 if controller_id
== None:
5656 data
= ovim
.get_of_controllers()
5658 data
= ovim
.show_of_controller(controller_id
)
5660 msg
= 'SDN controller list:\n {}'.format(data
)
5664 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
5665 select_
= ('uuid', 'config')
5666 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
5667 for datacenter
in datacenters
:
5668 if datacenter
['config']:
5669 config
= yaml
.load(datacenter
['config'])
5670 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
5671 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), httperrors
.Conflict
)
5673 data
= ovim
.delete_of_controller(controller_id
)
5674 msg
= 'SDN controller {} deleted'.format(data
)
5678 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
5679 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
5680 if len(controller
) < 1:
5681 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), httperrors
.Not_Found
)
5684 sdn_controller_id
= yaml
.load(controller
[0]["config"])["sdn-controller"]
5686 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), httperrors
.Bad_Request
)
5688 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
5689 switch_dpid
= sdn_controller
["dpid"]
5692 for compute_node
in sdn_port_mapping
:
5693 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
5695 element
["compute_node"] = compute_node
["compute_node"]
5696 for port
in compute_node
["ports"]:
5697 pci
= port
.get("pci")
5698 element
["switch_port"] = port
.get("switch_port")
5699 element
["switch_mac"] = port
.get("switch_mac")
5700 if not element
["switch_port"] and not element
["switch_mac"]:
5701 raise NfvoException ("The mapping must contain 'switch_port' or 'switch_mac'", httperrors
.Bad_Request
)
5702 for pci_expanded
in utils
.expand_brackets(pci
):
5703 element
["pci"] = pci_expanded
5704 maps
.append(dict(element
))
5706 return ovim
.set_of_port_mapping(maps
, ofc_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, region
=datacenter_id
)
5708 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
5709 maps
= ovim
.get_of_port_mappings(db_filter
={"region": datacenter_id
})
5712 "sdn-controller": None,
5713 "datacenter-id": datacenter_id
,
5715 "ports_mapping": list()
5718 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
5719 if datacenter
['config']:
5720 config
= yaml
.load(datacenter
['config'])
5721 if 'sdn-controller' in config
:
5722 controller_id
= config
['sdn-controller']
5723 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
5724 result
["sdn-controller"] = controller_id
5725 result
["dpid"] = sdn_controller
["dpid"]
5727 if result
["sdn-controller"] == None:
5728 raise NfvoException("SDN controller is not defined for datacenter {}".format(datacenter_id
), httperrors
.Bad_Request
)
5729 if result
["dpid"] == None:
5730 raise NfvoException("It was not possible to determine DPID for SDN controller {}".format(result
["sdn-controller"]),
5731 httperrors
.Internal_Server_Error
)
5736 ports_correspondence_dict
= dict()
5738 if result
["sdn-controller"] != link
["ofc_id"]:
5739 raise NfvoException("The sdn-controller specified for different port mappings differ", httperrors
.Internal_Server_Error
)
5740 if result
["dpid"] != link
["switch_dpid"]:
5741 raise NfvoException("The dpid specified for different port mappings differ", httperrors
.Internal_Server_Error
)
5743 element
["pci"] = link
["pci"]
5744 if link
["switch_port"]:
5745 element
["switch_port"] = link
["switch_port"]
5746 if link
["switch_mac"]:
5747 element
["switch_mac"] = link
["switch_mac"]
5749 if not link
["compute_node"] in ports_correspondence_dict
:
5751 content
["compute_node"] = link
["compute_node"]
5752 content
["ports"] = list()
5753 ports_correspondence_dict
[link
["compute_node"]] = content
5755 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
5757 for key
in sorted(ports_correspondence_dict
):
5758 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
5762 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
5763 return ovim
.clear_of_port_mapping(db_filter
={"region":datacenter_id
})
5765 def create_RO_keypair(tenant_id
):
5767 Creates a public / private keys for a RO tenant and returns their values
5769 tenant_id: ID of the tenant
5771 public_key: Public key for the RO tenant
5772 private_key: Encrypted private key for RO tenant
5776 key
= RSA
.generate(bits
)
5778 public_key
= key
.publickey().exportKey('OpenSSH')
5779 if isinstance(public_key
, ValueError):
5780 raise NfvoException("Unable to create public key: {}".format(public_key
), httperrors
.Internal_Server_Error
)
5781 private_key
= key
.exportKey(passphrase
=tenant_id
, pkcs
=8)
5782 except (ValueError, NameError) as e
:
5783 raise NfvoException("Unable to create private key: {}".format(e
), httperrors
.Internal_Server_Error
)
5784 return public_key
, private_key
5786 def decrypt_key (key
, tenant_id
):
5788 Decrypts an encrypted RSA key
5790 key: Private key to be decrypted
5791 tenant_id: ID of the tenant
5793 unencrypted_key: Unencrypted private key for RO tenant
5796 key
= RSA
.importKey(key
,tenant_id
)
5797 unencrypted_key
= key
.exportKey('PEM')
5798 if isinstance(unencrypted_key
, ValueError):
5799 raise NfvoException("Unable to decrypt the private key: {}".format(unencrypted_key
), httperrors
.Internal_Server_Error
)
5800 except ValueError as e
:
5801 raise NfvoException("Unable to decrypt the private key: {}".format(e
), httperrors
.Internal_Server_Error
)
5802 return unencrypted_key