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)
2679 #We should use the dictionary as input parameter for new_network
2681 if not sce_net
["external"]:
2682 network_id
, _
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2683 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
2684 sce_net
['vim_id'] = network_id
2685 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
2686 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2687 sce_net
["created"] = True
2689 if sce_net
['vim_id'] == None:
2690 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
2691 _
, message
= rollback(mydb
, vims
, rollbackList
)
2692 logger
.error("nfvo.start_scenario: %s", error_text
)
2693 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2694 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
2695 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
2697 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
2698 #For each vnf net, we create it and we add it to instanceNetlist.
2700 for sce_vnf
in scenarioDict
['vnfs']:
2701 for net
in sce_vnf
['nets']:
2702 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
2704 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
2705 myNetName
= myNetName
[0:255] #limit length
2706 myNetType
= net
['type']
2708 myNetDict
["name"] = myNetName
2709 myNetDict
["type"] = myNetType
2710 myNetDict
["tenant_id"] = myvim_tenant
2711 myNetIPProfile
= net
.get('ip_profile', None)
2714 #We should use the dictionary as input parameter for new_network
2715 network_id
, _
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2716 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
2717 net
['vim_id'] = network_id
2718 if sce_vnf
['uuid'] not in auxNetDict
:
2719 auxNetDict
[sce_vnf
['uuid']] = {}
2720 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
2721 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2722 net
["created"] = True
2724 #print "auxNetDict:"
2725 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2727 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
2728 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2730 for sce_vnf
in scenarioDict
['vnfs']:
2731 vnf_availability_zones
= []
2732 for vm
in sce_vnf
['vms']:
2733 vm_av
= vm
.get('availability_zone')
2734 if vm_av
and vm_av
not in vnf_availability_zones
:
2735 vnf_availability_zones
.append(vm_av
)
2737 # check if there is enough availability zones available at vim level.
2738 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
2739 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
2740 raise NfvoException('No enough availability zones at VIM for this deployment', httperrors
.Bad_Request
)
2742 for vm
in sce_vnf
['vms']:
2745 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
2746 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
2747 #myVMDict['description'] = vm['description']
2748 myVMDict
['description'] = myVMDict
['name'][0:99]
2750 myVMDict
['start'] = "no"
2751 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2752 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
2754 #create image at vim in case it not exist
2755 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2756 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
2757 vm
['vim_image_id'] = image_id
2759 #create flavor at vim in case it not exist
2760 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2761 if flavor_dict
['extended']!=None:
2762 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2763 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
2764 vm
['vim_flavor_id'] = flavor_id
2767 myVMDict
['imageRef'] = vm
['vim_image_id']
2768 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2769 myVMDict
['networks'] = []
2770 for iface
in vm
['interfaces']:
2772 if iface
['type']=="data":
2773 netDict
['type'] = iface
['model']
2774 elif "model" in iface
and iface
["model"]!=None:
2775 netDict
['model']=iface
['model']
2776 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2777 #discover type of interface looking at flavor
2778 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2779 for flavor_iface
in numa
.get('interfaces',[]):
2780 if flavor_iface
.get('name') == iface
['internal_name']:
2781 if flavor_iface
['dedicated'] == 'yes':
2782 netDict
['type']="PF" #passthrough
2783 elif flavor_iface
['dedicated'] == 'no':
2784 netDict
['type']="VF" #siov
2785 elif flavor_iface
['dedicated'] == 'yes:sriov':
2786 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2787 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2789 netDict
["use"]=iface
['type']
2790 if netDict
["use"]=="data" and not netDict
.get("type"):
2791 #print "netDict", netDict
2792 #print "iface", iface
2793 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'])
2794 if flavor_dict
.get('extended')==None:
2795 raise NfvoException(e_text
+ "After database migration some information is not available. \
2796 Try to delete and create the scenarios and VNFs again", httperrors
.Conflict
)
2798 raise NfvoException(e_text
, httperrors
.Internal_Server_Error
)
2799 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2800 netDict
["type"]="virtual"
2801 if "vpci" in iface
and iface
["vpci"] is not None:
2802 netDict
['vpci'] = iface
['vpci']
2803 if "mac" in iface
and iface
["mac"] is not None:
2804 netDict
['mac_address'] = iface
['mac']
2805 if "port-security" in iface
and iface
["port-security"] is not None:
2806 netDict
['port_security'] = iface
['port-security']
2807 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2808 netDict
['floating_ip'] = iface
['floating-ip']
2809 netDict
['name'] = iface
['internal_name']
2810 if iface
['net_id'] is None:
2811 for vnf_iface
in sce_vnf
["interfaces"]:
2814 if vnf_iface
['interface_id']==iface
['uuid']:
2815 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
2818 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2819 #skip bridge ifaces not connected to any net
2820 #if 'net_id' not in netDict or netDict['net_id']==None:
2822 myVMDict
['networks'].append(netDict
)
2823 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2824 #print myVMDict['name']
2825 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2826 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2827 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2829 if 'availability_zone' in myVMDict
:
2830 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
2834 vm_id
, _
= myvim
.new_vminstance(myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2835 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2836 availability_zone_index
=av_index
,
2837 availability_zone_list
=vnf_availability_zones
)
2838 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
2839 vm
['vim_id'] = vm_id
2840 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2841 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2842 for net
in myVMDict
['networks']:
2844 for iface
in vm
['interfaces']:
2845 if net
["name"]==iface
["internal_name"]:
2846 iface
["vim_id"]=net
["vim_id"]
2849 logger
.debug("start scenario Deployment done")
2850 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2851 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
2852 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
2853 return mydb
.get_instance_scenario(instance_id
)
2855 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
2856 _
, message
= rollback(mydb
, vims
, rollbackList
)
2857 if isinstance(e
, db_base_Exception
):
2858 error_text
= "Exception at database"
2860 error_text
= "Exception at VIM"
2861 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2862 #logger.error("start_scenario %s", error_text)
2863 raise NfvoException(error_text
, e
.http_code
)
2865 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
2866 """ join the cloud config information into cloud_config_preserve.
2867 In case of conflict cloud_config_preserve preserves
2870 if not cloud_config_preserve
and not cloud_config
:
2873 new_cloud_config
= {"key-pairs":[], "users":[]}
2875 if cloud_config_preserve
:
2876 for key
in cloud_config_preserve
.get("key-pairs", () ):
2877 if key
not in new_cloud_config
["key-pairs"]:
2878 new_cloud_config
["key-pairs"].append(key
)
2880 for key
in cloud_config
.get("key-pairs", () ):
2881 if key
not in new_cloud_config
["key-pairs"]:
2882 new_cloud_config
["key-pairs"].append(key
)
2883 if not new_cloud_config
["key-pairs"]:
2884 del new_cloud_config
["key-pairs"]
2888 new_cloud_config
["users"] += cloud_config
.get("users", () )
2889 if cloud_config_preserve
:
2890 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
2891 index_to_delete
= []
2892 users
= new_cloud_config
.get("users", [])
2893 for index0
in range(0,len(users
)):
2894 if index0
in index_to_delete
:
2896 for index1
in range(index0
+1,len(users
)):
2897 if index1
in index_to_delete
:
2899 if users
[index0
]["name"] == users
[index1
]["name"]:
2900 index_to_delete
.append(index1
)
2901 for key
in users
[index1
].get("key-pairs",()):
2902 if "key-pairs" not in users
[index0
]:
2903 users
[index0
]["key-pairs"] = [key
]
2904 elif key
not in users
[index0
]["key-pairs"]:
2905 users
[index0
]["key-pairs"].append(key
)
2906 index_to_delete
.sort(reverse
=True)
2907 for index
in index_to_delete
:
2909 if not new_cloud_config
["users"]:
2910 del new_cloud_config
["users"]
2913 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
2914 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
2915 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
2916 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
2919 new_cloud_config
["user-data"] = []
2920 if cloud_config
and cloud_config
.get("user-data"):
2921 if isinstance(cloud_config
["user-data"], list):
2922 new_cloud_config
["user-data"] += cloud_config
["user-data"]
2924 new_cloud_config
["user-data"].append(cloud_config
["user-data"])
2925 if cloud_config_preserve
and cloud_config_preserve
.get("user-data"):
2926 if isinstance(cloud_config_preserve
["user-data"], list):
2927 new_cloud_config
["user-data"] += cloud_config_preserve
["user-data"]
2929 new_cloud_config
["user-data"].append(cloud_config_preserve
["user-data"])
2930 if not new_cloud_config
["user-data"]:
2931 del new_cloud_config
["user-data"]
2934 new_cloud_config
["config-files"] = []
2935 if cloud_config
and cloud_config
.get("config-files") != None:
2936 new_cloud_config
["config-files"] += cloud_config
["config-files"]
2937 if cloud_config_preserve
:
2938 for file in cloud_config_preserve
.get("config-files", ()):
2939 for index
in range(0, len(new_cloud_config
["config-files"])):
2940 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
2941 new_cloud_config
["config-files"][index
] = file
2944 new_cloud_config
["config-files"].append(file)
2945 if not new_cloud_config
["config-files"]:
2946 del new_cloud_config
["config-files"]
2947 return new_cloud_config
2950 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
2951 datacenter_id
= None
2952 datacenter_name
= None
2955 if datacenter_tenant_id
:
2956 thread_id
= datacenter_tenant_id
2957 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
2959 where_
={"td.nfvo_tenant_id": tenant_id
}
2960 if datacenter_id_name
:
2961 if utils
.check_valid_uuid(datacenter_id_name
):
2962 datacenter_id
= datacenter_id_name
2963 where_
["dt.datacenter_id"] = datacenter_id
2965 datacenter_name
= datacenter_id_name
2966 where_
["d.name"] = datacenter_name
2967 if datacenter_tenant_id
:
2968 where_
["dt.uuid"] = datacenter_tenant_id
2969 datacenters
= mydb
.get_rows(
2970 SELECT
=("dt.uuid as datacenter_tenant_id",),
2971 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
2972 "join datacenters as d on d.uuid=dt.datacenter_id",
2974 if len(datacenters
) > 1:
2975 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
2977 thread_id
= datacenters
[0]["datacenter_tenant_id"]
2978 thread
= vim_threads
["running"].get(thread_id
)
2980 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
2981 return thread_id
, thread
2982 except db_base_Exception
as e
:
2983 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
2986 def get_datacenter_uuid(mydb
, tenant_id
, datacenter_id_name
):
2988 if utils
.check_valid_uuid(datacenter_id_name
):
2989 WHERE_dict
['d.uuid'] = datacenter_id_name
2991 WHERE_dict
['d.name'] = datacenter_id_name
2994 WHERE_dict
['nfvo_tenant_id'] = tenant_id
2995 from_
= "tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join datacenter_tenants as" \
2996 " dt on td.datacenter_tenant_id=dt.uuid"
2998 from_
= 'datacenters as d'
2999 vimaccounts
= mydb
.get_rows(FROM
=from_
, SELECT
=("d.uuid as uuid, d.name as name",), WHERE
=WHERE_dict
)
3000 if len(vimaccounts
) == 0:
3001 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
3002 elif len(vimaccounts
)>1:
3003 #print "nfvo.datacenter_action() error. Several datacenters found"
3004 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
3005 return vimaccounts
[0]["uuid"], vimaccounts
[0]["name"]
3008 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
3009 datacenter_id
= None
3010 datacenter_name
= None
3011 if datacenter_id_name
:
3012 if utils
.check_valid_uuid(datacenter_id_name
):
3013 datacenter_id
= datacenter_id_name
3015 datacenter_name
= datacenter_id_name
3016 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
3018 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
3020 #print "nfvo.datacenter_action() error. Several datacenters found"
3021 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
3022 return vims
.keys()[0], vims
.values()[0]
3026 """Takes dict d and updates it with the values in dict u.
3027 It merges all depth levels"""
3028 for k
, v
in u
.iteritems():
3029 if isinstance(v
, collections
.Mapping
):
3030 r
= update(d
.get(k
, {}), v
)
3037 def create_instance(mydb
, tenant_id
, instance_dict
):
3038 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
3039 # logger.debug("Creating instance...")
3040 scenario
= instance_dict
["scenario"]
3042 # find main datacenter
3044 myvim_threads_id
= {}
3045 datacenter
= instance_dict
.get("datacenter")
3046 default_wim_account
= instance_dict
.get("wim_account")
3047 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3048 myvims
[default_datacenter_id
] = vim
3049 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
3050 tenant
= mydb
.get_rows_by_id('nfvo_tenants', tenant_id
)
3051 # myvim_tenant = myvim['tenant_id']
3054 # print "Checking that the scenario exists and getting the scenario dictionary"
3055 if isinstance(scenario
, str):
3056 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, datacenter_vim_id
=myvim_threads_id
[default_datacenter_id
],
3057 datacenter_id
=default_datacenter_id
)
3059 scenarioDict
= scenario
3060 scenarioDict
["uuid"] = None
3062 # logger.debug(">>>>>> Dictionaries before merging")
3063 # logger.debug(">>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
3064 # logger.debug(">>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
3066 db_instance_vnfs
= []
3067 db_instance_vms
= []
3068 db_instance_interfaces
= []
3069 db_instance_sfis
= []
3070 db_instance_sfs
= []
3071 db_instance_classifications
= []
3072 db_instance_sfps
= []
3077 instance_name
= instance_dict
["name"]
3078 instance_uuid
= str(uuid4())
3079 uuid_list
.append(instance_uuid
)
3080 db_instance_scenario
= {
3081 "uuid": instance_uuid
,
3082 "name": instance_name
,
3083 "tenant_id": tenant_id
,
3084 "scenario_id": scenarioDict
['uuid'],
3085 "datacenter_id": default_datacenter_id
,
3086 # filled bellow 'datacenter_tenant_id'
3087 "description": instance_dict
.get("description"),
3089 if scenarioDict
.get("cloud-config"):
3090 db_instance_scenario
["cloud_config"] = yaml
.safe_dump(scenarioDict
["cloud-config"],
3091 default_flow_style
=True, width
=256)
3092 instance_action_id
= get_task_id()
3093 db_instance_action
= {
3094 "uuid": instance_action_id
, # same uuid for the instance and the action on create
3095 "tenant_id": tenant_id
,
3096 "instance_id": instance_uuid
,
3097 "description": "CREATE",
3100 # Auxiliary dictionaries from x to y
3101 sce_net2instance
= {}
3102 net2task_id
= {'scenario': {}}
3103 # Mapping between local networks and WIMs
3106 def ip_profile_IM2RO(ip_profile_im
):
3107 # translate from input format to database format
3109 if 'subnet-address' in ip_profile_im
:
3110 ip_profile_ro
['subnet_address'] = ip_profile_im
['subnet-address']
3111 if 'ip-version' in ip_profile_im
:
3112 ip_profile_ro
['ip_version'] = ip_profile_im
['ip-version']
3113 if 'gateway-address' in ip_profile_im
:
3114 ip_profile_ro
['gateway_address'] = ip_profile_im
['gateway-address']
3115 if 'dns-address' in ip_profile_im
:
3116 ip_profile_ro
['dns_address'] = ip_profile_im
['dns-address']
3117 if isinstance(ip_profile_ro
['dns_address'], (list, tuple)):
3118 ip_profile_ro
['dns_address'] = ";".join(ip_profile_ro
['dns_address'])
3119 if 'dhcp' in ip_profile_im
:
3120 ip_profile_ro
['dhcp_start_address'] = ip_profile_im
['dhcp'].get('start-address')
3121 ip_profile_ro
['dhcp_enabled'] = ip_profile_im
['dhcp'].get('enabled', True)
3122 ip_profile_ro
['dhcp_count'] = ip_profile_im
['dhcp'].get('count')
3123 return ip_profile_ro
3125 # logger.debug("Creating instance from scenario-dict:\n%s",
3126 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
3128 # 0 check correct parameters
3129 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).iteritems():
3130 for scenario_net
in scenarioDict
['nets']:
3131 if net_name
== scenario_net
.get("name") or net_name
== scenario_net
.get("osm_id") or net_name
== scenario_net
.get("uuid"):
3134 raise NfvoException("Invalid scenario network name or id '{}' at instance:networks".format(net_name
),
3135 httperrors
.Bad_Request
)
3136 if "sites" not in net_instance_desc
:
3137 net_instance_desc
["sites"] = [ {} ]
3138 site_without_datacenter_field
= False
3139 for site
in net_instance_desc
["sites"]:
3140 if site
.get("datacenter"):
3141 site
["datacenter"], _
= get_datacenter_uuid(mydb
, tenant_id
, site
["datacenter"])
3142 if site
["datacenter"] not in myvims
:
3143 # Add this datacenter to myvims
3144 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
3146 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
3147 site
["datacenter"] = d
# change name to id
3149 if site_without_datacenter_field
:
3150 raise NfvoException("Found more than one entries without datacenter field at "
3151 "instance:networks:{}:sites".format(net_name
), httperrors
.Bad_Request
)
3152 site_without_datacenter_field
= True
3153 site
["datacenter"] = default_datacenter_id
# change name to id
3155 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
3156 for scenario_vnf
in scenarioDict
['vnfs']:
3157 if vnf_name
== scenario_vnf
['member_vnf_index'] or vnf_name
== scenario_vnf
['uuid'] or vnf_name
== scenario_vnf
['name']:
3160 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_name
), httperrors
.Bad_Request
)
3161 if "datacenter" in vnf_instance_desc
:
3162 # Add this datacenter to myvims
3163 vnf_instance_desc
["datacenter"], _
= get_datacenter_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3164 if vnf_instance_desc
["datacenter"] not in myvims
:
3165 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3167 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3168 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
3170 for net_id
, net_instance_desc
in vnf_instance_desc
.get("networks", {}).iteritems():
3171 for scenario_net
in scenario_vnf
['nets']:
3172 if net_id
== scenario_net
['osm_id'] or net_id
== scenario_net
['uuid'] or net_id
== scenario_net
["name"]:
3175 raise NfvoException("Invalid net id or name '{}' at instance:vnfs:networks".format(net_id
), httperrors
.Bad_Request
)
3176 if net_instance_desc
.get("vim-network-name"):
3177 scenario_net
["vim-network-name"] = net_instance_desc
["vim-network-name"]
3178 if net_instance_desc
.get("vim-network-id"):
3179 scenario_net
["vim-network-id"] = net_instance_desc
["vim-network-id"]
3180 if net_instance_desc
.get("name"):
3181 scenario_net
["name"] = net_instance_desc
["name"]
3182 if 'ip-profile' in net_instance_desc
:
3183 ipprofile_db
= ip_profile_IM2RO(net_instance_desc
['ip-profile'])
3184 if 'ip_profile' not in scenario_net
:
3185 scenario_net
['ip_profile'] = ipprofile_db
3187 update(scenario_net
['ip_profile'], ipprofile_db
)
3189 for vdu_id
, vdu_instance_desc
in vnf_instance_desc
.get("vdus", {}).iteritems():
3190 for scenario_vm
in scenario_vnf
['vms']:
3191 if vdu_id
== scenario_vm
['osm_id'] or vdu_id
== scenario_vm
["name"]:
3194 raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id
), httperrors
.Bad_Request
)
3195 scenario_vm
["instance_parameters"] = vdu_instance_desc
3196 for iface_id
, iface_instance_desc
in vdu_instance_desc
.get("interfaces", {}).iteritems():
3197 for scenario_interface
in scenario_vm
['interfaces']:
3198 if iface_id
== scenario_interface
['internal_name'] or iface_id
== scenario_interface
["external_name"]:
3199 scenario_interface
.update(iface_instance_desc
)
3202 raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id
), httperrors
.Bad_Request
)
3204 # 0.1 parse cloud-config parameters
3205 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
3207 # 0.2 merge instance information into scenario
3208 # Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
3209 # However, this is not possible yet.
3210 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).iteritems():
3211 for scenario_net
in scenarioDict
['nets']:
3212 if net_name
== scenario_net
.get("name") or net_name
== scenario_net
.get("osm_id") or net_name
== scenario_net
.get("uuid"):
3213 if "wim_account" in net_instance_desc
and net_instance_desc
["wim_account"] is not None:
3214 scenario_net
["wim_account"] = net_instance_desc
["wim_account"]
3215 if 'ip-profile' in net_instance_desc
:
3216 ipprofile_db
= ip_profile_IM2RO(net_instance_desc
['ip-profile'])
3217 if 'ip_profile' not in scenario_net
:
3218 scenario_net
['ip_profile'] = ipprofile_db
3220 update(scenario_net
['ip_profile'], ipprofile_db
)
3221 for interface
in net_instance_desc
.get('interfaces', ()):
3222 if 'ip_address' in interface
:
3223 for vnf
in scenarioDict
['vnfs']:
3224 if interface
['vnf'] == vnf
['name']:
3225 for vnf_interface
in vnf
['interfaces']:
3226 if interface
['vnf_interface'] == vnf_interface
['external_name']:
3227 vnf_interface
['ip_address'] = interface
['ip_address']
3229 # logger.debug(">>>>>>>> Merged dictionary")
3230 # logger.debug("Creating instance scenario-dict MERGED:\n%s",
3231 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
3233 # 1. Creating new nets (sce_nets) in the VIM"
3234 number_mgmt_networks
= 0
3235 db_instance_nets
= []
3236 for sce_net
in scenarioDict
['nets']:
3237 sce_net_uuid
= sce_net
.get('uuid', sce_net
["name"])
3238 # get involved datacenters where this network need to be created
3239 involved_datacenters
= []
3240 for sce_vnf
in scenarioDict
.get("vnfs", ()):
3241 vnf_datacenter
= sce_vnf
.get("datacenter", default_datacenter_id
)
3242 if vnf_datacenter
in involved_datacenters
:
3244 if sce_vnf
.get("interfaces"):
3245 for sce_vnf_ifaces
in sce_vnf
["interfaces"]:
3246 if sce_vnf_ifaces
.get("sce_net_id") == sce_net
["uuid"]:
3247 involved_datacenters
.append(vnf_datacenter
)
3249 if not involved_datacenters
:
3250 involved_datacenters
.append(default_datacenter_id
)
3251 target_wim_account
= sce_net
.get("wim_account", default_wim_account
)
3254 # TODO: use this information during network creation
3255 wim_account_id
= wim_account_name
= None
3256 if len(involved_datacenters
) > 1 and 'uuid' in sce_net
:
3257 if target_wim_account
is None or target_wim_account
is True: # automatic selection of WIM
3258 # OBS: sce_net without uuid are used internally to VNFs
3259 # and the assumption is that VNFs will not be split among
3260 # different datacenters
3261 wim_account
= wim_engine
.find_suitable_wim_account(
3262 involved_datacenters
, tenant_id
)
3263 wim_account_id
= wim_account
['uuid']
3264 wim_account_name
= wim_account
['name']
3265 wim_usage
[sce_net
['uuid']] = wim_account_id
3266 elif isinstance(target_wim_account
, str): # manual selection of WIM
3267 wim_account
.persist
.get_wim_account_by(target_wim_account
, tenant_id
)
3268 wim_account_id
= wim_account
['uuid']
3269 wim_account_name
= wim_account
['name']
3270 wim_usage
[sce_net
['uuid']] = wim_account_id
3271 else: # not WIM usage
3272 wim_usage
[sce_net
['uuid']] = False
3276 if instance_dict
.get("networks"):
3277 if sce_net
.get("uuid") in instance_dict
["networks"]:
3278 descriptor_net
= instance_dict
["networks"][sce_net
["uuid"]]
3279 descriptor_net_name
= sce_net
["uuid"]
3280 elif sce_net
.get("osm_id") in instance_dict
["networks"]:
3281 descriptor_net
= instance_dict
["networks"][sce_net
["osm_id"]]
3282 descriptor_net_name
= sce_net
["osm_id"]
3283 elif sce_net
["name"] in instance_dict
["networks"]:
3284 descriptor_net
= instance_dict
["networks"][sce_net
["name"]]
3285 descriptor_net_name
= sce_net
["name"]
3286 net_name
= descriptor_net
.get("vim-network-name")
3287 # add datacenters from instantiation parameters
3288 if descriptor_net
.get("sites"):
3289 for site
in descriptor_net
["sites"]:
3290 if site
.get("datacenter") and site
["datacenter"] not in involved_datacenters
:
3291 involved_datacenters
.append(site
["datacenter"])
3292 sce_net2instance
[sce_net_uuid
] = {}
3293 net2task_id
['scenario'][sce_net_uuid
] = {}
3296 related_network
= None
3297 if descriptor_net
.get("use-network"):
3298 target_instance_nets
= mydb
.get_rows(
3300 FROM
="instance_nets",
3301 WHERE
={"instance_scenario_id": descriptor_net
["use-network"]["instance_scenario_id"],
3302 "osm_id": descriptor_net
["use-network"]["osm_id"]},
3304 if not target_instance_nets
:
3305 raise NfvoException(
3306 "Cannot find the target network at instance:networks[{}]:use-network".format(descriptor_net_name
),
3307 httperrors
.Bad_Request
)
3309 use_network
= target_instance_nets
[0]["related"]
3311 if sce_net
["external"]:
3312 number_mgmt_networks
+= 1
3314 for datacenter_id
in involved_datacenters
:
3316 netmap_create
= None
3317 if descriptor_net
.get("sites"):
3318 for site
in descriptor_net
["sites"]:
3319 if site
.get("datacenter") == datacenter_id
:
3320 netmap_use
= site
.get("netmap-use")
3321 netmap_create
= site
.get("netmap-create")
3324 vim
= myvims
[datacenter_id
]
3325 myvim_thread_id
= myvim_threads_id
[datacenter_id
]
3327 net_type
= sce_net
['type']
3329 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} # 'shared': True
3332 if sce_net
["external"]:
3333 net_name
= sce_net
["name"]
3335 net_name
= "{}-{}".format(instance_name
, sce_net
["name"])
3336 net_name
= net_name
[:255] # limit length
3338 if netmap_use
or netmap_create
:
3339 create_network
= False
3340 lookfor_network
= False
3342 lookfor_network
= True
3343 if utils
.check_valid_uuid(netmap_use
):
3344 lookfor_filter
["id"] = netmap_use
3346 lookfor_filter
["name"] = netmap_use
3348 create_network
= True
3349 net_vim_name
= net_name
3350 if isinstance(netmap_create
, str):
3351 net_vim_name
= netmap_create
3352 elif sce_net
.get("vim_network_name"):
3353 create_network
= False
3354 lookfor_network
= True
3355 lookfor_filter
["name"] = sce_net
.get("vim_network_name")
3356 elif sce_net
["external"]:
3357 if sce_net
.get('vim_id'):
3358 # there is a netmap at datacenter_nets database # TODO REVISE!!!!
3359 create_network
= False
3360 lookfor_network
= True
3361 lookfor_filter
["id"] = sce_net
['vim_id']
3362 elif vim
["config"].get("management_network_id") or vim
["config"].get("management_network_name"):
3363 if number_mgmt_networks
> 1:
3364 raise NfvoException("Found several VLD of type mgmt. "
3365 "You must concrete what vim-network must be use for each one",
3366 httperrors
.Bad_Request
)
3367 create_network
= False
3368 lookfor_network
= True
3369 if vim
["config"].get("management_network_id"):
3370 lookfor_filter
["id"] = vim
["config"]["management_network_id"]
3372 lookfor_filter
["name"] = vim
["config"]["management_network_name"]
3374 # There is not a netmap, look at datacenter for a net with this name and create if not found
3375 create_network
= True
3376 lookfor_network
= True
3377 lookfor_filter
["name"] = sce_net
["name"]
3378 net_vim_name
= sce_net
["name"]
3380 net_vim_name
= net_name
3381 create_network
= True
3382 lookfor_network
= False
3386 task_action
= "CREATE"
3387 task_extra
["params"] = (net_vim_name
, net_type
, sce_net
.get('ip_profile', None), wim_account_name
)
3389 task_extra
["find"] = (lookfor_filter
,)
3390 elif lookfor_network
:
3391 task_action
= "FIND"
3392 task_extra
["params"] = (lookfor_filter
,)
3394 # fill database content
3395 net_uuid
= str(uuid4())
3396 uuid_list
.append(net_uuid
)
3397 sce_net2instance
[sce_net_uuid
][datacenter_id
] = net_uuid
3398 if not related_network
: # all db_instance_nets will have same related
3399 related_network
= use_network
or net_uuid
3402 "osm_id": sce_net
.get("osm_id") or sce_net
["name"],
3403 "related": related_network
,
3405 "vim_name": net_vim_name
,
3406 "instance_scenario_id": instance_uuid
,
3407 "sce_net_id": sce_net
.get("uuid"),
3408 "created": create_network
,
3409 'datacenter_id': datacenter_id
,
3410 'datacenter_tenant_id': myvim_thread_id
,
3411 'status': 'BUILD' # if create_network else "ACTIVE"
3413 db_instance_nets
.append(db_net
)
3415 "instance_action_id": instance_action_id
,
3416 "status": "SCHEDULED",
3417 "task_index": task_index
,
3418 "datacenter_vim_id": myvim_thread_id
,
3419 "action": task_action
,
3420 "item": "instance_nets",
3421 "item_id": net_uuid
,
3422 "related": related_network
,
3423 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
3425 net2task_id
['scenario'][sce_net_uuid
][datacenter_id
] = task_index
3427 db_vim_actions
.append(db_vim_action
)
3429 if 'ip_profile' in sce_net
:
3431 'instance_net_id': net_uuid
,
3432 'ip_version': sce_net
['ip_profile']['ip_version'],
3433 'subnet_address': sce_net
['ip_profile']['subnet_address'],
3434 'gateway_address': sce_net
['ip_profile']['gateway_address'],
3435 'dns_address': sce_net
['ip_profile']['dns_address'],
3436 'dhcp_enabled': sce_net
['ip_profile']['dhcp_enabled'],
3437 'dhcp_start_address': sce_net
['ip_profile']['dhcp_start_address'],
3438 'dhcp_count': sce_net
['ip_profile']['dhcp_count'],
3440 db_ip_profiles
.append(db_ip_profile
)
3444 "default_datacenter_id": default_datacenter_id
,
3445 "myvim_threads_id": myvim_threads_id
,
3446 "instance_uuid": instance_uuid
,
3447 "instance_name": instance_name
,
3448 "instance_action_id": instance_action_id
,
3450 "cloud_config": cloud_config
,
3451 "RO_pub_key": tenant
[0].get('RO_pub_key'),
3452 "instance_parameters": instance_dict
,
3455 "task_index": task_index
,
3456 "uuid_list": uuid_list
,
3457 "db_instance_nets": db_instance_nets
,
3458 "db_vim_actions": db_vim_actions
,
3459 "db_ip_profiles": db_ip_profiles
,
3460 "db_instance_vnfs": db_instance_vnfs
,
3461 "db_instance_vms": db_instance_vms
,
3462 "db_instance_interfaces": db_instance_interfaces
,
3463 "net2task_id": net2task_id
,
3464 "sce_net2instance": sce_net2instance
,
3466 # sce_vnf_list = sorted(scenarioDict['vnfs'], key=lambda k: k['name'])
3467 for sce_vnf
in scenarioDict
.get('vnfs', ()): # sce_vnf_list:
3468 instantiate_vnf(mydb
, sce_vnf
, vnf_params
, vnf_params_out
, rollbackList
)
3469 task_index
= vnf_params_out
["task_index"]
3470 uuid_list
= vnf_params_out
["uuid_list"]
3473 # task_depends_on = []
3474 for vnffg
in scenarioDict
.get('vnffgs', ()):
3475 for rsp
in vnffg
['rsps']:
3477 for cp
in rsp
['connection_points']:
3478 count
= mydb
.get_rows(
3480 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_rsp_hops as h "
3481 "on interfaces.uuid=h.ingress_interface_id",
3482 WHERE
={'h.uuid': cp
['uuid']})[0]['count']
3483 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == cp
['sce_vnf_id']), None)
3484 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3486 for instance_vm
in instance_vms
:
3487 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3489 dependencies
.append(action
['task_index'])
3490 # TODO: throw exception if count != len(instance_vms)
3491 # TODO: and action shouldn't ever be None
3493 for i
in range(count
):
3495 sfi_uuid
= str(uuid4())
3497 "ingress_interface_id": cp
["ingress_interface_id"],
3498 "egress_interface_id": cp
["egress_interface_id"]
3500 uuid_list
.append(sfi_uuid
)
3503 "related": sfi_uuid
,
3504 "instance_scenario_id": instance_uuid
,
3505 'sce_rsp_hop_id': cp
['uuid'],
3506 'datacenter_id': datacenter_id
,
3507 'datacenter_tenant_id': myvim_thread_id
,
3508 "vim_sfi_id": None, # vim thread will populate
3510 db_instance_sfis
.append(db_sfi
)
3512 "instance_action_id": instance_action_id
,
3513 "task_index": task_index
,
3514 "datacenter_vim_id": myvim_thread_id
,
3516 "status": "SCHEDULED",
3517 "item": "instance_sfis",
3518 "item_id": sfi_uuid
,
3519 "related": sfi_uuid
,
3520 "extra": yaml
.safe_dump({"params": extra_params
, "depends_on": [dependencies
[i
]]},
3521 default_flow_style
=True, width
=256)
3523 sfis_created
.append(task_index
)
3525 db_vim_actions
.append(db_vim_action
)
3527 sf_uuid
= str(uuid4())
3528 uuid_list
.append(sf_uuid
)
3532 "instance_scenario_id": instance_uuid
,
3533 'sce_rsp_hop_id': cp
['uuid'],
3534 'datacenter_id': datacenter_id
,
3535 'datacenter_tenant_id': myvim_thread_id
,
3536 "vim_sf_id": None, # vim thread will populate
3538 db_instance_sfs
.append(db_sf
)
3540 "instance_action_id": instance_action_id
,
3541 "task_index": task_index
,
3542 "datacenter_vim_id": myvim_thread_id
,
3544 "status": "SCHEDULED",
3545 "item": "instance_sfs",
3548 "extra": yaml
.safe_dump({"params": "", "depends_on": sfis_created
},
3549 default_flow_style
=True, width
=256)
3551 sfs_created
.append(task_index
)
3553 db_vim_actions
.append(db_vim_action
)
3554 classifier
= rsp
['classifier']
3556 # TODO the following ~13 lines can be reused for the sfi case
3557 count
= mydb
.get_rows(
3558 SELECT
=('vms.count'),
3559 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_classifiers as c on interfaces.uuid=c.interface_id",
3560 WHERE
={'c.uuid': classifier
['uuid']})[0]['count']
3561 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == classifier
['sce_vnf_id']), None)
3562 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3564 for instance_vm
in instance_vms
:
3565 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3567 dependencies
.append(action
['task_index'])
3568 # TODO: throw exception if count != len(instance_vms)
3569 # TODO: and action shouldn't ever be None
3570 classifications_created
= []
3571 for i
in range(count
):
3572 for match
in classifier
['matches']:
3573 # create classifications
3574 classification_uuid
= str(uuid4())
3575 uuid_list
.append(classification_uuid
)
3576 db_classification
= {
3577 "uuid": classification_uuid
,
3578 "related": classification_uuid
,
3579 "instance_scenario_id": instance_uuid
,
3580 'sce_classifier_match_id': match
['uuid'],
3581 'datacenter_id': datacenter_id
,
3582 'datacenter_tenant_id': myvim_thread_id
,
3583 "vim_classification_id": None, # vim thread will populate
3585 db_instance_classifications
.append(db_classification
)
3586 classification_params
= {
3587 "ip_proto": match
["ip_proto"],
3588 "source_ip": match
["source_ip"],
3589 "destination_ip": match
["destination_ip"],
3590 "source_port": match
["source_port"],
3591 "destination_port": match
["destination_port"]
3594 "instance_action_id": instance_action_id
,
3595 "task_index": task_index
,
3596 "datacenter_vim_id": myvim_thread_id
,
3598 "status": "SCHEDULED",
3599 "item": "instance_classifications",
3600 "item_id": classification_uuid
,
3601 "related": classification_uuid
,
3602 "extra": yaml
.safe_dump({"params": classification_params
, "depends_on": [dependencies
[i
]]},
3603 default_flow_style
=True, width
=256)
3605 classifications_created
.append(task_index
)
3607 db_vim_actions
.append(db_vim_action
)
3610 sfp_uuid
= str(uuid4())
3611 uuid_list
.append(sfp_uuid
)
3614 "related": sfp_uuid
,
3615 "instance_scenario_id": instance_uuid
,
3616 'sce_rsp_id': rsp
['uuid'],
3617 'datacenter_id': datacenter_id
,
3618 'datacenter_tenant_id': myvim_thread_id
,
3619 "vim_sfp_id": None, # vim thread will populate
3621 db_instance_sfps
.append(db_sfp
)
3623 "instance_action_id": instance_action_id
,
3624 "task_index": task_index
,
3625 "datacenter_vim_id": myvim_thread_id
,
3627 "status": "SCHEDULED",
3628 "item": "instance_sfps",
3629 "item_id": sfp_uuid
,
3630 "related": sfp_uuid
,
3631 "extra": yaml
.safe_dump({"params": "", "depends_on": sfs_created
+ classifications_created
},
3632 default_flow_style
=True, width
=256)
3635 db_vim_actions
.append(db_vim_action
)
3636 db_instance_action
["number_tasks"] = task_index
3639 logger
.debug('wim_usage:\n%s\n\n', pformat(wim_usage
))
3640 wan_links
= wim_engine
.derive_wan_links(wim_usage
, db_instance_nets
, tenant_id
)
3641 wim_actions
= wim_engine
.create_actions(wan_links
)
3642 wim_actions
, db_instance_action
= (
3643 wim_engine
.incorporate_actions(wim_actions
, db_instance_action
))
3646 scenarioDict
["datacenter2tenant"] = myvim_threads_id
3648 db_instance_scenario
['datacenter_tenant_id'] = myvim_threads_id
[default_datacenter_id
]
3649 db_instance_scenario
['datacenter_id'] = default_datacenter_id
3651 {"instance_scenarios": db_instance_scenario
},
3652 {"instance_vnfs": db_instance_vnfs
},
3653 {"instance_nets": db_instance_nets
},
3654 {"ip_profiles": db_ip_profiles
},
3655 {"instance_vms": db_instance_vms
},
3656 {"instance_interfaces": db_instance_interfaces
},
3657 {"instance_actions": db_instance_action
},
3658 {"instance_sfis": db_instance_sfis
},
3659 {"instance_sfs": db_instance_sfs
},
3660 {"instance_classifications": db_instance_classifications
},
3661 {"instance_sfps": db_instance_sfps
},
3662 {"instance_wim_nets": wan_links
},
3663 {"vim_wim_actions": db_vim_actions
+ wim_actions
}
3666 logger
.debug("create_instance done DB tables: %s",
3667 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
3668 mydb
.new_rows(db_tables
, uuid_list
)
3669 for myvim_thread_id
in myvim_threads_id
.values():
3670 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
3672 wim_engine
.dispatch(wim_actions
)
3674 returned_instance
= mydb
.get_instance_scenario(instance_uuid
)
3675 returned_instance
["action_id"] = instance_action_id
3676 return returned_instance
3677 except (NfvoException
, vimconn
.vimconnException
, wimconn
.WimConnectorError
, db_base_Exception
) as e
:
3678 message
= rollback(mydb
, myvims
, rollbackList
)
3679 if isinstance(e
, db_base_Exception
):
3680 error_text
= "database Exception"
3681 elif isinstance(e
, vimconn
.vimconnException
):
3682 error_text
= "VIM Exception"
3683 elif isinstance(e
, wimconn
.WimConnectorError
):
3684 error_text
= "WIM Exception"
3686 error_text
= "Exception"
3687 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
3688 # logger.error("create_instance: %s", error_text)
3690 raise NfvoException(error_text
, e
.http_code
)
3693 def instantiate_vnf(mydb
, sce_vnf
, params
, params_out
, rollbackList
):
3694 default_datacenter_id
= params
["default_datacenter_id"]
3695 myvim_threads_id
= params
["myvim_threads_id"]
3696 instance_uuid
= params
["instance_uuid"]
3697 instance_name
= params
["instance_name"]
3698 instance_action_id
= params
["instance_action_id"]
3699 myvims
= params
["myvims"]
3700 cloud_config
= params
["cloud_config"]
3701 RO_pub_key
= params
["RO_pub_key"]
3703 task_index
= params_out
["task_index"]
3704 uuid_list
= params_out
["uuid_list"]
3705 db_instance_nets
= params_out
["db_instance_nets"]
3706 db_vim_actions
= params_out
["db_vim_actions"]
3707 db_ip_profiles
= params_out
["db_ip_profiles"]
3708 db_instance_vnfs
= params_out
["db_instance_vnfs"]
3709 db_instance_vms
= params_out
["db_instance_vms"]
3710 db_instance_interfaces
= params_out
["db_instance_interfaces"]
3711 net2task_id
= params_out
["net2task_id"]
3712 sce_net2instance
= params_out
["sce_net2instance"]
3714 vnf_net2instance
= {}
3716 # 2. Creating new nets (vnf internal nets) in the VIM"
3717 # For each vnf net, we create it and we add it to instanceNetlist.
3718 if sce_vnf
.get("datacenter"):
3719 datacenter_id
= sce_vnf
["datacenter"]
3720 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
3722 datacenter_id
= default_datacenter_id
3723 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
3724 for net
in sce_vnf
['nets']:
3726 # descriptor_net = instance_dict.get("vnfs", {}).get(sce_vnf["name"], {})
3727 # net_name = descriptor_net.get("name")
3730 net_name
= "{}-{}".format(instance_name
, net
["name"])
3731 net_name
= net_name
[:255] # limit length
3732 net_type
= net
['type']
3734 if sce_vnf
['uuid'] not in vnf_net2instance
:
3735 vnf_net2instance
[sce_vnf
['uuid']] = {}
3736 if sce_vnf
['uuid'] not in net2task_id
:
3737 net2task_id
[sce_vnf
['uuid']] = {}
3738 net2task_id
[sce_vnf
['uuid']][net
['uuid']] = task_index
3740 # fill database content
3741 net_uuid
= str(uuid4())
3742 uuid_list
.append(net_uuid
)
3743 vnf_net2instance
[sce_vnf
['uuid']][net
['uuid']] = net_uuid
3746 "related": net_uuid
,
3748 "vim_name": net_name
,
3749 "instance_scenario_id": instance_uuid
,
3750 "net_id": net
["uuid"],
3752 'datacenter_id': datacenter_id
,
3753 'datacenter_tenant_id': myvim_thread_id
,
3755 db_instance_nets
.append(db_net
)
3758 if net
.get("vim-network-name"):
3759 lookfor_filter
["name"] = net
["vim-network-name"]
3760 if net
.get("vim-network-id"):
3761 lookfor_filter
["id"] = net
["vim-network-id"]
3763 task_action
= "FIND"
3764 task_extra
= {"params": (lookfor_filter
,)}
3766 task_action
= "CREATE"
3767 task_extra
= {"params": (net_name
, net_type
, net
.get('ip_profile', None))}
3770 "instance_action_id": instance_action_id
,
3771 "task_index": task_index
,
3772 "datacenter_vim_id": myvim_thread_id
,
3773 "status": "SCHEDULED",
3774 "action": task_action
,
3775 "item": "instance_nets",
3776 "item_id": net_uuid
,
3777 "related": net_uuid
,
3778 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
3781 db_vim_actions
.append(db_vim_action
)
3783 if 'ip_profile' in net
:
3785 'instance_net_id': net_uuid
,
3786 'ip_version': net
['ip_profile']['ip_version'],
3787 'subnet_address': net
['ip_profile']['subnet_address'],
3788 'gateway_address': net
['ip_profile']['gateway_address'],
3789 'dns_address': net
['ip_profile']['dns_address'],
3790 'dhcp_enabled': net
['ip_profile']['dhcp_enabled'],
3791 'dhcp_start_address': net
['ip_profile']['dhcp_start_address'],
3792 'dhcp_count': net
['ip_profile']['dhcp_count'],
3794 db_ip_profiles
.append(db_ip_profile
)
3796 # print "vnf_net2instance:"
3797 # print yaml.safe_dump(vnf_net2instance, indent=4, default_flow_style=False)
3799 # 3. Creating new vm instances in the VIM
3800 # myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
3802 if sce_vnf
.get('mgmt_access'):
3803 ssh_access
= sce_vnf
['mgmt_access'].get('config-access', {}).get('ssh-access')
3804 vnf_availability_zones
= []
3805 for vm
in sce_vnf
.get('vms'):
3806 vm_av
= vm
.get('availability_zone')
3807 if vm_av
and vm_av
not in vnf_availability_zones
:
3808 vnf_availability_zones
.append(vm_av
)
3810 # check if there is enough availability zones available at vim level.
3811 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
3812 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
3813 raise NfvoException('No enough availability zones at VIM for this deployment', httperrors
.Bad_Request
)
3815 if sce_vnf
.get("datacenter"):
3816 vim
= myvims
[sce_vnf
["datacenter"]]
3817 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
3818 datacenter_id
= sce_vnf
["datacenter"]
3820 vim
= myvims
[default_datacenter_id
]
3821 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
3822 datacenter_id
= default_datacenter_id
3823 sce_vnf
["datacenter_id"] = datacenter_id
3826 vnf_uuid
= str(uuid4())
3827 uuid_list
.append(vnf_uuid
)
3830 'instance_scenario_id': instance_uuid
,
3831 'vnf_id': sce_vnf
['vnf_id'],
3832 'sce_vnf_id': sce_vnf
['uuid'],
3833 'datacenter_id': datacenter_id
,
3834 'datacenter_tenant_id': myvim_thread_id
,
3836 db_instance_vnfs
.append(db_instance_vnf
)
3838 for vm
in sce_vnf
['vms']:
3840 if vm
.get("pdu_type"):
3844 sce_vnf_name
= sce_vnf
['member_vnf_index'] if sce_vnf
['member_vnf_index'] else sce_vnf
['name']
3845 myVMDict
['name'] = "{}-{}-{}".format(instance_name
[:64], sce_vnf_name
[:64], vm
["name"][:64])
3846 myVMDict
['description'] = myVMDict
['name'][0:99]
3848 # myVMDict['start'] = "no"
3849 if vm
.get("instance_parameters") and vm
["instance_parameters"].get("name"):
3850 myVMDict
['name'] = vm
["instance_parameters"].get("name")
3851 myVMDict
['name'] = myVMDict
['name'][0:255] # limit name length
3852 # create image at vim in case it not exist
3853 image_uuid
= vm
['image_id']
3854 if vm
.get("image_list"):
3855 for alternative_image
in vm
["image_list"]:
3856 if alternative_image
["vim_type"] == vim
["config"]["_vim_type_internal"]:
3857 image_uuid
= alternative_image
['image_id']
3859 image_dict
= mydb
.get_table_by_uuid_name("images", image_uuid
)
3860 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
3861 vm
['vim_image_id'] = image_id
3863 # create flavor at vim in case it not exist
3864 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
3865 if flavor_dict
['extended'] != None:
3866 flavor_dict
['extended'] = yaml
.load(flavor_dict
['extended'])
3867 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
3869 # Obtain information for additional disks
3870 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',),
3871 WHERE
={'vim_id': flavor_id
})
3872 if not extended_flavor_dict
:
3873 raise NfvoException("flavor '{}' not found".format(flavor_id
), httperrors
.Not_Found
)
3875 # extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
3876 myVMDict
['disks'] = None
3877 extended_info
= extended_flavor_dict
[0]['extended']
3878 if extended_info
!= None:
3879 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
3880 if 'disks' in extended_flavor_dict_yaml
:
3881 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
3882 if vm
.get("instance_parameters") and vm
["instance_parameters"].get("devices"):
3883 for disk
in myVMDict
['disks']:
3884 if disk
.get("name") in vm
["instance_parameters"]["devices"]:
3885 disk
.update(vm
["instance_parameters"]["devices"][disk
.get("name")])
3887 vm
['vim_flavor_id'] = flavor_id
3888 myVMDict
['imageRef'] = vm
['vim_image_id']
3889 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
3890 myVMDict
['availability_zone'] = vm
.get('availability_zone')
3891 myVMDict
['networks'] = []
3892 task_depends_on
= []
3893 # TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
3894 is_management_vm
= False
3896 for iface
in vm
['interfaces']:
3898 if iface
['type'] == "data":
3899 netDict
['type'] = iface
['model']
3900 elif "model" in iface
and iface
["model"] != None:
3901 netDict
['model'] = iface
['model']
3902 # TODO in future, remove this because mac_address will not be set, and the type of PV,VF
3903 # is obtained from iterface table model
3904 # discover type of interface looking at flavor
3905 for numa
in flavor_dict
.get('extended', {}).get('numas', []):
3906 for flavor_iface
in numa
.get('interfaces', []):
3907 if flavor_iface
.get('name') == iface
['internal_name']:
3908 if flavor_iface
['dedicated'] == 'yes':
3909 netDict
['type'] = "PF" # passthrough
3910 elif flavor_iface
['dedicated'] == 'no':
3911 netDict
['type'] = "VF" # siov
3912 elif flavor_iface
['dedicated'] == 'yes:sriov':
3913 netDict
['type'] = "VFnotShared" # sriov but only one sriov on the PF
3914 netDict
["mac_address"] = flavor_iface
.get("mac_address")
3916 netDict
["use"] = iface
['type']
3917 if netDict
["use"] == "data" and not netDict
.get("type"):
3918 # print "netDict", netDict
3919 # print "iface", iface
3920 e_text
= "Cannot determine the interface type PF or VF of VNF '{}' VM '{}' iface '{}'".fromat(
3921 sce_vnf
['name'], vm
['name'], iface
['internal_name'])
3922 if flavor_dict
.get('extended') == None:
3923 raise NfvoException(e_text
+ "After database migration some information is not available. \
3924 Try to delete and create the scenarios and VNFs again", httperrors
.Conflict
)
3926 raise NfvoException(e_text
, httperrors
.Internal_Server_Error
)
3927 if netDict
["use"] == "mgmt":
3928 is_management_vm
= True
3929 netDict
["type"] = "virtual"
3930 if netDict
["use"] == "bridge":
3931 netDict
["type"] = "virtual"
3932 if iface
.get("vpci"):
3933 netDict
['vpci'] = iface
['vpci']
3934 if iface
.get("mac"):
3935 netDict
['mac_address'] = iface
['mac']
3936 if iface
.get("mac_address"):
3937 netDict
['mac_address'] = iface
['mac_address']
3938 if iface
.get("ip_address"):
3939 netDict
['ip_address'] = iface
['ip_address']
3940 if iface
.get("port-security") is not None:
3941 netDict
['port_security'] = iface
['port-security']
3942 if iface
.get("floating-ip") is not None:
3943 netDict
['floating_ip'] = iface
['floating-ip']
3944 netDict
['name'] = iface
['internal_name']
3945 if iface
['net_id'] is None:
3946 for vnf_iface
in sce_vnf
["interfaces"]:
3949 if vnf_iface
['interface_id'] == iface
['uuid']:
3950 netDict
['net_id'] = "TASK-{}".format(
3951 net2task_id
['scenario'][vnf_iface
['sce_net_id']][datacenter_id
])
3952 instance_net_id
= sce_net2instance
[vnf_iface
['sce_net_id']][datacenter_id
]
3953 task_depends_on
.append(net2task_id
['scenario'][vnf_iface
['sce_net_id']][datacenter_id
])
3956 netDict
['net_id'] = "TASK-{}".format(net2task_id
[sce_vnf
['uuid']][iface
['net_id']])
3957 instance_net_id
= vnf_net2instance
[sce_vnf
['uuid']][iface
['net_id']]
3958 task_depends_on
.append(net2task_id
[sce_vnf
['uuid']][iface
['net_id']])
3959 # skip bridge ifaces not connected to any net
3960 if 'net_id' not in netDict
or netDict
['net_id'] == None:
3962 myVMDict
['networks'].append(netDict
)
3965 # 'instance_vm_id': instance_vm_uuid,
3966 "instance_net_id": instance_net_id
,
3967 'interface_id': iface
['uuid'],
3968 # 'vim_interface_id': ,
3969 'type': 'external' if iface
['external_name'] is not None else 'internal',
3970 'ip_address': iface
.get('ip_address'),
3971 'mac_address': iface
.get('mac'),
3972 'floating_ip': int(iface
.get('floating-ip', False)),
3973 'port_security': int(iface
.get('port-security', True))
3975 db_vm_ifaces
.append(db_vm_iface
)
3976 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3977 # print myVMDict['name']
3978 # print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
3979 # print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
3980 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3982 # We add the RO key to cloud_config if vnf will need ssh access
3983 cloud_config_vm
= cloud_config
3984 if is_management_vm
and params
["instance_parameters"].get("mgmt_keys"):
3985 cloud_config_vm
= unify_cloud_config({"key-pairs": params
["instance_parameters"]["mgmt_keys"]},
3988 if vm
.get("instance_parameters") and "mgmt_keys" in vm
["instance_parameters"]:
3989 if vm
["instance_parameters"]["mgmt_keys"]:
3990 cloud_config_vm
= unify_cloud_config({"key-pairs": vm
["instance_parameters"]["mgmt_keys"]},
3993 cloud_config_vm
= unify_cloud_config(cloud_config_vm
, {"key-pairs": [RO_pub_key
]})
3994 if vm
.get("boot_data"):
3995 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config_vm
)
3997 if myVMDict
.get('availability_zone'):
3998 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
4001 for vm_index
in range(0, vm
.get('count', 1)):
4002 vm_name
= myVMDict
['name'] + "-" + str(vm_index
+1)
4003 task_params
= (vm_name
, myVMDict
['description'], myVMDict
.get('start', None),
4004 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'], cloud_config_vm
,
4005 myVMDict
['disks'], av_index
, vnf_availability_zones
)
4006 # put interface uuid back to scenario[vnfs][vms[[interfaces]
4007 for net
in myVMDict
['networks']:
4009 for iface
in vm
['interfaces']:
4010 if net
["name"] == iface
["internal_name"]:
4011 iface
["vim_id"] = net
["vim_id"]
4013 vm_uuid
= str(uuid4())
4014 uuid_list
.append(vm_uuid
)
4018 'instance_vnf_id': vnf_uuid
,
4019 # TODO delete "vim_vm_id": vm_id,
4020 "vm_id": vm
["uuid"],
4021 "vim_name": vm_name
,
4024 db_instance_vms
.append(db_vm
)
4027 for db_vm_iface
in db_vm_ifaces
:
4028 iface_uuid
= str(uuid4())
4029 uuid_list
.append(iface_uuid
)
4030 db_vm_iface_instance
= {
4032 "instance_vm_id": vm_uuid
4034 db_vm_iface_instance
.update(db_vm_iface
)
4035 if db_vm_iface_instance
.get("ip_address"): # increment ip_address
4036 ip
= db_vm_iface_instance
.get("ip_address")
4041 ip
= ip
[i
:] + str(int(ip
[:i
]) + 1)
4042 db_vm_iface_instance
["ip_address"] = ip
4044 db_vm_iface_instance
["ip_address"] = None
4045 db_instance_interfaces
.append(db_vm_iface_instance
)
4046 myVMDict
['networks'][iface_index
]["uuid"] = iface_uuid
4050 "instance_action_id": instance_action_id
,
4051 "task_index": task_index
,
4052 "datacenter_vim_id": myvim_thread_id
,
4054 "status": "SCHEDULED",
4055 "item": "instance_vms",
4058 "extra": yaml
.safe_dump({"params": task_params
, "depends_on": task_depends_on
},
4059 default_flow_style
=True, width
=256)
4062 db_vim_actions
.append(db_vim_action
)
4063 params_out
["task_index"] = task_index
4064 params_out
["uuid_list"] = uuid_list
4067 def delete_instance(mydb
, tenant_id
, instance_id
):
4068 # print "Checking that the instance_id exists and getting the instance dictionary"
4069 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
4070 # print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
4071 tenant_id
= instanceDict
["tenant_id"]
4074 # We need to retrieve the WIM Actions now, before the instance_scenario is
4075 # deleted. The reason for that is that: ON CASCADE rules will delete the
4076 # instance_wim_nets record in the database
4077 wim_actions
= wim_engine
.delete_actions(instance_scenario_id
=instance_id
)
4080 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
4081 # 1. Delete from Database
4082 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
4084 # 2. delete from VIM
4088 vimthread_affected
= {}
4089 net2vm_dependencies
= {}
4092 instance_action_id
= get_task_id()
4094 db_instance_action
= {
4095 "uuid": instance_action_id
, # same uuid for the instance and the action on create
4096 "tenant_id": tenant_id
,
4097 "instance_id": instance_id
,
4098 "description": "DELETE",
4099 # "number_tasks": 0 # filled bellow
4102 # 2.1 deleting VNFFGs
4103 for sfp
in instanceDict
.get('sfps', ()):
4104 vimthread_affected
[sfp
["datacenter_tenant_id"]] = None
4105 datacenter_key
= (sfp
["datacenter_id"], sfp
["datacenter_tenant_id"])
4106 if datacenter_key
not in myvims
:
4108 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sfp
["datacenter_id"], sfp
["datacenter_tenant_id"])
4109 except NfvoException
as e
:
4110 logger
.error(str(e
))
4112 myvim_threads
[datacenter_key
] = myvim_thread
4113 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sfp
["datacenter_id"],
4114 datacenter_tenant_id
=sfp
["datacenter_tenant_id"])
4116 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfp
["datacenter_id"], sfp
["datacenter_tenant_id"]))
4117 myvims
[datacenter_key
] = None
4119 myvims
[datacenter_key
] = vims
.values()[0]
4120 myvim
= myvims
[datacenter_key
]
4121 myvim_thread
= myvim_threads
[datacenter_key
]
4124 error_msg
+= "\n vim_sfp_id={} cannot be deleted because datacenter={} not found".format(sfp
['vim_sfp_id'], sfp
["datacenter_id"])
4126 extra
= {"params": (sfp
['vim_sfp_id'])}
4128 "instance_action_id": instance_action_id
,
4129 "task_index": task_index
,
4130 "datacenter_vim_id": sfp
["datacenter_tenant_id"],
4132 "status": "SCHEDULED",
4133 "item": "instance_sfps",
4134 "item_id": sfp
["uuid"],
4135 "related": sfp
["related"],
4136 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4139 db_vim_actions
.append(db_vim_action
)
4141 for classification
in instanceDict
['classifications']:
4142 vimthread_affected
[classification
["datacenter_tenant_id"]] = None
4143 datacenter_key
= (classification
["datacenter_id"], classification
["datacenter_tenant_id"])
4144 if datacenter_key
not in myvims
:
4146 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, classification
["datacenter_id"], classification
["datacenter_tenant_id"])
4147 except NfvoException
as e
:
4148 logger
.error(str(e
))
4150 myvim_threads
[datacenter_key
] = myvim_thread
4151 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=classification
["datacenter_id"],
4152 datacenter_tenant_id
=classification
["datacenter_tenant_id"])
4154 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(classification
["datacenter_id"],
4155 classification
["datacenter_tenant_id"]))
4156 myvims
[datacenter_key
] = None
4158 myvims
[datacenter_key
] = vims
.values()[0]
4159 myvim
= myvims
[datacenter_key
]
4160 myvim_thread
= myvim_threads
[datacenter_key
]
4163 error_msg
+= "\n vim_classification_id={} cannot be deleted because datacenter={} not found".format(classification
['vim_classification_id'],
4164 classification
["datacenter_id"])
4166 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfps"]
4167 extra
= {"params": (classification
['vim_classification_id']), "depends_on": depends_on
}
4169 "instance_action_id": instance_action_id
,
4170 "task_index": task_index
,
4171 "datacenter_vim_id": classification
["datacenter_tenant_id"],
4173 "status": "SCHEDULED",
4174 "item": "instance_classifications",
4175 "item_id": classification
["uuid"],
4176 "related": classification
["related"],
4177 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4180 db_vim_actions
.append(db_vim_action
)
4182 for sf
in instanceDict
.get('sfs', ()):
4183 vimthread_affected
[sf
["datacenter_tenant_id"]] = None
4184 datacenter_key
= (sf
["datacenter_id"], sf
["datacenter_tenant_id"])
4185 if datacenter_key
not in myvims
:
4187 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sf
["datacenter_id"], sf
["datacenter_tenant_id"])
4188 except NfvoException
as e
:
4189 logger
.error(str(e
))
4191 myvim_threads
[datacenter_key
] = myvim_thread
4192 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sf
["datacenter_id"],
4193 datacenter_tenant_id
=sf
["datacenter_tenant_id"])
4195 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sf
["datacenter_id"], sf
["datacenter_tenant_id"]))
4196 myvims
[datacenter_key
] = None
4198 myvims
[datacenter_key
] = vims
.values()[0]
4199 myvim
= myvims
[datacenter_key
]
4200 myvim_thread
= myvim_threads
[datacenter_key
]
4203 error_msg
+= "\n vim_sf_id={} cannot be deleted because datacenter={} not found".format(sf
['vim_sf_id'], sf
["datacenter_id"])
4205 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfps"]
4206 extra
= {"params": (sf
['vim_sf_id']), "depends_on": depends_on
}
4208 "instance_action_id": instance_action_id
,
4209 "task_index": task_index
,
4210 "datacenter_vim_id": sf
["datacenter_tenant_id"],
4212 "status": "SCHEDULED",
4213 "item": "instance_sfs",
4214 "item_id": sf
["uuid"],
4215 "related": sf
["related"],
4216 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4219 db_vim_actions
.append(db_vim_action
)
4221 for sfi
in instanceDict
.get('sfis', ()):
4222 vimthread_affected
[sfi
["datacenter_tenant_id"]] = None
4223 datacenter_key
= (sfi
["datacenter_id"], sfi
["datacenter_tenant_id"])
4224 if datacenter_key
not in myvims
:
4226 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sfi
["datacenter_id"], sfi
["datacenter_tenant_id"])
4227 except NfvoException
as e
:
4228 logger
.error(str(e
))
4230 myvim_threads
[datacenter_key
] = myvim_thread
4231 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sfi
["datacenter_id"],
4232 datacenter_tenant_id
=sfi
["datacenter_tenant_id"])
4234 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfi
["datacenter_id"], sfi
["datacenter_tenant_id"]))
4235 myvims
[datacenter_key
] = None
4237 myvims
[datacenter_key
] = vims
.values()[0]
4238 myvim
= myvims
[datacenter_key
]
4239 myvim_thread
= myvim_threads
[datacenter_key
]
4242 error_msg
+= "\n vim_sfi_id={} cannot be deleted because datacenter={} not found".format(sfi
['vim_sfi_id'], sfi
["datacenter_id"])
4244 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfs"]
4245 extra
= {"params": (sfi
['vim_sfi_id']), "depends_on": depends_on
}
4247 "instance_action_id": instance_action_id
,
4248 "task_index": task_index
,
4249 "datacenter_vim_id": sfi
["datacenter_tenant_id"],
4251 "status": "SCHEDULED",
4252 "item": "instance_sfis",
4253 "item_id": sfi
["uuid"],
4254 "related": sfi
["related"],
4255 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4258 db_vim_actions
.append(db_vim_action
)
4262 for sce_vnf
in instanceDict
.get('vnfs', ()):
4263 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
4264 vimthread_affected
[sce_vnf
["datacenter_tenant_id"]] = None
4265 if datacenter_key
not in myvims
:
4267 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
4268 except NfvoException
as e
:
4269 logger
.error(str(e
))
4271 myvim_threads
[datacenter_key
] = myvim_thread
4272 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
4273 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
4275 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
4276 sce_vnf
["datacenter_tenant_id"]))
4277 myvims
[datacenter_key
] = None
4279 myvims
[datacenter_key
] = vims
.values()[0]
4280 myvim
= myvims
[datacenter_key
]
4281 myvim_thread
= myvim_threads
[datacenter_key
]
4283 for vm
in sce_vnf
['vms']:
4285 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
4287 sfi_dependencies
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfis"]
4289 "instance_action_id": instance_action_id
,
4290 "task_index": task_index
,
4291 "datacenter_vim_id": sce_vnf
["datacenter_tenant_id"],
4293 "status": "SCHEDULED",
4294 "item": "instance_vms",
4295 "item_id": vm
["uuid"],
4296 "related": vm
["related"],
4297 "extra": yaml
.safe_dump({"params": vm
["interfaces"], "depends_on": sfi_dependencies
},
4298 default_flow_style
=True, width
=256)
4300 db_vim_actions
.append(db_vim_action
)
4301 for interface
in vm
["interfaces"]:
4302 if not interface
.get("instance_net_id"):
4304 if interface
["instance_net_id"] not in net2vm_dependencies
:
4305 net2vm_dependencies
[interface
["instance_net_id"]] = []
4306 net2vm_dependencies
[interface
["instance_net_id"]].append(task_index
)
4311 for net
in instanceDict
['nets']:
4312 vimthread_affected
[net
["datacenter_tenant_id"]] = None
4313 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
4314 if datacenter_key
not in myvims
:
4316 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, net
["datacenter_id"], net
["datacenter_tenant_id"])
4317 except NfvoException
as e
:
4318 logger
.error(str(e
))
4320 myvim_threads
[datacenter_key
] = myvim_thread
4321 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
4322 datacenter_tenant_id
=net
["datacenter_tenant_id"])
4324 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
4325 myvims
[datacenter_key
] = None
4327 myvims
[datacenter_key
] = vims
.values()[0]
4328 myvim
= myvims
[datacenter_key
]
4329 myvim_thread
= myvim_threads
[datacenter_key
]
4332 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
4334 extra
= {"params": (net
['vim_net_id'], net
['sdn_net_id'])}
4335 if net2vm_dependencies
.get(net
["uuid"]):
4336 extra
["depends_on"] = net2vm_dependencies
[net
["uuid"]]
4337 sfi_dependencies
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfis"]
4338 if len(sfi_dependencies
) > 0:
4339 if "depends_on" in extra
:
4340 extra
["depends_on"] += sfi_dependencies
4342 extra
["depends_on"] = sfi_dependencies
4344 "instance_action_id": instance_action_id
,
4345 "task_index": task_index
,
4346 "datacenter_vim_id": net
["datacenter_tenant_id"],
4348 "status": "SCHEDULED",
4349 "item": "instance_nets",
4350 "item_id": net
["uuid"],
4351 "related": net
["related"],
4352 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4355 db_vim_actions
.append(db_vim_action
)
4357 db_instance_action
["number_tasks"] = task_index
4360 wim_actions
, db_instance_action
= (
4361 wim_engine
.incorporate_actions(wim_actions
, db_instance_action
))
4365 {"instance_actions": db_instance_action
},
4366 {"vim_wim_actions": db_vim_actions
+ wim_actions
}
4369 logger
.debug("delete_instance done DB tables: %s",
4370 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
4371 mydb
.new_rows(db_tables
, ())
4372 for myvim_thread_id
in vimthread_affected
.keys():
4373 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
4375 wim_engine
.dispatch(wim_actions
)
4377 if len(error_msg
) > 0:
4378 return 'action_id={} instance {} deleted but some elements could not be deleted, or already deleted '\
4379 '(error: 404) from VIM: {}'.format(instance_action_id
, message
, error_msg
)
4381 return "action_id={} instance {} deleted".format(instance_action_id
, message
)
4383 def get_instance_id(mydb
, tenant_id
, instance_id
):
4385 #check valid tenant_id
4386 check_tenant(mydb
, tenant_id
)
4389 instance_dict
= mydb
.get_instance_scenario(instance_id
, tenant_id
, verbose
=True)
4390 for net
in instance_dict
["nets"]:
4391 if net
.get("sdn_net_id"):
4392 net_sdn
= ovim
.show_network(net
["sdn_net_id"])
4394 "admin_state_up": net_sdn
.get("admin_state_up"),
4395 "flows": net_sdn
.get("flows"),
4396 "last_error": net_sdn
.get("last_error"),
4397 "ports": net_sdn
.get("ports"),
4398 "type": net_sdn
.get("type"),
4399 "status": net_sdn
.get("status"),
4400 "vlan": net_sdn
.get("vlan"),
4402 return instance_dict
4404 @deprecated("Instance is automatically refreshed by vim_threads")
4405 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
4406 '''Refreshes a scenario instance. It modifies instanceDict'''
4408 - 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
4411 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
4412 # #print "nfvo.refresh_instance begins"
4413 # #print json.dumps(instanceDict, indent=4)
4415 # #print "Getting the VIM URL and the VIM tenant_id"
4418 # # 1. Getting VIM vm and net list
4419 # vms_updated = [] #List of VM instance uuids in openmano that were updated
4422 # for sce_vnf in instanceDict['vnfs']:
4423 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
4424 # if datacenter_key not in vm_list:
4425 # vm_list[datacenter_key] = []
4426 # if datacenter_key not in myvims:
4427 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
4428 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
4429 # if len(vims) == 0:
4430 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
4431 # myvims[datacenter_key] = None
4433 # myvims[datacenter_key] = vims.values()[0]
4434 # for vm in sce_vnf['vms']:
4435 # vm_list[datacenter_key].append(vm['vim_vm_id'])
4436 # vms_notupdated.append(vm["uuid"])
4438 # nets_updated = [] #List of VM instance uuids in openmano that were updated
4439 # nets_notupdated=[]
4441 # for net in instanceDict['nets']:
4442 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
4443 # if datacenter_key not in net_list:
4444 # net_list[datacenter_key] = []
4445 # if datacenter_key not in myvims:
4446 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
4447 # datacenter_tenant_id=net["datacenter_tenant_id"])
4448 # if len(vims) == 0:
4449 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
4450 # myvims[datacenter_key] = None
4452 # myvims[datacenter_key] = vims.values()[0]
4454 # net_list[datacenter_key].append(net['vim_net_id'])
4455 # nets_notupdated.append(net["uuid"])
4457 # # 1. Getting the status of all VMs
4459 # for datacenter_key in myvims:
4460 # if not vm_list.get(datacenter_key):
4464 # if not myvims[datacenter_key]:
4465 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
4468 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
4470 # except vimconn.vimconnException as e:
4471 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
4472 # failed_message = str(e)
4474 # for vm in vm_list[datacenter_key]:
4475 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
4477 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
4478 # for sce_vnf in instanceDict['vnfs']:
4479 # for vm in sce_vnf['vms']:
4480 # vm_id = vm['vim_vm_id']
4481 # interfaces = vm_dict[vm_id].pop('interfaces', [])
4482 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
4483 # has_mgmt_iface = False
4484 # for iface in vm["interfaces"]:
4485 # if iface["type"]=="mgmt":
4486 # has_mgmt_iface = True
4487 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
4488 # vm_dict[vm_id]['status'] = "ACTIVE"
4489 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
4490 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
4491 # 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'):
4492 # vm['status'] = vm_dict[vm_id]['status']
4493 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
4494 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
4495 # # 2.1. Update in openmano DB the VMs whose status changed
4497 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
4498 # vms_notupdated.remove(vm["uuid"])
4500 # vms_updated.append(vm["uuid"])
4501 # except db_base_Exception as e:
4502 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
4503 # # 2.2. Update in openmano DB the interface VMs
4504 # for interface in interfaces:
4505 # #translate from vim_net_id to instance_net_id
4506 # network_id_list=[]
4507 # for net in instanceDict['nets']:
4508 # if net["vim_net_id"] == interface["vim_net_id"]:
4509 # network_id_list.append(net["uuid"])
4510 # if not network_id_list:
4512 # del interface["vim_net_id"]
4514 # for network_id in network_id_list:
4515 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
4516 # except db_base_Exception as e:
4517 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
4519 # # 3. Getting the status of all nets
4521 # for datacenter_key in myvims:
4522 # if not net_list.get(datacenter_key):
4525 # failed_message = ""
4526 # if not myvims[datacenter_key]:
4527 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
4530 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
4532 # except vimconn.vimconnException as e:
4533 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
4534 # failed_message = str(e)
4536 # for net in net_list[datacenter_key]:
4537 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
4539 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
4540 # # TODO: update nets inside a vnf
4541 # for net in instanceDict['nets']:
4542 # net_id = net['vim_net_id']
4543 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
4544 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
4545 # 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'):
4546 # net['status'] = net_dict[net_id]['status']
4547 # net['error_msg'] = net_dict[net_id].get('error_msg')
4548 # net['vim_info'] = net_dict[net_id].get('vim_info')
4549 # # 5.1. Update in openmano DB the nets whose status changed
4551 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
4552 # nets_notupdated.remove(net["uuid"])
4554 # nets_updated.append(net["uuid"])
4555 # except db_base_Exception as e:
4556 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
4558 # # Returns appropriate output
4559 # #print "nfvo.refresh_instance finishes"
4560 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
4561 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
4562 instance_id
= instanceDict
['uuid']
4563 # if len(vms_notupdated)+len(nets_notupdated)>0:
4564 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
4565 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
4567 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
4569 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
4570 #print "Checking that the instance_id exists and getting the instance dictionary"
4571 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
4572 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
4574 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
4575 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
4577 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), httperrors
.Not_Found
)
4578 myvim
= vims
.values()[0]
4583 myvim_threads_id
= {}
4584 if action_dict
.get("vdu-scaling"):
4585 db_instance_vms
= []
4587 db_instance_interfaces
= []
4588 instance_action_id
= get_task_id()
4589 db_instance_action
= {
4590 "uuid": instance_action_id
, # same uuid for the instance and the action on create
4591 "tenant_id": nfvo_tenant
,
4592 "instance_id": instance_id
,
4593 "description": "SCALE",
4595 vm_result
["instance_action_id"] = instance_action_id
4596 vm_result
["created"] = []
4597 vm_result
["deleted"] = []
4599 for vdu
in action_dict
["vdu-scaling"]:
4600 vdu_id
= vdu
.get("vdu-id")
4601 osm_vdu_id
= vdu
.get("osm_vdu_id")
4602 member_vnf_index
= vdu
.get("member-vnf-index")
4603 vdu_count
= vdu
.get("count", 1)
4605 target_vms
= mydb
.get_rows(
4606 FROM
="instance_vms as vms join instance_vnfs as vnfs on vms.instance_vnf_id=vnfs.uuid",
4607 WHERE
={"vms.uuid": vdu_id
},
4608 ORDER_BY
="vms.created_at"
4611 raise NfvoException("Cannot find the vdu with id {}".format(vdu_id
), httperrors
.Not_Found
)
4613 if not osm_vdu_id
and not member_vnf_index
:
4614 raise NfvoException("Invalid input vdu parameters. Must supply either 'vdu-id' of 'osm_vdu_id','member-vnf-index'")
4615 target_vms
= mydb
.get_rows(
4616 # SELECT=("ivms.uuid", "ivnfs.datacenter_id", "ivnfs.datacenter_tenant_id"),
4617 FROM
="instance_vms as ivms join instance_vnfs as ivnfs on ivms.instance_vnf_id=ivnfs.uuid"\
4618 " join sce_vnfs as svnfs on ivnfs.sce_vnf_id=svnfs.uuid"\
4619 " join vms on ivms.vm_id=vms.uuid",
4620 WHERE
={"vms.osm_id": osm_vdu_id
, "svnfs.member_vnf_index": member_vnf_index
,
4621 "ivnfs.instance_scenario_id": instance_id
},
4622 ORDER_BY
="ivms.created_at"
4625 raise NfvoException("Cannot find the vdu with osm_vdu_id {} and member-vnf-index {}".format(osm_vdu_id
, member_vnf_index
), httperrors
.Not_Found
)
4626 vdu_id
= target_vms
[-1]["uuid"]
4627 target_vm
= target_vms
[-1]
4628 datacenter
= target_vm
["datacenter_id"]
4629 myvim_threads_id
[datacenter
], _
= get_vim_thread(mydb
, nfvo_tenant
, datacenter
)
4631 if vdu
["type"] == "delete":
4632 for index
in range(0, vdu_count
):
4633 target_vm
= target_vms
[-1-index
]
4634 vdu_id
= target_vm
["uuid"]
4636 vm_interfaces
= None
4637 for sce_vnf
in instanceDict
['vnfs']:
4638 for vm
in sce_vnf
['vms']:
4639 if vm
["uuid"] == vdu_id
:
4640 # TODO revise this should not be vm["uuid"] instance_vms["vm_id"]
4641 vm_interfaces
= vm
["interfaces"]
4645 "instance_action_id": instance_action_id
,
4646 "task_index": task_index
,
4647 "datacenter_vim_id": target_vm
["datacenter_tenant_id"],
4649 "status": "SCHEDULED",
4650 "item": "instance_vms",
4652 "related": target_vm
["related"],
4653 "extra": yaml
.safe_dump({"params": vm_interfaces
},
4654 default_flow_style
=True, width
=256)
4657 db_vim_actions
.append(db_vim_action
)
4658 vm_result
["deleted"].append(vdu_id
)
4659 # delete from database
4660 db_instance_vms
.append({"TO-DELETE": vdu_id
})
4662 else: # vdu["type"] == "create":
4664 where
= {"item": "instance_vms", "item_id": target_vm
["uuid"], "action": "CREATE"}
4666 vim_action_to_clone
= mydb
.get_rows(FROM
="vim_wim_actions", WHERE
=where
)
4667 if not vim_action_to_clone
:
4668 raise NfvoException("Cannot find the vim_action at database with {}".format(where
), httperrors
.Internal_Server_Error
)
4669 vim_action_to_clone
= vim_action_to_clone
[0]
4670 extra
= yaml
.safe_load(vim_action_to_clone
["extra"])
4672 # generate a new depends_on. Convert format TASK-Y into new format TASK-ACTION-XXXX.XXXX.Y
4673 # TODO do the same for flavor and image when available
4674 task_depends_on
= []
4675 task_params
= extra
["params"]
4676 task_params_networks
= deepcopy(task_params
[5])
4677 for iface
in task_params
[5]:
4678 if iface
["net_id"].startswith("TASK-"):
4679 if "." not in iface
["net_id"]:
4680 task_depends_on
.append("{}.{}".format(vim_action_to_clone
["instance_action_id"],
4681 iface
["net_id"][5:]))
4682 iface
["net_id"] = "TASK-{}.{}".format(vim_action_to_clone
["instance_action_id"],
4683 iface
["net_id"][5:])
4685 task_depends_on
.append(iface
["net_id"][5:])
4686 if "mac_address" in iface
:
4687 del iface
["mac_address"]
4689 vm_ifaces_to_clone
= mydb
.get_rows(FROM
="instance_interfaces", WHERE
={"instance_vm_id": target_vm
["uuid"]})
4690 for index
in range(0, vdu_count
):
4691 vm_uuid
= str(uuid4())
4692 vm_name
= target_vm
.get('vim_name')
4694 suffix
= vm_name
.rfind("-")
4695 vm_name
= vm_name
[:suffix
+1] + str(index
+ 1 + int(vm_name
[suffix
+1:]))
4701 'instance_vnf_id': target_vm
['instance_vnf_id'],
4702 'vm_id': target_vm
['vm_id'],
4703 'vim_name': vm_name
,
4705 db_instance_vms
.append(db_instance_vm
)
4707 for vm_iface
in vm_ifaces_to_clone
:
4708 iface_uuid
= str(uuid4())
4709 iface2iface
[vm_iface
["uuid"]] = iface_uuid
4712 'instance_vm_id': vm_uuid
,
4713 "instance_net_id": vm_iface
["instance_net_id"],
4714 'interface_id': vm_iface
['interface_id'],
4715 'type': vm_iface
['type'],
4716 'floating_ip': vm_iface
['floating_ip'],
4717 'port_security': vm_iface
['port_security']
4719 db_instance_interfaces
.append(db_vm_iface
)
4720 task_params_copy
= deepcopy(task_params
)
4721 for iface
in task_params_copy
[5]:
4722 iface
["uuid"] = iface2iface
[iface
["uuid"]]
4723 # increment ip_address
4724 if "ip_address" in iface
:
4725 ip
= iface
.get("ip_address")
4730 ip
= ip
[i
:] + str(int(ip
[:i
]) + 1)
4731 iface
["ip_address"] = ip
4733 iface
["ip_address"] = None
4735 task_params_copy
[0] = vm_name
4737 "instance_action_id": instance_action_id
,
4738 "task_index": task_index
,
4739 "datacenter_vim_id": vim_action_to_clone
["datacenter_vim_id"],
4741 "status": "SCHEDULED",
4742 "item": "instance_vms",
4747 # TODO examinar parametros, quitar MAC o incrementar. Incrementar IP y colocar las dependencias con ACTION-asdfasd.
4750 "extra": yaml
.safe_dump({"params": task_params_copy
, "depends_on": task_depends_on
}, default_flow_style
=True, width
=256)
4753 db_vim_actions
.append(db_vim_action
)
4754 vm_result
["created"].append(vm_uuid
)
4756 db_instance_action
["number_tasks"] = task_index
4758 {"instance_vms": db_instance_vms
},
4759 {"instance_interfaces": db_instance_interfaces
},
4760 {"instance_actions": db_instance_action
},
4762 # {"instance_sfis": db_instance_sfis},
4763 # {"instance_sfs": db_instance_sfs},
4764 # {"instance_classifications": db_instance_classifications},
4765 # {"instance_sfps": db_instance_sfps},
4766 {"vim_wim_actions": db_vim_actions
}
4768 logger
.debug("create_vdu done DB tables: %s",
4769 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
4770 mydb
.new_rows(db_tables
, [])
4771 for myvim_thread
in myvim_threads_id
.values():
4772 vim_threads
["running"][myvim_thread
].insert_task(db_vim_actions
)
4776 input_vnfs
= action_dict
.pop("vnfs", [])
4777 input_vms
= action_dict
.pop("vms", [])
4778 action_over_all
= True if not input_vnfs
and not input_vms
else False
4779 for sce_vnf
in instanceDict
['vnfs']:
4780 for vm
in sce_vnf
['vms']:
4781 if not action_over_all
and sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
4782 sce_vnf
['member_vnf_index'] not in input_vnfs
and \
4783 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
and \
4784 sce_vnf
['member_vnf_index'] + "-" + vm
['vdu_osm_id'] not in input_vms
: # TODO conside vm_count_index
4787 if "add_public_key" in action_dict
:
4788 if sce_vnf
.get('mgmt_access'):
4789 mgmt_access
= yaml
.load(sce_vnf
['mgmt_access'])
4790 if not input_vms
and mgmt_access
.get("vdu-id") != vm
['vdu_osm_id']:
4792 default_user
= mgmt_access
.get("default-user")
4793 password
= mgmt_access
.get("password")
4794 if mgmt_access
.get(vm
['vdu_osm_id']):
4795 default_user
= mgmt_access
[vm
['vdu_osm_id']].get("default-user", default_user
)
4796 password
= mgmt_access
[vm
['vdu_osm_id']].get("password", password
)
4798 tenant
= mydb
.get_rows_by_id('nfvo_tenants', nfvo_tenant
)
4800 if 'ip_address' in vm
:
4801 mgmt_ip
= vm
['ip_address'].split(';')
4802 priv_RO_key
= decrypt_key(tenant
[0]['encrypted_RO_priv_key'], tenant
[0]['uuid'])
4803 data
= myvim
.inject_user_key(mgmt_ip
[0], action_dict
.get('user', default_user
),
4804 action_dict
['add_public_key'],
4805 password
=password
, ro_key
=priv_RO_key
)
4806 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4807 "description": "Public key injected",
4812 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4813 httperrors
.Internal_Server_Error
)
4815 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4816 httperrors
.Internal_Server_Error
)
4818 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
4819 if "console" in action_dict
:
4820 if not global_config
["http_console_proxy"]:
4821 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4822 "description": "{protocol}//{ip}:{port}/{suffix}".format(
4823 protocol
=data
["protocol"],
4824 ip
= data
["server"],
4825 port
= data
["port"],
4826 suffix
= data
["suffix"]),
4830 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
4831 vm_result
[ vm
['uuid'] ] = {"vim_result": -httperrors
.Unauthorized
,
4832 "description": "this console is only reachable by local interface",
4837 #print "console data", data
4839 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
4840 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4841 "description": "{protocol}//{ip}:{port}/{suffix}".format(
4842 protocol
=data
["protocol"],
4843 ip
= global_config
["http_console_host"],
4844 port
= console_thread
.port
,
4845 suffix
= data
["suffix"]),
4849 except NfvoException
as e
:
4850 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
4854 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
4856 except vimconn
.vimconnException
as e
:
4857 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
4860 if vm_ok
==0: #all goes wrong
4865 def instance_action_get(mydb
, nfvo_tenant
, instance_id
, action_id
):
4867 if nfvo_tenant
and nfvo_tenant
!= "any":
4868 filter["tenant_id"] = nfvo_tenant
4869 if instance_id
and instance_id
!= "any":
4870 filter["instance_id"] = instance_id
4872 filter["uuid"] = action_id
4873 rows
= mydb
.get_rows(FROM
="instance_actions", WHERE
=filter)
4876 raise NfvoException("Not found any action with this criteria", httperrors
.Not_Found
)
4877 vim_wim_actions
= mydb
.get_rows(FROM
="vim_wim_actions", WHERE
={"instance_action_id": action_id
})
4878 rows
[0]["vim_wim_actions"] = vim_wim_actions
4879 # for backward compatibility set vim_actions = vim_wim_actions
4880 rows
[0]["vim_actions"] = vim_wim_actions
4881 return {"actions": rows
}
4884 def create_or_use_console_proxy_thread(console_server
, console_port
):
4885 #look for a non-used port
4886 console_thread_key
= console_server
+ ":" + str(console_port
)
4887 if console_thread_key
in global_config
["console_thread"]:
4888 #global_config["console_thread"][console_thread_key].start_timeout()
4889 return global_config
["console_thread"][console_thread_key
]
4891 for port
in global_config
["console_port_iterator"]():
4892 #print "create_or_use_console_proxy_thread() port:", port
4893 if port
in global_config
["console_ports"]:
4896 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
4898 global_config
["console_thread"][console_thread_key
] = clithread
4899 global_config
["console_ports"][port
] = console_thread_key
4901 except cli
.ConsoleProxyExceptionPortUsed
as e
:
4902 #port used, try with onoher
4904 except cli
.ConsoleProxyException
as e
:
4905 raise NfvoException(str(e
), httperrors
.Bad_Request
)
4906 raise NfvoException("Not found any free 'http_console_ports'", httperrors
.Conflict
)
4909 def check_tenant(mydb
, tenant_id
):
4910 '''check that tenant exists at database'''
4911 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
4913 raise NfvoException("tenant '{}' not found".format(tenant_id
), httperrors
.Not_Found
)
4916 def new_tenant(mydb
, tenant_dict
):
4918 tenant_uuid
= str(uuid4())
4919 tenant_dict
['uuid'] = tenant_uuid
4921 pub_key
, priv_key
= create_RO_keypair(tenant_uuid
)
4922 tenant_dict
['RO_pub_key'] = pub_key
4923 tenant_dict
['encrypted_RO_priv_key'] = priv_key
4924 mydb
.new_row("nfvo_tenants", tenant_dict
, confidential_data
=True)
4925 except db_base_Exception
as e
:
4926 raise NfvoException("Error creating the new tenant: {} ".format(tenant_dict
['name']) + str(e
), e
.http_code
)
4929 def delete_tenant(mydb
, tenant
):
4930 #get nfvo_tenant info
4932 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
4933 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
4934 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
4937 def new_datacenter(mydb
, datacenter_descriptor
):
4938 sdn_port_mapping
= None
4939 if "config" in datacenter_descriptor
:
4940 sdn_port_mapping
= datacenter_descriptor
["config"].pop("sdn-port-mapping", None)
4941 datacenter_descriptor
["config"] = yaml
.safe_dump(datacenter_descriptor
["config"], default_flow_style
=True,
4943 # Check that datacenter-type is correct
4944 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
4945 # module_info = None
4947 module
= "vimconn_" + datacenter_type
4948 pkg
= __import__("osm_ro." + module
)
4949 # vim_conn = getattr(pkg, module)
4950 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
4951 except (IOError, ImportError):
4952 # if module_info and module_info[0]:
4953 # file.close(module_info[0])
4954 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}.py' not installed".format(datacenter_type
,
4956 httperrors
.Bad_Request
)
4958 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True, confidential_data
=True)
4959 if sdn_port_mapping
:
4961 datacenter_sdn_port_mapping_set(mydb
, None, datacenter_id
, sdn_port_mapping
)
4962 except Exception as e
:
4963 mydb
.delete_row_by_id("datacenters", datacenter_id
) # Rollback
4965 return datacenter_id
4968 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
4969 # obtain data, check that only one exist
4970 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
4973 datacenter_id
= datacenter
['uuid']
4974 where
= {'uuid': datacenter
['uuid']}
4975 remove_port_mapping
= False
4976 new_sdn_port_mapping
= None
4977 if "config" in datacenter_descriptor
:
4978 if datacenter_descriptor
['config'] != None:
4980 new_config_dict
= datacenter_descriptor
["config"]
4981 if "sdn-port-mapping" in new_config_dict
:
4982 remove_port_mapping
= True
4983 new_sdn_port_mapping
= new_config_dict
.pop("sdn-port-mapping")
4984 # delete null fields
4986 for k
in new_config_dict
:
4987 if new_config_dict
[k
] is None:
4989 if k
== 'sdn-controller':
4990 remove_port_mapping
= True
4992 config_text
= datacenter
.get("config")
4995 config_dict
= yaml
.load(config_text
)
4996 config_dict
.update(new_config_dict
)
4997 # delete null fields
5000 except Exception as e
:
5001 raise NfvoException("Bad format at datacenter:config " + str(e
), httperrors
.Bad_Request
)
5003 datacenter_descriptor
["config"] = yaml
.safe_dump(config_dict
, default_flow_style
=True, width
=256)
5005 datacenter_descriptor
["config"] = None
5006 if remove_port_mapping
:
5008 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_id
)
5009 except ovimException
as e
:
5010 raise NfvoException("Error deleting datacenter-port-mapping " + str(e
), httperrors
.Conflict
)
5012 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
5013 if new_sdn_port_mapping
:
5015 datacenter_sdn_port_mapping_set(mydb
, None, datacenter_id
, new_sdn_port_mapping
)
5016 except ovimException
as e
:
5018 mydb
.update_rows('datacenters', datacenter
, where
)
5019 raise NfvoException("Error adding datacenter-port-mapping " + str(e
), httperrors
.Conflict
)
5020 return datacenter_id
5023 def delete_datacenter(mydb
, datacenter
):
5024 #get nfvo_tenant info
5025 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
5026 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
5028 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_dict
['uuid'])
5029 except ovimException
as e
:
5030 raise NfvoException("Error deleting datacenter-port-mapping " + str(e
))
5031 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
5034 def create_vim_account(mydb
, nfvo_tenant
, datacenter_id
, name
=None, vim_id
=None, vim_tenant
=None, vim_tenant_name
=None,
5035 vim_username
=None, vim_password
=None, config
=None):
5036 # get datacenter info
5038 if not datacenter_id
:
5040 raise NfvoException("You must provide 'vim_id", http_code
=httperrors
.Bad_Request
)
5041 datacenter_id
= vim_id
5042 datacenter_id
, datacenter_name
= get_datacenter_uuid(mydb
, None, datacenter_id
)
5044 create_vim_tenant
= True if not vim_tenant
and not vim_tenant_name
else False
5046 # get nfvo_tenant info
5047 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
5048 if vim_tenant_name
==None:
5049 vim_tenant_name
=tenant_dict
['name']
5051 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
5052 # #check that this association does not exist before
5053 # tenants_datacenters = mydb.get_rows(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict)
5054 # if len(tenants_datacenters)>0:
5055 # raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id, tenant_dict['uuid']), httperrors.Conflict)
5057 vim_tenant_id_exist_atdb
=False
5058 if not create_vim_tenant
:
5059 where_
={"datacenter_id": datacenter_id
}
5060 if vim_tenant
!=None:
5061 where_
["vim_tenant_id"] = vim_tenant
5062 if vim_tenant_name
!=None:
5063 where_
["vim_tenant_name"] = vim_tenant_name
5064 #check if vim_tenant_id is already at database
5065 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
5066 if len(datacenter_tenants_dict
)>=1:
5067 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
5068 vim_tenant_id_exist_atdb
=True
5069 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
5071 datacenter_tenants_dict
= {}
5072 #insert at table datacenter_tenants
5073 else: #if vim_tenant==None:
5074 #create tenant at VIM if not provided
5076 _
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
, vim_user
=vim_username
,
5077 vim_passwd
=vim_password
)
5078 datacenter_name
= myvim
["name"]
5079 vim_tenant
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
5080 except vimconn
.vimconnException
as e
:
5081 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), httperrors
.Internal_Server_Error
)
5082 datacenter_tenants_dict
= {}
5083 datacenter_tenants_dict
["created"]="true"
5085 #fill datacenter_tenants table
5086 if not vim_tenant_id_exist_atdb
:
5087 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant
5088 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
5089 datacenter_tenants_dict
["user"] = vim_username
5090 datacenter_tenants_dict
["passwd"] = vim_password
5091 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
5093 datacenter_tenants_dict
["name"] = name
5095 datacenter_tenants_dict
["name"] = datacenter_name
5097 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
5098 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True, confidential_data
=True)
5099 datacenter_tenants_dict
["uuid"] = id_
5101 #fill tenants_datacenters table
5102 datacenter_tenant_id
= datacenter_tenants_dict
["uuid"]
5103 tenants_datacenter_dict
["datacenter_tenant_id"] = datacenter_tenant_id
5104 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
5107 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
5108 new_thread
= vim_thread
.vim_thread(task_lock
, thread_name
, datacenter_name
, datacenter_tenant_id
,
5109 db
=db
, db_lock
=db_lock
, ovim
=ovim
)
5111 thread_id
= datacenter_tenants_dict
["uuid"]
5112 vim_threads
["running"][thread_id
] = new_thread
5114 except vimconn
.vimconnException
as e
:
5115 raise NfvoException(str(e
), httperrors
.Bad_Request
)
5118 def edit_vim_account(mydb
, nfvo_tenant
, datacenter_tenant_id
, datacenter_id
=None, name
=None, vim_tenant
=None,
5119 vim_tenant_name
=None, vim_username
=None, vim_password
=None, config
=None):
5121 # get vim_account; check is valid for this tenant
5122 from_
= "datacenter_tenants as dt JOIN tenants_datacenters as td ON dt.uuid=td.datacenter_tenant_id"
5123 where_
= {"td.nfvo_tenant_id": nfvo_tenant
}
5124 if datacenter_tenant_id
:
5125 where_
["dt.uuid"] = datacenter_tenant_id
5127 where_
["dt.datacenter_id"] = datacenter_id
5128 vim_accounts
= mydb
.get_rows(SELECT
="dt.uuid as uuid, config", FROM
=from_
, WHERE
=where_
)
5129 if not vim_accounts
:
5130 raise NfvoException("vim_account not found for this tenant", http_code
=httperrors
.Not_Found
)
5131 elif len(vim_accounts
) > 1:
5132 raise NfvoException("found more than one vim_account for this tenant", http_code
=httperrors
.Conflict
)
5133 datacenter_tenant_id
= vim_accounts
[0]["uuid"]
5134 original_config
= vim_accounts
[0]["config"]
5138 original_config_dict
= yaml
.load(original_config
)
5139 original_config_dict
.update(config
)
5140 update
["config"] = yaml
.safe_dump(original_config_dict
, default_flow_style
=True, width
=256)
5142 update_
['name'] = name
5144 update_
['vim_tenant_id'] = vim_tenant
5146 update_
['vim_tenant_name'] = vim_tenant_name
5148 update_
['user'] = vim_username
5150 update_
['passwd'] = vim_password
5152 mydb
.update_rows("datacenter_tenants", UPDATE
=update_
, WHERE
={"uuid": datacenter_tenant_id
})
5154 vim_threads
["running"][datacenter_tenant_id
].insert_task("reload")
5155 return datacenter_tenant_id
5157 def delete_vim_account(mydb
, tenant_id
, vim_account_id
, datacenter
=None):
5158 #get nfvo_tenant info
5159 if not tenant_id
or tenant_id
=="any":
5162 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
5163 tenant_uuid
= tenant_dict
['uuid']
5165 #check that this association exist before
5166 tenants_datacenter_dict
= {}
5168 datacenter_id
, _
= get_datacenter_uuid(mydb
, tenant_uuid
, datacenter
)
5169 tenants_datacenter_dict
["datacenter_id"] = datacenter_id
5170 elif vim_account_id
:
5171 tenants_datacenter_dict
["datacenter_tenant_id"] = vim_account_id
5173 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
5174 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
5175 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
5176 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), httperrors
.Not_Found
)
5178 #delete this association
5179 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
5181 #get vim_tenant info and deletes
5183 for tenant_datacenter_item
in tenant_datacenter_list
:
5184 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
5185 #try to delete vim:tenant
5187 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
5188 if vim_tenant_dict
['created']=='true':
5189 #delete tenant at VIM if created by NFVO
5191 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5192 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
5193 except vimconn
.vimconnException
as e
:
5194 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
5195 logger
.warn(warning
)
5196 except db_base_Exception
as e
:
5197 logger
.error("Cannot delete datacenter_tenants " + str(e
))
5198 pass # the error will be caused because dependencies, vim_tenant can not be deleted
5199 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
5200 thread
= vim_threads
["running"].get(thread_id
)
5202 thread
.insert_task("exit")
5203 vim_threads
["deleting"][thread_id
] = thread
5204 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
5207 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
5209 #get datacenter info
5210 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5212 if 'check-connectivity' in action_dict
:
5214 myvim
.check_vim_connectivity()
5215 except vimconn
.vimconnException
as e
:
5216 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
5217 raise NfvoException(str(e
), e
.http_code
)
5218 elif 'net-update' in action_dict
:
5220 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
5222 except vimconn
.vimconnException
as e
:
5223 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
5224 raise NfvoException(str(e
), httperrors
.Internal_Server_Error
)
5225 #update nets Change from VIM format to NFVO format
5228 net_nfvo
={'datacenter_id': datacenter_id
}
5229 net_nfvo
['name'] = net
['name']
5230 #net_nfvo['description']= net['name']
5231 net_nfvo
['vim_net_id'] = net
['id']
5232 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
5233 net_nfvo
['shared'] = net
['shared']
5234 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
5235 net_list
.append(net_nfvo
)
5236 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
5237 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
5239 elif 'net-edit' in action_dict
:
5240 net
= action_dict
['net-edit'].pop('net')
5241 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
5242 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
5243 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
5245 elif 'net-delete' in action_dict
:
5246 net
= action_dict
['net-deelte'].get('net')
5247 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
5248 result
= mydb
.delete_row(FROM
='datacenter_nets',
5249 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
5253 raise NfvoException("Unknown action " + str(action_dict
), httperrors
.Bad_Request
)
5256 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
5257 #get datacenter info
5258 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5260 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
5261 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
5262 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
5266 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
5267 #get datacenter info
5268 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5271 action_dict
= action_dict
["netmap"]
5272 if 'vim_id' in action_dict
:
5273 filter_dict
["id"] = action_dict
['vim_id']
5274 if 'vim_name' in action_dict
:
5275 filter_dict
["name"] = action_dict
['vim_name']
5277 filter_dict
["shared"] = True
5280 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
5281 except vimconn
.vimconnException
as e
:
5282 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
5283 raise NfvoException(str(e
), httperrors
.Internal_Server_Error
)
5284 if len(vim_nets
)>1 and action_dict
:
5285 raise NfvoException("more than two networks found, specify with vim_id", httperrors
.Conflict
)
5286 elif len(vim_nets
)==0: # and action_dict:
5287 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), httperrors
.Not_Found
)
5289 for net
in vim_nets
:
5290 net_nfvo
={'datacenter_id': datacenter_id
}
5291 if action_dict
and "name" in action_dict
:
5292 net_nfvo
['name'] = action_dict
['name']
5294 net_nfvo
['name'] = net
['name']
5295 #net_nfvo['description']= net['name']
5296 net_nfvo
['vim_net_id'] = net
['id']
5297 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
5298 net_nfvo
['shared'] = net
['shared']
5299 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
5301 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
5302 net_nfvo
["status"] = "OK"
5303 net_nfvo
["uuid"] = net_id
5304 except db_base_Exception
as e
:
5308 net_nfvo
["status"] = "FAIL: " + str(e
)
5309 net_list
.append(net_nfvo
)
5312 def get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
):
5313 # obtain all network data
5315 if utils
.check_valid_uuid(network_id
):
5316 filter_dict
= {"id": network_id
}
5318 filter_dict
= {"name": network_id
}
5320 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5321 network
= myvim
.get_network_list(filter_dict
=filter_dict
)
5322 except vimconn
.vimconnException
as e
:
5323 raise NfvoException("Not possible to get_sdn_net_id from VIM: {}".format(str(e
)), e
.http_code
)
5325 # ensure the network is defined
5326 if len(network
) == 0:
5327 raise NfvoException("Network {} is not present in the system".format(network_id
),
5328 httperrors
.Bad_Request
)
5330 # ensure there is only one network with the provided name
5331 if len(network
) > 1:
5332 raise NfvoException("Multiple networks present in vim identified by {}".format(network_id
), httperrors
.Bad_Request
)
5334 # ensure it is a dataplane network
5335 if network
[0]['type'] != 'data':
5338 # ensure we use the id
5339 network_id
= network
[0]['id']
5341 # search in dabase mano_db in table instance nets for the sdn_net_id that corresponds to the vim_net_id==network_id
5342 # and with instance_scenario_id==NULL
5343 #search_dict = {'vim_net_id': network_id, 'instance_scenario_id': None}
5344 search_dict
= {'vim_net_id': network_id
}
5347 #sdn_network_id = mydb.get_rows(SELECT=('sdn_net_id',), FROM='instance_nets', WHERE=search_dict)[0]['sdn_net_id']
5348 result
= mydb
.get_rows(SELECT
=('sdn_net_id',), FROM
='instance_nets', WHERE
=search_dict
)
5349 except db_base_Exception
as e
:
5350 raise NfvoException("db_base_Exception obtaining SDN network to associated to vim network {}".format(
5351 network_id
) + str(e
), e
.http_code
)
5355 if net
['sdn_net_id'] != None:
5357 sdn_net_id
= net
['sdn_net_id']
5359 if sdn_net_counter
== 0:
5361 elif sdn_net_counter
== 1:
5364 raise NfvoException("More than one SDN network is associated to vim network {}".format(
5365 network_id
), httperrors
.Internal_Server_Error
)
5367 def get_sdn_controller_id(mydb
, datacenter
):
5368 # Obtain sdn controller id
5369 config
= mydb
.get_rows(SELECT
=('config',), FROM
='datacenters', WHERE
={'uuid': datacenter
})[0].get('config', '{}')
5373 return yaml
.load(config
).get('sdn-controller')
5375 def vim_net_sdn_attach(mydb
, tenant_id
, datacenter
, network_id
, descriptor
):
5377 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
5378 if not sdn_network_id
:
5379 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
), httperrors
.Internal_Server_Error
)
5381 #Obtain sdn controller id
5382 controller_id
= get_sdn_controller_id(mydb
, datacenter
)
5383 if not controller_id
:
5384 raise NfvoException("No SDN controller is set for datacenter {}".format(datacenter
), httperrors
.Internal_Server_Error
)
5386 #Obtain sdn controller info
5387 sdn_controller
= ovim
.show_of_controller(controller_id
)
5390 'name': 'external_port',
5391 'net_id': sdn_network_id
,
5392 'ofc_id': controller_id
,
5393 'switch_dpid': sdn_controller
['dpid'],
5394 'switch_port': descriptor
['port']
5397 if 'vlan' in descriptor
:
5398 port_data
['vlan'] = descriptor
['vlan']
5399 if 'mac' in descriptor
:
5400 port_data
['mac'] = descriptor
['mac']
5402 result
= ovim
.new_port(port_data
)
5403 except ovimException
as e
:
5404 raise NfvoException("ovimException attaching SDN network {} to vim network {}".format(
5405 sdn_network_id
, network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5406 except db_base_Exception
as e
:
5407 raise NfvoException("db_base_Exception attaching SDN network to vim network {}".format(
5408 network_id
) + str(e
), e
.http_code
)
5410 return 'Port uuid: '+ result
5412 def vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, network_id
, port_id
=None):
5414 filter = {'uuid': port_id
}
5416 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
5417 if not sdn_network_id
:
5418 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
),
5419 httperrors
.Internal_Server_Error
)
5420 #in case no port_id is specified only ports marked as 'external_port' will be detached
5421 filter = {'name': 'external_port', 'net_id': sdn_network_id
}
5424 port_list
= ovim
.get_ports(columns
={'uuid'}, filter=filter)
5425 except ovimException
as e
:
5426 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
5427 httperrors
.Internal_Server_Error
)
5429 if len(port_list
) == 0:
5430 raise NfvoException("No ports attached to the network {} were found with the requested criteria".format(network_id
),
5431 httperrors
.Bad_Request
)
5434 for port
in port_list
:
5436 port_uuid_list
.append(port
['uuid'])
5437 ovim
.delete_port(port
['uuid'])
5438 except ovimException
as e
:
5439 raise NfvoException("ovimException deleting port {} for net {}. ".format(port
['uuid'], network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5441 return 'Detached ports uuid: {}'.format(','.join(port_uuid_list
))
5443 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
5444 #get datacenter info
5445 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5448 if utils
.check_valid_uuid(name
):
5449 filter_dict
["id"] = name
5451 filter_dict
["name"] = name
5453 if item
=="networks":
5454 #filter_dict['tenant_id'] = myvim['tenant_id']
5455 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
5457 if len(content
) == 0:
5458 raise NfvoException("Network {} is not present in the system. ".format(name
),
5459 httperrors
.Bad_Request
)
5461 #Update the networks with the attached ports
5463 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, net
['id'])
5464 if sdn_network_id
!= None:
5466 #port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan'}, filter={'name': 'external_port', 'net_id': sdn_network_id})
5467 port_list
= ovim
.get_ports(columns
={'uuid', 'switch_port', 'vlan','name'}, filter={'net_id': sdn_network_id
})
5468 except ovimException
as e
:
5469 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5470 #Remove field name and if port name is external_port save it as 'type'
5471 for port
in port_list
:
5472 if port
['name'] == 'external_port':
5473 port
['type'] = "External"
5475 net
['sdn_network_id'] = sdn_network_id
5476 net
['sdn_attached_ports'] = port_list
5478 elif item
=="tenants":
5479 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
5480 elif item
== "images":
5482 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
5484 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5485 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
5486 if name
and len(content
)==1:
5487 return {item
[:-1]: content
[0]}
5488 elif name
and len(content
)==0:
5489 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
5492 return {item
: content
}
5493 except vimconn
.vimconnException
as e
:
5494 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
5495 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
5498 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
5499 #get datacenter info
5500 if tenant_id
== "any":
5503 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5505 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
5506 logger
.debug("vim_action_delete vim response: " + str(content
))
5507 items
= content
.values()[0]
5508 if type(items
)==list and len(items
)==0:
5509 raise NfvoException("Not found " + item
, httperrors
.Not_Found
)
5510 elif type(items
)==list and len(items
)>1:
5511 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), httperrors
.Not_Found
)
5512 else: # it is a dict
5513 item_id
= items
["id"]
5514 item_name
= str(items
.get("name"))
5517 if item
=="networks":
5518 # If there is a SDN network associated to the vim-network, proceed to clear the relationship and delete it
5519 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, item_id
)
5520 if sdn_network_id
!= None:
5521 #Delete any port attachment to this network
5523 port_list
= ovim
.get_ports(columns
={'uuid'}, filter={'net_id': sdn_network_id
})
5524 except ovimException
as e
:
5525 raise NfvoException(
5526 "ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
5527 httperrors
.Internal_Server_Error
)
5529 # By calling one by one all ports to be detached we ensure that not only the external_ports get detached
5530 for port
in port_list
:
5531 vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, item_id
, port
['uuid'])
5533 #Delete from 'instance_nets' the correspondence between the vim-net-id and the sdn-net-id
5535 mydb
.delete_row(FROM
='instance_nets', WHERE
={'instance_scenario_id': None, 'sdn_net_id': sdn_network_id
, 'vim_net_id': item_id
})
5536 except db_base_Exception
as e
:
5537 raise NfvoException("Error deleting correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
5538 str(e
), e
.http_code
)
5540 #Delete the SDN network
5542 ovim
.delete_network(sdn_network_id
)
5543 except ovimException
as e
:
5544 logger
.error("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
), exc_info
=True)
5545 raise NfvoException("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
),
5546 httperrors
.Internal_Server_Error
)
5548 content
= myvim
.delete_network(item_id
)
5549 elif item
=="tenants":
5550 content
= myvim
.delete_tenant(item_id
)
5551 elif item
== "images":
5552 content
= myvim
.delete_image(item_id
)
5554 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5555 except vimconn
.vimconnException
as e
:
5556 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
5557 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
5559 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
5562 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
5563 #get datacenter info
5564 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
5565 if tenant_id
== "any":
5567 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5569 if item
=="networks":
5570 net
= descriptor
["network"]
5571 net_name
= net
.pop("name")
5572 net_type
= net
.pop("type", "bridge")
5573 net_public
= net
.pop("shared", False)
5574 net_ipprofile
= net
.pop("ip_profile", None)
5575 net_vlan
= net
.pop("vlan", None)
5576 content
, _
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
5578 #If the datacenter has a SDN controller defined and the network is of dataplane type, then create the sdn network
5579 if get_sdn_controller_id(mydb
, datacenter
) != None and (net_type
== 'data' or net_type
== 'ptp'):
5580 #obtain datacenter_tenant_id
5581 datacenter_tenant_id
= mydb
.get_rows(SELECT
=('uuid',),
5582 FROM
='datacenter_tenants',
5583 WHERE
={'datacenter_id': datacenter
})[0]['uuid']
5586 sdn_network
['vlan'] = net_vlan
5587 sdn_network
['type'] = net_type
5588 sdn_network
['name'] = net_name
5589 sdn_network
['region'] = datacenter_tenant_id
5590 ovim_content
= ovim
.new_network(sdn_network
)
5591 except ovimException
as e
:
5592 logger
.error("ovimException creating SDN network={} ".format(
5593 sdn_network
) + str(e
), exc_info
=True)
5594 raise NfvoException("ovimException creating SDN network={} ".format(sdn_network
) + str(e
),
5595 httperrors
.Internal_Server_Error
)
5597 # Save entry in in dabase mano_db in table instance_nets to stablish a dictionary vim_net_id <->sdn_net_id
5598 # use instance_scenario_id=None to distinguish from real instaces of nets
5599 correspondence
= {'instance_scenario_id': None,
5600 'sdn_net_id': ovim_content
,
5601 'vim_net_id': content
,
5602 'datacenter_tenant_id': datacenter_tenant_id
5605 mydb
.new_row('instance_nets', correspondence
, add_uuid
=True)
5606 except db_base_Exception
as e
:
5607 raise NfvoException("Error saving correspondence for VIM/SDN dataplane networks{}: {}".format(
5608 correspondence
, e
), e
.http_code
)
5609 elif item
=="tenants":
5610 tenant
= descriptor
["tenant"]
5611 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
5613 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5614 except vimconn
.vimconnException
as e
:
5615 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
5617 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
5619 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
5620 data
= ovim
.new_of_controller(sdn_controller
)
5621 logger
.debug('New SDN controller created with uuid {}'.format(data
))
5624 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
5625 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
5626 msg
= 'SDN controller {} updated'.format(data
)
5630 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
5631 if controller_id
== None:
5632 data
= ovim
.get_of_controllers()
5634 data
= ovim
.show_of_controller(controller_id
)
5636 msg
= 'SDN controller list:\n {}'.format(data
)
5640 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
5641 select_
= ('uuid', 'config')
5642 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
5643 for datacenter
in datacenters
:
5644 if datacenter
['config']:
5645 config
= yaml
.load(datacenter
['config'])
5646 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
5647 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), httperrors
.Conflict
)
5649 data
= ovim
.delete_of_controller(controller_id
)
5650 msg
= 'SDN controller {} deleted'.format(data
)
5654 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
5655 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
5656 if len(controller
) < 1:
5657 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), httperrors
.Not_Found
)
5660 sdn_controller_id
= yaml
.load(controller
[0]["config"])["sdn-controller"]
5662 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), httperrors
.Bad_Request
)
5664 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
5665 switch_dpid
= sdn_controller
["dpid"]
5668 for compute_node
in sdn_port_mapping
:
5669 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
5671 element
["compute_node"] = compute_node
["compute_node"]
5672 for port
in compute_node
["ports"]:
5673 pci
= port
.get("pci")
5674 element
["switch_port"] = port
.get("switch_port")
5675 element
["switch_mac"] = port
.get("switch_mac")
5676 if not element
["switch_port"] and not element
["switch_mac"]:
5677 raise NfvoException ("The mapping must contain 'switch_port' or 'switch_mac'", httperrors
.Bad_Request
)
5678 for pci_expanded
in utils
.expand_brackets(pci
):
5679 element
["pci"] = pci_expanded
5680 maps
.append(dict(element
))
5682 return ovim
.set_of_port_mapping(maps
, ofc_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, region
=datacenter_id
)
5684 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
5685 maps
= ovim
.get_of_port_mappings(db_filter
={"region": datacenter_id
})
5688 "sdn-controller": None,
5689 "datacenter-id": datacenter_id
,
5691 "ports_mapping": list()
5694 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
5695 if datacenter
['config']:
5696 config
= yaml
.load(datacenter
['config'])
5697 if 'sdn-controller' in config
:
5698 controller_id
= config
['sdn-controller']
5699 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
5700 result
["sdn-controller"] = controller_id
5701 result
["dpid"] = sdn_controller
["dpid"]
5703 if result
["sdn-controller"] == None:
5704 raise NfvoException("SDN controller is not defined for datacenter {}".format(datacenter_id
), httperrors
.Bad_Request
)
5705 if result
["dpid"] == None:
5706 raise NfvoException("It was not possible to determine DPID for SDN controller {}".format(result
["sdn-controller"]),
5707 httperrors
.Internal_Server_Error
)
5712 ports_correspondence_dict
= dict()
5714 if result
["sdn-controller"] != link
["ofc_id"]:
5715 raise NfvoException("The sdn-controller specified for different port mappings differ", httperrors
.Internal_Server_Error
)
5716 if result
["dpid"] != link
["switch_dpid"]:
5717 raise NfvoException("The dpid specified for different port mappings differ", httperrors
.Internal_Server_Error
)
5719 element
["pci"] = link
["pci"]
5720 if link
["switch_port"]:
5721 element
["switch_port"] = link
["switch_port"]
5722 if link
["switch_mac"]:
5723 element
["switch_mac"] = link
["switch_mac"]
5725 if not link
["compute_node"] in ports_correspondence_dict
:
5727 content
["compute_node"] = link
["compute_node"]
5728 content
["ports"] = list()
5729 ports_correspondence_dict
[link
["compute_node"]] = content
5731 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
5733 for key
in sorted(ports_correspondence_dict
):
5734 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
5738 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
5739 return ovim
.clear_of_port_mapping(db_filter
={"region":datacenter_id
})
5741 def create_RO_keypair(tenant_id
):
5743 Creates a public / private keys for a RO tenant and returns their values
5745 tenant_id: ID of the tenant
5747 public_key: Public key for the RO tenant
5748 private_key: Encrypted private key for RO tenant
5752 key
= RSA
.generate(bits
)
5754 public_key
= key
.publickey().exportKey('OpenSSH')
5755 if isinstance(public_key
, ValueError):
5756 raise NfvoException("Unable to create public key: {}".format(public_key
), httperrors
.Internal_Server_Error
)
5757 private_key
= key
.exportKey(passphrase
=tenant_id
, pkcs
=8)
5758 except (ValueError, NameError) as e
:
5759 raise NfvoException("Unable to create private key: {}".format(e
), httperrors
.Internal_Server_Error
)
5760 return public_key
, private_key
5762 def decrypt_key (key
, tenant_id
):
5764 Decrypts an encrypted RSA key
5766 key: Private key to be decrypted
5767 tenant_id: ID of the tenant
5769 unencrypted_key: Unencrypted private key for RO tenant
5772 key
= RSA
.importKey(key
,tenant_id
)
5773 unencrypted_key
= key
.exportKey('PEM')
5774 if isinstance(unencrypted_key
, ValueError):
5775 raise NfvoException("Unable to decrypt the private key: {}".format(unencrypted_key
), httperrors
.Internal_Server_Error
)
5776 except ValueError as e
:
5777 raise NfvoException("Unable to decrypt the private key: {}".format(e
), httperrors
.Internal_Server_Error
)
5778 return unencrypted_key