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$"
33 from osm_ro
import utils
34 from osm_ro
.utils
import deprecated
35 from osm_ro
.vim_thread
import vim_thread
36 import osm_ro
.console_proxy_thread
as cli
37 from osm_ro
import vimconn
41 from uuid
import uuid4
42 from osm_ro
.db_base
import db_base_Exception
44 from osm_ro
import nfvo_db
45 from threading
import Lock
48 # from lib_osm_openvim import ovim as ovim_module
49 # from lib_osm_openvim.ovim import ovimException
50 from unittest
.mock
import MagicMock
51 ovim_module
= MagicMock()
52 class ovimException(Exception):
54 ovim_module
.ovimException
= ovimException
57 from Crypto
.PublicKey
import RSA
59 import osm_im
.vnfd
as vnfd_catalog
60 import osm_im
.nsd
as nsd_catalog
61 from pyangbind
.lib
.serialise
import pybindJSONDecoder
62 from copy
import deepcopy
63 from pkg_resources
import iter_entry_points
67 import osm_ro
.wim
.wimconn
as wimconn
68 import osm_ro
.wim
.wim_thread
as wim_thread
69 from osm_ro
.http_tools
import errors
as httperrors
70 from osm_ro
.wim
.engine
import WimEngine
71 from osm_ro
.wim
.persistence
import WimPersistence
72 from copy
import deepcopy
73 from pprint
import pformat
80 global wimconn_imported
83 global default_volume_size
84 default_volume_size
= '5' #size in GB
89 plugins
= {} # dictionary with VIM type as key, loaded module as value
90 vim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-VIMs
91 vim_persistent_info
= {}
93 wimconn_imported
= {} # dictionary with WIM type as key, loaded module as value
94 wim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-WIMs
95 wim_persistent_info
= {}
98 logger
= logging
.getLogger('openmano.nfvo')
105 class NfvoException(httperrors
.HttpMappedError
):
106 """Common Class for NFVO errors"""
108 def _load_vim_plugin(name
):
110 for v
in iter_entry_points('osm_rovim.plugins', name
):
111 plugins
[name
] = v
.load()
112 if name
and name
not in plugins
:
113 raise NfvoException("Unknown vim type '{}'. This plugin has not been registered".format(name
),
114 httperrors
.Bad_Request
)
119 if task_id
<= last_task_id
:
120 task_id
= last_task_id
+ 0.000001
121 last_task_id
= task_id
122 return "ACTION-{:.6f}".format(task_id
)
123 # return (t.strftime("%Y%m%dT%H%M%S.{}%Z", t.localtime(task_id))).format(int((task_id % 1)*1e6))
126 def new_task(name
, params
, depends
=None):
128 task_id
= get_task_id()
129 task
= {"status": "enqueued", "id": task_id
, "name": name
, "params": params
}
131 task
["depends"] = depends
136 return True if id[:5] == "TASK-" else False
139 def get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_name
, tenant_id
):
140 name
= datacenter_name
[:16]
141 if name
not in vim_threads
["names"]:
142 vim_threads
["names"].append(name
)
145 name
= datacenter_name
[:16] + "." + tenant_name
[:16]
146 if name
not in vim_threads
["names"]:
147 vim_threads
["names"].append(name
)
150 vim_threads
["names"].append(name
)
154 def get_non_used_wim_name(wim_name
, wim_id
, tenant_name
, tenant_id
):
156 if name
not in wim_threads
["names"]:
157 wim_threads
["names"].append(name
)
159 name
= wim_name
[:16] + "." + tenant_name
[:16]
160 if name
not in wim_threads
["names"]:
161 wim_threads
["names"].append(name
)
163 name
= wim_id
+ "-" + tenant_id
164 wim_threads
["names"].append(name
)
168 def start_service(mydb
, persistence
=None, wim
=None):
169 global db
, global_config
, plugins
170 db
= nfvo_db
.nfvo_db(lock
=db_lock
)
172 db
.connect(global_config
['db_host'], global_config
['db_user'], global_config
['db_passwd'], global_config
['db_name'])
175 persistence
= persistence
or WimPersistence(db
)
177 # Initialize openvim for SDN control
178 # TODO: Avoid static configuration by adding new parameters to openmanod.cfg
179 # TODO: review ovim.py to delete not needed configuration
180 ovim_configuration
= {
181 'logger_name': 'openmano.ovim',
182 'network_vlan_range_start': 1000,
183 'network_vlan_range_end': 4096,
184 'db_name': global_config
["db_ovim_name"],
185 'db_host': global_config
["db_ovim_host"],
186 'db_user': global_config
["db_ovim_user"],
187 'db_passwd': global_config
["db_ovim_passwd"],
190 'network_type': 'bridge',
191 #TODO: log_level_of should not be needed. To be modified in ovim
192 'log_level_of': 'DEBUG'
195 # starts ovim library
196 ovim
= ovim_module
.ovim(ovim_configuration
)
199 wim_engine
= wim
or WimEngine(persistence
)
200 wim_engine
.ovim
= ovim
204 #delete old unneeded vim_wim_actions
208 from_
= 'tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join '\
209 'datacenter_tenants as dt on td.datacenter_tenant_id=dt.uuid'
210 select_
= ('type', 'd.config as config', 'd.uuid as datacenter_id', 'vim_url', 'vim_url_admin',
211 'd.name as datacenter_name', 'dt.uuid as datacenter_tenant_id',
212 'dt.vim_tenant_name as vim_tenant_name', 'dt.vim_tenant_id as vim_tenant_id',
213 'user', 'passwd', 'dt.config as dt_config', 'nfvo_tenant_id')
214 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
)
216 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
217 'datacenter_id': vim
.get('datacenter_id')}
219 extra
.update(yaml
.load(vim
["config"], Loader
=yaml
.Loader
))
220 if vim
.get('dt_config'):
221 extra
.update(yaml
.load(vim
["dt_config"], Loader
=yaml
.Loader
))
222 plugin_name
= "rovim_" + vim
["type"]
223 if plugin_name
not in plugins
:
224 _load_vim_plugin(plugin_name
)
226 thread_id
= vim
['datacenter_tenant_id']
227 vim_persistent_info
[thread_id
] = {}
230 # return -httperrors.Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
231 myvim
= plugins
[plugin_name
].vimconnector(
232 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
233 tenant_id
=vim
['vim_tenant_id'], tenant_name
=vim
['vim_tenant_name'],
234 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
235 user
=vim
['user'], passwd
=vim
['passwd'],
236 config
=extra
, persistent_info
=vim_persistent_info
[thread_id
]
238 except vimconn
.vimconnException
as e
:
240 logger
.error("Cannot launch thread for VIM {} '{}': {}".format(vim
['datacenter_name'],
241 vim
['datacenter_id'], e
))
242 except Exception as e
:
243 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, e
),
244 httperrors
.Internal_Server_Error
)
245 thread_name
= get_non_used_vim_name(vim
['datacenter_name'], vim
['datacenter_id'], vim
['vim_tenant_name'],
246 vim
['vim_tenant_id'])
247 new_thread
= vim_thread(task_lock
, plugins
, thread_name
, vim
['datacenter_name'],
248 vim
['datacenter_tenant_id'], db
=db
, db_lock
=db_lock
, ovim
=ovim
)
250 vim_threads
["running"][thread_id
] = new_thread
252 wim_engine
.start_threads()
253 except db_base_Exception
as e
:
254 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
255 except ovim_module
.ovimException
as e
:
257 if message
[:22] == "DATABASE wrong version":
258 message
= "DATABASE wrong version of lib_osm_openvim {msg} -d{dbname} -u{dbuser} -p{dbpass} {ver}' "\
259 "at host {dbhost}".format(
260 msg
=message
[22:-3], dbname
=global_config
["db_ovim_name"],
261 dbuser
=global_config
["db_ovim_user"], dbpass
=global_config
["db_ovim_passwd"],
262 ver
=message
[-3:-1], dbhost
=global_config
["db_ovim_host"])
263 raise NfvoException(message
, httperrors
.Bad_Request
)
267 global ovim
, global_config
270 for thread_id
, thread
in vim_threads
["running"].items():
271 thread
.insert_task("exit")
272 vim_threads
["deleting"][thread_id
] = thread
273 vim_threads
["running"] = {}
276 wim_engine
.stop_threads()
278 if global_config
and global_config
.get("console_thread"):
279 for thread
in global_config
["console_thread"]:
280 thread
.terminate
= True
283 return ("openmanod version {} {}\n(c) Copyright Telefonica".format(global_config
["version"],
284 global_config
["version_date"] ))
288 Clean unused or old entries at database to avoid unlimited growing
289 :param mydb: database connector
292 # get and delete unused vim_wim_actions: all elements deleted, one week before, instance not present
293 now
= t
.time()-3600*24*7
294 instance_action_id
= None
297 actions_to_delete
= mydb
.get_rows(
298 SELECT
=("item", "item_id", "instance_action_id"),
299 FROM
="vim_wim_actions as va join instance_actions as ia on va.instance_action_id=ia.uuid "
300 "left join instance_scenarios as i on ia.instance_id=i.uuid",
301 WHERE
={"va.action": "DELETE", "va.modified_at<": now
, "i.uuid": None,
302 "va.status": ("DONE", "SUPERSEDED")},
305 for to_delete
in actions_to_delete
:
306 mydb
.delete_row(FROM
="vim_wim_actions", WHERE
=to_delete
)
307 if instance_action_id
!= to_delete
["instance_action_id"]:
308 instance_action_id
= to_delete
["instance_action_id"]
309 mydb
.delete_row(FROM
="instance_actions", WHERE
={"uuid": instance_action_id
})
310 nb_deleted
+= len(actions_to_delete
)
311 if len(actions_to_delete
) < 100:
314 mydb
.update_rows("vim_wim_actions", UPDATE
={"worker": None}, WHERE
={"worker<>": None})
317 logger
.debug("Removed {} unused vim_wim_actions".format(nb_deleted
))
320 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
322 return result, content:
323 <0, error_text upon error
324 nb_records, flavor_list on success
327 WHERE_dict
['vnf_id'] = vnf_id
328 if nfvo_tenant
is not None:
329 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
331 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
332 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
333 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
334 #print "get_flavor_list result:", result
335 #print "get_flavor_list content:", content
337 for flavor
in flavors
:
338 flavorList
.append(flavor
['flavor_id'])
342 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
344 Get used images of all vms belonging to this VNFD
345 :param mydb: database conector
346 :param vnf_id: vnfd uuid
347 :param nfvo_tenant: tenant, not used
348 :return: The list of image uuid used
351 vms
= mydb
.get_rows(SELECT
=('image_id','image_list'), FROM
='vms', WHERE
={'vnf_id': vnf_id
})
353 if vm
["image_id"] and vm
["image_id"] not in image_list
:
354 image_list
.append(vm
["image_id"])
356 vm_image_list
= yaml
.load(vm
["image_list"], Loader
=yaml
.Loader
)
357 for image_dict
in vm_image_list
:
358 if image_dict
["image_id"] not in image_list
:
359 image_list
.append(image_dict
["image_id"])
363 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
364 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None, ignore_errors
=False):
365 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
366 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
367 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
368 raise exception upon error
372 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
373 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
374 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
375 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
376 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
377 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
378 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
379 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'
380 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
381 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
382 'user','passwd', 'dt.config as dt_config')
384 from_
= 'datacenters as d'
385 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
387 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
390 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
391 'datacenter_id': vim
.get('datacenter_id'),
392 '_vim_type_internal': vim
.get('type')}
394 extra
.update(yaml
.load(vim
["config"], Loader
=yaml
.Loader
))
395 if vim
.get('dt_config'):
396 extra
.update(yaml
.load(vim
["dt_config"], Loader
=yaml
.Loader
))
397 plugin_name
= "rovim_" + vim
["type"]
398 if plugin_name
not in plugins
:
400 _load_vim_plugin(plugin_name
)
401 except NfvoException
as e
:
403 logger
.error("{}".format(e
))
408 if 'datacenter_tenant_id' in vim
:
409 thread_id
= vim
["datacenter_tenant_id"]
410 if thread_id
not in vim_persistent_info
:
411 vim_persistent_info
[thread_id
] = {}
412 persistent_info
= vim_persistent_info
[thread_id
]
416 # return -httperrors.Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
417 vim_dict
[vim
['datacenter_id']] = plugins
[plugin_name
].vimconnector(
418 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
419 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
),
420 tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
421 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
422 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
423 config
=extra
, persistent_info
=persistent_info
425 except Exception as e
:
427 logger
.error("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)))
429 http_code
= httperrors
.Internal_Server_Error
430 if isinstance(e
, vimconn
.vimconnException
):
431 http_code
= e
.http_code
432 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), http_code
)
434 except db_base_Exception
as e
:
435 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
438 def rollback(mydb
, vims
, rollback_list
):
440 #delete things by reverse order
441 for i
in range(len(rollback_list
)-1, -1, -1):
442 item
= rollback_list
[i
]
443 if item
["where"]=="vim":
444 if item
["vim_id"] not in vims
:
446 if is_task_id(item
["uuid"]):
448 vim
= vims
[item
["vim_id"]]
450 if item
["what"]=="image":
451 vim
.delete_image(item
["uuid"])
452 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_vim_id": vim
["id"], "vim_id":item
["uuid"]})
453 elif item
["what"]=="flavor":
454 vim
.delete_flavor(item
["uuid"])
455 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_vim_id": vim
["id"], "vim_id":item
["uuid"]})
456 elif item
["what"]=="network":
457 vim
.delete_network(item
["uuid"])
458 elif item
["what"]=="vm":
459 vim
.delete_vminstance(item
["uuid"])
460 except vimconn
.vimconnException
as e
:
461 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
462 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
463 except db_base_Exception
as e
:
464 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
468 if item
["what"]=="image":
469 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
470 elif item
["what"]=="flavor":
471 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
472 except db_base_Exception
as e
:
473 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
474 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
475 if len(undeleted_items
)==0:
476 return True," Rollback successful."
478 return False," Rollback fails to delete: " + str(undeleted_items
)
481 def check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1):
483 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
485 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
487 #dataplane interfaces
488 for numa
in vnfc
.get("numas",() ):
489 for interface
in numa
.get("interfaces",()):
490 if interface
["name"] in name_dict
:
492 "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
493 vnfc
["name"], interface
["name"]),
494 httperrors
.Bad_Request
)
495 name_dict
[ interface
["name"] ] = "underlay"
497 for interface
in vnfc
.get("bridge-ifaces",() ):
498 if interface
["name"] in name_dict
:
500 "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
501 vnfc
["name"], interface
["name"]),
502 httperrors
.Bad_Request
)
503 name_dict
[ interface
["name"] ] = "overlay"
504 vnfc_interfaces
[ vnfc
["name"] ] = name_dict
505 # check bood-data info
506 # if "boot-data" in vnfc:
507 # # check that user-data is incompatible with users and config-files
508 # if (vnfc["boot-data"].get("users") or vnfc["boot-data"].get("config-files")) and vnfc["boot-data"].get("user-data"):
509 # raise NfvoException(
510 # "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
511 # httperrors.Bad_Request)
513 #check if the info in external_connections matches with the one in the vnfcs
515 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
516 if external_connection
["name"] in name_list
:
518 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
519 external_connection
["name"]),
520 httperrors
.Bad_Request
)
521 name_list
.append(external_connection
["name"])
522 if external_connection
["VNFC"] not in vnfc_interfaces
:
524 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
525 external_connection
["name"], external_connection
["VNFC"]),
526 httperrors
.Bad_Request
)
528 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
530 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
531 external_connection
["name"],
532 external_connection
["local_iface_name"]),
533 httperrors
.Bad_Request
)
535 #check if the info in internal_connections matches with the one in the vnfcs
537 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
538 if internal_connection
["name"] in name_list
:
540 "Error at vnf:internal-connections:name, value '{}' already used as an internal-connection".format(
541 internal_connection
["name"]),
542 httperrors
.Bad_Request
)
543 name_list
.append(internal_connection
["name"])
544 #We should check that internal-connections of type "ptp" have only 2 elements
546 if len(internal_connection
["elements"])>2 and (internal_connection
.get("type") == "ptp" or internal_connection
.get("type") == "e-line"):
548 "Error at 'vnf:internal-connections[name:'{}']:elements', size must be 2 for a '{}' type. Consider change it to '{}' type".format(
549 internal_connection
["name"],
550 'ptp' if vnf_descriptor_version
==1 else 'e-line',
551 'data' if vnf_descriptor_version
==1 else "e-lan"),
552 httperrors
.Bad_Request
)
553 for port
in internal_connection
["elements"]:
555 iface
= port
["local_iface_name"]
556 if vnf
not in vnfc_interfaces
:
558 "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
559 internal_connection
["name"], vnf
),
560 httperrors
.Bad_Request
)
561 if iface
not in vnfc_interfaces
[ vnf
]:
563 "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
564 internal_connection
["name"], iface
),
565 httperrors
.Bad_Request
)
566 return -httperrors
.Bad_Request
,
567 if vnf_descriptor_version
==1 and "type" not in internal_connection
:
568 if vnfc_interfaces
[vnf
][iface
] == "overlay":
569 internal_connection
["type"] = "bridge"
571 internal_connection
["type"] = "data"
572 if vnf_descriptor_version
==2 and "implementation" not in internal_connection
:
573 if vnfc_interfaces
[vnf
][iface
] == "overlay":
574 internal_connection
["implementation"] = "overlay"
576 internal_connection
["implementation"] = "underlay"
577 if (internal_connection
.get("type") == "data" or internal_connection
.get("type") == "ptp" or \
578 internal_connection
.get("implementation") == "underlay") and vnfc_interfaces
[vnf
][iface
] == "overlay":
580 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
581 internal_connection
["name"],
582 iface
, 'bridge' if vnf_descriptor_version
==1 else 'overlay',
583 'data' if vnf_descriptor_version
==1 else 'underlay'),
584 httperrors
.Bad_Request
)
585 if (internal_connection
.get("type") == "bridge" or internal_connection
.get("implementation") == "overlay") and \
586 vnfc_interfaces
[vnf
][iface
] == "underlay":
588 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
589 internal_connection
["name"], iface
,
590 'data' if vnf_descriptor_version
==1 else 'underlay',
591 'bridge' if vnf_descriptor_version
==1 else 'overlay'),
592 httperrors
.Bad_Request
)
595 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=None):
597 if only_create_at_vim
:
598 image_mano_id
= image_dict
['uuid']
599 if return_on_error
== None:
600 return_on_error
= True
602 if image_dict
['location']:
603 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
605 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
607 image_mano_id
= images
[0]['uuid']
609 #create image in MANO DB
610 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
611 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
612 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
614 #temp_image_dict['location'] = image_dict.get('new_location') if image_dict['location'] is None
615 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
616 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
617 #create image at every vim
618 for vim_id
,vim
in vims
.items():
619 datacenter_vim_id
= vim
["config"]["datacenter_tenant_id"]
620 image_created
="false"
622 image_db
= mydb
.get_rows(FROM
="datacenters_images",
623 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'image_id': image_mano_id
})
624 #look at VIM if this image exist
626 if image_dict
['location'] is not None:
627 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
630 filter_dict
['name'] = image_dict
['universal_name']
631 if image_dict
.get('checksum') != None:
632 filter_dict
['checksum'] = image_dict
['checksum']
633 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
634 vim_images
= vim
.get_image_list(filter_dict
)
635 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
636 if len(vim_images
) > 1:
637 raise vimconn
.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict
)), httperrors
.Conflict
)
638 elif len(vim_images
) == 0:
639 raise vimconn
.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict
)))
641 #logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
642 image_vim_id
= vim_images
[0]['id']
644 except vimconn
.vimconnNotFoundException
as e
:
645 #Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
647 #image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
648 if image_dict
['location']:
649 image_vim_id
= vim
.new_image(image_dict
)
650 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
653 #If we reach this point, then the image has image name, and optionally checksum, and could not be found
654 raise vimconn
.vimconnException(str(e
))
655 except vimconn
.vimconnException
as e
:
657 logger
.error("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
660 logger
.warn("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
662 except vimconn
.vimconnException
as e
:
664 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
666 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
669 #if we reach here, the image has been created or existed
671 #add new vim_id at datacenters_images
672 mydb
.new_row('datacenters_images', {'datacenter_vim_id': datacenter_vim_id
,
673 'image_id':image_mano_id
,
674 'vim_id': image_vim_id
,
675 'created':image_created
})
676 elif image_db
[0]["vim_id"]!=image_vim_id
:
677 #modify existing vim_id at datacenters_images
678 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_vim_id':vim_id
, 'image_id':image_mano_id
})
680 return image_vim_id
if only_create_at_vim
else image_mano_id
683 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
684 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',0),
685 'ram':flavor_dict
.get('ram'),
686 'vcpus':flavor_dict
.get('vcpus'),
688 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
689 del flavor_dict
['extended']
690 if 'extended' in flavor_dict
:
691 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
693 #look if flavor exist
694 if only_create_at_vim
:
695 flavor_mano_id
= flavor_dict
['uuid']
696 if return_on_error
== None:
697 return_on_error
= True
699 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
701 flavor_mano_id
= flavors
[0]['uuid']
704 #create one by one the images of aditional disks
705 dev_image_list
=[] #list of images
706 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
708 for device
in flavor_dict
['extended'].get('devices',[]):
709 if "image" not in device
and "image name" not in device
:
712 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
713 image_dict
['universal_name']=device
.get('image name')
714 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
715 image_dict
['location']=device
.get('image')
716 #image_dict['new_location']=vnfc.get('image location')
717 image_dict
['checksum']=device
.get('image checksum')
718 image_metadata_dict
= device
.get('image metadata', None)
719 image_metadata_str
= None
720 if image_metadata_dict
!= None:
721 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
722 image_dict
['metadata']=image_metadata_str
723 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
724 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
725 dev_image_list
.append(image_id
)
727 temp_flavor_dict
['name'] = flavor_dict
['name']
728 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
729 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
730 flavor_mano_id
= content
731 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
732 #create flavor at every vim
733 if 'uuid' in flavor_dict
:
734 del flavor_dict
['uuid']
736 for vim_id
,vim
in vims
.items():
737 datacenter_vim_id
= vim
["config"]["datacenter_tenant_id"]
738 flavor_created
="false"
740 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors",
741 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
})
742 #look at VIM if this flavor exist SKIPPED
743 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
745 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
749 # Create the flavor in VIM
750 # Translate images at devices from MANO id to VIM id
752 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
753 # make a copy of original devices
756 for device
in flavor_dict
["extended"].get("devices",[]):
759 devices_original
.append(dev
)
760 if 'image' in device
:
762 if 'image metadata' in device
:
763 del device
['image metadata']
764 if 'image checksum' in device
:
765 del device
['image checksum']
767 for index
in range(0,len(devices_original
)) :
768 device
=devices_original
[index
]
769 if "image" not in device
and "image name" not in device
:
770 # if 'size' in device:
771 disk_list
.append({'size': device
.get('size', default_volume_size
), 'name': device
.get('name')})
774 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
775 image_dict
['universal_name']=device
.get('image name')
776 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
777 image_dict
['location']=device
.get('image')
778 # image_dict['new_location']=device.get('image location')
779 image_dict
['checksum']=device
.get('image checksum')
780 image_metadata_dict
= device
.get('image metadata', None)
781 image_metadata_str
= None
782 if image_metadata_dict
!= None:
783 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
784 image_dict
['metadata']=image_metadata_str
785 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
786 image_dict
["uuid"]=image_mano_id
787 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
789 #save disk information (image must be based on and size
790 disk_list
.append({'image_id': image_vim_id
, 'size': device
.get('size', default_volume_size
)})
792 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
795 #check that this vim_id exist in VIM, if not create
796 flavor_vim_id
=flavor_db
[0]["vim_id"]
798 vim
.get_flavor(flavor_vim_id
)
799 continue #flavor exist
800 except vimconn
.vimconnException
:
802 #create flavor at vim
803 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
806 flavor_vim_id
=vim
.get_flavor_id_from_data(flavor_dict
)
807 flavor_created
="false"
808 except vimconn
.vimconnException
as e
:
811 if not flavor_vim_id
:
812 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
813 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
814 flavor_created
="true"
815 except vimconn
.vimconnException
as e
:
817 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
819 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
822 #if reach here the flavor has been create or exist
823 if len(flavor_db
)==0:
824 #add new vim_id at datacenters_flavors
825 extended_devices_yaml
= None
826 if len(disk_list
) > 0:
827 extended_devices
= dict()
828 extended_devices
['disks'] = disk_list
829 extended_devices_yaml
= yaml
.safe_dump(extended_devices
,default_flow_style
=True,width
=256)
830 mydb
.new_row('datacenters_flavors',
831 {'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
, 'vim_id': flavor_vim_id
,
832 'created': flavor_created
, 'extended': extended_devices_yaml
})
833 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
834 #modify existing vim_id at datacenters_flavors
835 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
},
836 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
})
838 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
841 def get_str(obj
, field
, length
):
843 Obtain the str value,
848 value
= obj
.get(field
)
849 if value
is not None:
850 value
= str(value
)[:length
]
853 def _lookfor_or_create_image(db_image
, mydb
, descriptor
):
855 fill image content at db_image dictionary. Check if the image with this image and checksum exist
856 :param db_image: dictionary to insert data
857 :param mydb: database connector
858 :param descriptor: yang descriptor
859 :return: uuid if the image exist at DB, or None if a new image must be created with the data filled at db_image
862 db_image
["name"] = get_str(descriptor
, "image", 255)
863 db_image
["checksum"] = get_str(descriptor
, "image-checksum", 32)
864 if not db_image
["checksum"]: # Ensure that if empty string, None is stored
865 db_image
["checksum"] = None
866 if db_image
["name"].startswith("/"):
867 db_image
["location"] = db_image
["name"]
868 existing_images
= mydb
.get_rows(FROM
="images", WHERE
={'location': db_image
["location"]})
870 db_image
["universal_name"] = db_image
["name"]
871 existing_images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name': db_image
['universal_name'],
872 'checksum': db_image
['checksum']})
874 return existing_images
[0]["uuid"]
876 image_uuid
= str(uuid4())
877 db_image
["uuid"] = image_uuid
880 def get_resource_allocation_params(quota_descriptor
):
882 read the quota_descriptor from vnfd and fetch the resource allocation properties from the descriptor object
883 :param quota_descriptor: cpu/mem/vif/disk-io quota descriptor
884 :return: quota params for limit, reserve, shares from the descriptor object
887 if quota_descriptor
.get("limit"):
888 quota
["limit"] = int(quota_descriptor
["limit"])
889 if quota_descriptor
.get("reserve"):
890 quota
["reserve"] = int(quota_descriptor
["reserve"])
891 if quota_descriptor
.get("shares"):
892 quota
["shares"] = int(quota_descriptor
["shares"])
895 def new_vnfd_v3(mydb
, tenant_id
, vnf_descriptor
):
897 Parses an OSM IM vnfd_catalog and insert at DB
900 :param vnf_descriptor:
901 :return: The list of cretated vnf ids
904 myvnfd
= vnfd_catalog
.vnfd()
906 pybindJSONDecoder
.load_ietf_json(vnf_descriptor
, None, None, obj
=myvnfd
, path_helper
=True,
908 except Exception as e
:
909 raise NfvoException("Error. Invalid VNF descriptor format " + str(e
), httperrors
.Bad_Request
)
917 db_ip_profiles_index
= 0
921 vnfd_catalog_descriptor
= vnf_descriptor
.get("vnfd:vnfd-catalog")
922 if not vnfd_catalog_descriptor
:
923 vnfd_catalog_descriptor
= vnf_descriptor
.get("vnfd-catalog")
924 vnfd_descriptor_list
= vnfd_catalog_descriptor
.get("vnfd")
925 if not vnfd_descriptor_list
:
926 vnfd_descriptor_list
= vnfd_catalog_descriptor
.get("vnfd:vnfd")
927 for vnfd_yang
in myvnfd
.vnfd_catalog
.vnfd
.values():
928 vnfd
= vnfd_yang
.get()
931 vnf_uuid
= str(uuid4())
932 uuid_list
.append(vnf_uuid
)
933 vnfd_uuid_list
.append(vnf_uuid
)
934 vnfd_id
= get_str(vnfd
, "id", 255)
938 "name": get_str(vnfd
, "name", 255),
939 "description": get_str(vnfd
, "description", 255),
940 "tenant_id": tenant_id
,
941 "vendor": get_str(vnfd
, "vendor", 255),
942 "short_name": get_str(vnfd
, "short-name", 255),
943 "descriptor": str(vnf_descriptor
)[:60000]
946 for vnfd_descriptor
in vnfd_descriptor_list
:
947 if vnfd_descriptor
["id"] == str(vnfd
["id"]):
950 # table ip_profiles (ip-profiles)
951 ip_profile_name2db_table_index
= {}
952 for ip_profile
in vnfd
.get("ip-profiles").values():
954 "ip_version": str(ip_profile
["ip-profile-params"].get("ip-version", "ipv4")),
955 "subnet_address": str(ip_profile
["ip-profile-params"].get("subnet-address")),
956 "gateway_address": str(ip_profile
["ip-profile-params"].get("gateway-address")),
957 "dhcp_enabled": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("enabled", True)),
958 "dhcp_start_address": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("start-address")),
959 "dhcp_count": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("count")),
962 for dns
in ip_profile
["ip-profile-params"]["dns-server"].values():
963 dns_list
.append(str(dns
.get("address")))
964 db_ip_profile
["dns_address"] = ";".join(dns_list
)
965 if ip_profile
["ip-profile-params"].get('security-group'):
966 db_ip_profile
["security_group"] = ip_profile
["ip-profile-params"]['security-group']
967 ip_profile_name2db_table_index
[str(ip_profile
["name"])] = db_ip_profiles_index
968 db_ip_profiles_index
+= 1
969 db_ip_profiles
.append(db_ip_profile
)
971 # table nets (internal-vld)
972 net_id2uuid
= {} # for mapping interface with network
973 for vld
in vnfd
.get("internal-vld").values():
974 net_uuid
= str(uuid4())
975 uuid_list
.append(net_uuid
)
977 "name": get_str(vld
, "name", 255),
980 "description": get_str(vld
, "description", 255),
981 "osm_id": get_str(vld
, "id", 255),
982 "type": "bridge", # TODO adjust depending on connection point type
984 net_id2uuid
[vld
.get("id")] = net_uuid
985 db_nets
.append(db_net
)
986 # ip-profile, link db_ip_profile with db_sce_net
987 if vld
.get("ip-profile-ref"):
988 ip_profile_name
= vld
.get("ip-profile-ref")
989 if ip_profile_name
not in ip_profile_name2db_table_index
:
990 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vld[{}]':'ip-profile-ref':"
991 "'{}'. Reference to a non-existing 'ip_profiles'".format(
992 str(vnfd
["id"]), str(vld
["id"]), str(vld
["ip-profile-ref"])),
993 httperrors
.Bad_Request
)
994 db_ip_profiles
[ip_profile_name2db_table_index
[ip_profile_name
]]["net_id"] = net_uuid
995 else: #check no ip-address has been defined
996 for icp
in vld
.get("internal-connection-point").values():
997 if icp
.get("ip-address"):
998 raise NfvoException("Error at 'vnfd[{}]':'vld[{}]':'internal-connection-point[{}]' "
999 "contains an ip-address but no ip-profile has been defined at VLD".format(
1000 str(vnfd
["id"]), str(vld
["id"]), str(icp
["id"])),
1001 httperrors
.Bad_Request
)
1003 # connection points vaiable declaration
1004 cp_name2iface_uuid
= {}
1006 cp_name2vm_uuid
= {}
1007 cp_name2db_interface
= {}
1008 vdu_id2cp_name
= {} # stored only when one external connection point is presented at this VDU
1012 vdu_id2db_table_index
= {}
1014 for vdu
in vnfd
.get("vdu").values():
1016 for vdu_descriptor
in vnfd_descriptor
["vdu"]:
1017 if vdu_descriptor
["id"] == str(vdu
["id"]):
1019 vm_uuid
= str(uuid4())
1020 uuid_list
.append(vm_uuid
)
1021 vdu_id
= get_str(vdu
, "id", 255)
1025 "name": get_str(vdu
, "name", 255),
1026 "description": get_str(vdu
, "description", 255),
1027 "pdu_type": get_str(vdu
, "pdu-type", 255),
1030 vdu_id2uuid
[db_vm
["osm_id"]] = vm_uuid
1031 vdu_id2db_table_index
[db_vm
["osm_id"]] = db_vms_index
1032 if vdu
.get("count"):
1033 db_vm
["count"] = int(vdu
["count"])
1036 image_present
= False
1037 if vdu
.get("image"):
1038 image_present
= True
1040 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, vdu
)
1042 image_uuid
= db_image
["uuid"]
1043 db_images
.append(db_image
)
1044 db_vm
["image_id"] = image_uuid
1045 if vdu
.get("alternative-images"):
1046 vm_alternative_images
= []
1047 for alt_image
in vdu
.get("alternative-images").values():
1049 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, alt_image
)
1051 image_uuid
= db_image
["uuid"]
1052 db_images
.append(db_image
)
1053 vm_alternative_images
.append({
1054 "image_id": image_uuid
,
1055 "vim_type": str(alt_image
["vim-type"]),
1056 # "universal_name": str(alt_image["image"]),
1057 # "checksum": str(alt_image["image-checksum"]) if alt_image.get("image-checksum") else None
1060 db_vm
["image_list"] = yaml
.safe_dump(vm_alternative_images
, default_flow_style
=True, width
=256)
1064 if vdu
.get("volumes"):
1065 for volume_key
in vdu
["volumes"]:
1066 volume
= vdu
["volumes"][volume_key
]
1067 if not image_present
:
1068 # Convert the first volume to vnfc.image
1069 image_present
= True
1071 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, volume
)
1073 image_uuid
= db_image
["uuid"]
1074 db_images
.append(db_image
)
1075 db_vm
["image_id"] = image_uuid
1077 # Add Openmano devices
1078 device
= {"name": str(volume
.get("name"))}
1079 device
["type"] = str(volume
.get("device-type"))
1080 if volume
.get("size"):
1081 device
["size"] = int(volume
["size"])
1082 if volume
.get("image"):
1083 device
["image name"] = str(volume
["image"])
1084 if volume
.get("image-checksum"):
1085 device
["image checksum"] = str(volume
["image-checksum"])
1087 devices
.append(device
)
1089 if not db_vm
.get("image_id"):
1090 if not db_vm
["pdu_type"]:
1091 raise NfvoException("Not defined image for VDU")
1092 # create a fake image
1096 if vdu
.get("cloud-init"):
1097 boot_data
["user-data"] = str(vdu
["cloud-init"])
1098 elif vdu
.get("cloud-init-file"):
1099 # TODO Where this file content is present???
1100 # boot_data["user-data"] = vnfd_yang.files[vdu["cloud-init-file"]]
1101 boot_data
["user-data"] = str(vdu
["cloud-init-file"])
1103 if vdu
.get("supplemental-boot-data"):
1104 if vdu
["supplemental-boot-data"].get('boot-data-drive'):
1105 boot_data
['boot-data-drive'] = True
1106 if vdu
["supplemental-boot-data"].get('config-file'):
1107 om_cfgfile_list
= list()
1108 for custom_config_file
in vdu
["supplemental-boot-data"]['config-file'].values():
1109 # TODO Where this file content is present???
1110 cfg_source
= str(custom_config_file
["source"])
1111 om_cfgfile_list
.append({"dest": custom_config_file
["dest"],
1112 "content": cfg_source
})
1113 boot_data
['config-files'] = om_cfgfile_list
1115 db_vm
["boot_data"] = yaml
.safe_dump(boot_data
, default_flow_style
=True, width
=256)
1117 db_vms
.append(db_vm
)
1120 # table interfaces (internal/external interfaces)
1121 flavor_epa_interfaces
= []
1122 # for iface in chain(vdu.get("internal-interface").values(), vdu.get("external-interface").values()):
1123 for iface
in vdu
.get("interface").values():
1124 flavor_epa_interface
= {}
1125 iface_uuid
= str(uuid4())
1126 uuid_list
.append(iface_uuid
)
1129 "internal_name": get_str(iface
, "name", 255),
1132 flavor_epa_interface
["name"] = db_interface
["internal_name"]
1133 if iface
.get("virtual-interface").get("vpci"):
1134 db_interface
["vpci"] = get_str(iface
.get("virtual-interface"), "vpci", 12)
1135 flavor_epa_interface
["vpci"] = db_interface
["vpci"]
1137 if iface
.get("virtual-interface").get("bandwidth"):
1138 bps
= int(iface
.get("virtual-interface").get("bandwidth"))
1139 db_interface
["bw"] = int(math
.ceil(bps
/ 1000000.0))
1140 flavor_epa_interface
["bandwidth"] = "{} Mbps".format(db_interface
["bw"])
1142 if iface
.get("virtual-interface").get("type") == "OM-MGMT":
1143 db_interface
["type"] = "mgmt"
1144 elif iface
.get("virtual-interface").get("type") in ("VIRTIO", "E1000", "PARAVIRT"):
1145 db_interface
["type"] = "bridge"
1146 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1147 elif iface
.get("virtual-interface").get("type") in ("SR-IOV", "PCI-PASSTHROUGH"):
1148 db_interface
["type"] = "data"
1149 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1150 flavor_epa_interface
["dedicated"] = "no" if iface
["virtual-interface"]["type"] == "SR-IOV" \
1152 flavor_epa_interfaces
.append(flavor_epa_interface
)
1154 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vdu[{}]':'interface':'virtual"
1155 "-interface':'type':'{}'. Interface type is not supported".format(
1156 vnfd_id
, vdu_id
, iface
.get("virtual-interface").get("type")),
1157 httperrors
.Bad_Request
)
1159 if iface
.get("mgmt-interface"):
1160 db_interface
["type"] = "mgmt"
1162 if iface
.get("external-connection-point-ref"):
1164 cp
= vnfd
.get("connection-point")[iface
.get("external-connection-point-ref")]
1165 db_interface
["external_name"] = get_str(cp
, "name", 255)
1166 cp_name2iface_uuid
[db_interface
["external_name"]] = iface_uuid
1167 cp_name2vdu_id
[db_interface
["external_name"]] = vdu_id
1168 cp_name2vm_uuid
[db_interface
["external_name"]] = vm_uuid
1169 cp_name2db_interface
[db_interface
["external_name"]] = db_interface
1170 for cp_descriptor
in vnfd_descriptor
["connection-point"]:
1171 if cp_descriptor
["name"] == db_interface
["external_name"]:
1176 if vdu_id
in vdu_id2cp_name
:
1177 vdu_id2cp_name
[vdu_id
] = None # more than two connecdtion point for this VDU
1179 vdu_id2cp_name
[vdu_id
] = db_interface
["external_name"]
1182 if str(cp_descriptor
.get("port-security-enabled")).lower() == "false":
1183 db_interface
["port_security"] = 0
1184 elif str(cp_descriptor
.get("port-security-enabled")).lower() == "true":
1185 db_interface
["port_security"] = 1
1187 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1188 "'interface[{iface}]':'vnfd-connection-point-ref':'{cp}' is not present"
1189 " at connection-point".format(
1190 vnf
=vnfd_id
, vdu
=vdu_id
, iface
=iface
["name"],
1191 cp
=iface
.get("vnfd-connection-point-ref")),
1192 httperrors
.Bad_Request
)
1193 elif iface
.get("internal-connection-point-ref"):
1195 for icp_descriptor
in vdu_descriptor
["internal-connection-point"]:
1196 if icp_descriptor
["id"] == str(iface
.get("internal-connection-point-ref")):
1199 raise KeyError("does not exist at vdu:internal-connection-point")
1202 for vld
in vnfd
.get("internal-vld").values():
1203 for cp
in vld
.get("internal-connection-point").values():
1204 if cp
.get("id-ref") == iface
.get("internal-connection-point-ref"):
1206 raise KeyError("is referenced by more than one 'internal-vld'")
1210 raise KeyError("is not referenced by any 'internal-vld'")
1212 db_interface
["net_id"] = net_id2uuid
[icp_vld
.get("id")]
1213 if str(icp_descriptor
.get("port-security-enabled")).lower() == "false":
1214 db_interface
["port_security"] = 0
1215 elif str(icp_descriptor
.get("port-security-enabled")).lower() == "true":
1216 db_interface
["port_security"] = 1
1217 if icp
.get("ip-address"):
1218 if not icp_vld
.get("ip-profile-ref"):
1220 db_interface
["ip_address"] = str(icp
.get("ip-address"))
1221 except KeyError as e
:
1222 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1223 "'interface[{iface}]':'internal-connection-point-ref':'{cp}'"
1225 vnf
=vnfd_id
, vdu
=vdu_id
, iface
=iface
["name"],
1226 cp
=iface
.get("internal-connection-point-ref"), msg
=str(e
)),
1227 httperrors
.Bad_Request
)
1228 if iface
.get("position"):
1229 db_interface
["created_at"] = int(iface
.get("position")) * 50
1230 if iface
.get("mac-address"):
1231 db_interface
["mac"] = str(iface
.get("mac-address"))
1232 db_interfaces
.append(db_interface
)
1236 "name": get_str(vdu
, "name", 250) + "-flv",
1237 "vcpus": int(vdu
["vm-flavor"].get("vcpu-count", 1)),
1238 "ram": int(vdu
["vm-flavor"].get("memory-mb", 1)),
1239 "disk": int(vdu
["vm-flavor"].get("storage-gb", 0)),
1241 # TODO revise the case of several numa-node-policy node
1245 extended
["devices"] = devices
1246 if flavor_epa_interfaces
:
1247 numa
["interfaces"] = flavor_epa_interfaces
1248 if vdu
.get("guest-epa"): # TODO or dedicated_int:
1249 epa_vcpu_set
= False
1250 if vdu
["guest-epa"].get("numa-node-policy"): # TODO or dedicated_int:
1251 numa_node_policy
= vdu
["guest-epa"].get("numa-node-policy")
1252 if numa_node_policy
.get("node"):
1253 numa_node
= next(iter(numa_node_policy
["node"].values()))
1254 if numa_node
.get("num-cores"):
1255 numa
["cores"] = numa_node
["num-cores"]
1257 if numa_node
.get("paired-threads"):
1258 if numa_node
["paired-threads"].get("num-paired-threads"):
1259 numa
["paired-threads"] = int(numa_node
["paired-threads"]["num-paired-threads"])
1261 if len(numa_node
["paired-threads"].get("paired-thread-ids")):
1262 numa
["paired-threads-id"] = []
1263 for pair
in numa_node
["paired-threads"]["paired-thread-ids"].values():
1264 numa
["paired-threads-id"].append(
1265 (str(pair
["thread-a"]), str(pair
["thread-b"]))
1267 if numa_node
.get("num-threads"):
1268 numa
["threads"] = int(numa_node
["num-threads"])
1270 if numa_node
.get("memory-mb"):
1271 numa
["memory"] = max(int(numa_node
["memory-mb"] / 1024), 1)
1272 if vdu
["guest-epa"].get("mempage-size"):
1273 if vdu
["guest-epa"]["mempage-size"] != "SMALL":
1274 numa
["memory"] = max(int(db_flavor
["ram"] / 1024), 1)
1275 if vdu
["guest-epa"].get("cpu-pinning-policy") and not epa_vcpu_set
:
1276 if vdu
["guest-epa"]["cpu-pinning-policy"] == "DEDICATED":
1277 if vdu
["guest-epa"].get("cpu-thread-pinning-policy") and \
1278 vdu
["guest-epa"]["cpu-thread-pinning-policy"] != "PREFER":
1279 numa
["cores"] = max(db_flavor
["vcpus"], 1)
1281 numa
["threads"] = max(db_flavor
["vcpus"], 1)
1283 if vdu
["guest-epa"].get("cpu-quota") and not epa_vcpu_set
:
1284 cpuquota
= get_resource_allocation_params(vdu
["guest-epa"].get("cpu-quota"))
1286 extended
["cpu-quota"] = cpuquota
1287 if vdu
["guest-epa"].get("mem-quota"):
1288 vduquota
= get_resource_allocation_params(vdu
["guest-epa"].get("mem-quota"))
1290 extended
["mem-quota"] = vduquota
1291 if vdu
["guest-epa"].get("disk-io-quota"):
1292 diskioquota
= get_resource_allocation_params(vdu
["guest-epa"].get("disk-io-quota"))
1294 extended
["disk-io-quota"] = diskioquota
1295 if vdu
["guest-epa"].get("vif-quota"):
1296 vifquota
= get_resource_allocation_params(vdu
["guest-epa"].get("vif-quota"))
1298 extended
["vif-quota"] = vifquota
1300 extended
["numas"] = [numa
]
1302 extended_text
= yaml
.safe_dump(extended
, default_flow_style
=True, width
=256)
1303 db_flavor
["extended"] = extended_text
1304 # look if flavor exist
1305 temp_flavor_dict
= {'disk': db_flavor
.get('disk', 0),
1306 'ram': db_flavor
.get('ram'),
1307 'vcpus': db_flavor
.get('vcpus'),
1308 'extended': db_flavor
.get('extended')
1310 existing_flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
1311 if existing_flavors
:
1312 flavor_uuid
= existing_flavors
[0]["uuid"]
1314 flavor_uuid
= str(uuid4())
1315 uuid_list
.append(flavor_uuid
)
1316 db_flavor
["uuid"] = flavor_uuid
1317 db_flavors
.append(db_flavor
)
1318 db_vm
["flavor_id"] = flavor_uuid
1320 # VNF affinity and antiaffinity
1321 for pg
in vnfd
.get("placement-groups").values():
1322 pg_name
= get_str(pg
, "name", 255)
1323 for vdu
in pg
.get("member-vdus").values():
1324 vdu_id
= get_str(vdu
, "member-vdu-ref", 255)
1325 if vdu_id
not in vdu_id2db_table_index
:
1326 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'placement-groups[{pg}]':"
1327 "'member-vdus':'{vdu}'. Reference to a non-existing vdu".format(
1328 vnf
=vnfd_id
, pg
=pg_name
, vdu
=vdu_id
),
1329 httperrors
.Bad_Request
)
1330 db_vms
[vdu_id2db_table_index
[vdu_id
]]["availability_zone"] = pg_name
1331 # TODO consider the case of isolation and not colocation
1332 # if pg.get("strategy") == "ISOLATION":
1334 # VNF mgmt configuration
1335 if vnfd
["mgmt-interface"].get("vdu-id"):
1336 mgmt_vdu_id
= get_str(vnfd
["mgmt-interface"], "vdu-id", 255)
1337 if mgmt_vdu_id
not in vdu_id2uuid
:
1338 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'vdu-id':"
1339 "'{vdu}'. Reference to a non-existing vdu".format(
1340 vnf
=vnfd_id
, vdu
=mgmt_vdu_id
),
1341 httperrors
.Bad_Request
)
1342 mgmt_access
["vm_id"] = vdu_id2uuid
[mgmt_vdu_id
]
1343 mgmt_access
["vdu-id"] = mgmt_vdu_id
1344 # if only one cp is defined by this VDU, mark this interface as of type "mgmt"
1345 if vdu_id2cp_name
.get(mgmt_vdu_id
):
1346 if cp_name2db_interface
[vdu_id2cp_name
[mgmt_vdu_id
]]:
1347 cp_name2db_interface
[vdu_id2cp_name
[mgmt_vdu_id
]]["type"] = "mgmt"
1349 if vnfd
["mgmt-interface"].get("ip-address"):
1350 mgmt_access
["ip-address"] = str(vnfd
["mgmt-interface"].get("ip-address"))
1351 if vnfd
["mgmt-interface"].get("cp"):
1352 if vnfd
["mgmt-interface"]["cp"] not in cp_name2iface_uuid
:
1353 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'cp'['{cp}']. "
1354 "Reference to a non-existing connection-point".format(
1355 vnf
=vnfd_id
, cp
=vnfd
["mgmt-interface"]["cp"]),
1356 httperrors
.Bad_Request
)
1357 mgmt_access
["vm_id"] = cp_name2vm_uuid
[vnfd
["mgmt-interface"]["cp"]]
1358 mgmt_access
["interface_id"] = cp_name2iface_uuid
[vnfd
["mgmt-interface"]["cp"]]
1359 mgmt_access
["vdu-id"] = cp_name2vdu_id
[vnfd
["mgmt-interface"]["cp"]]
1360 # mark this interface as of type mgmt
1361 if cp_name2db_interface
[vnfd
["mgmt-interface"]["cp"]]:
1362 cp_name2db_interface
[vnfd
["mgmt-interface"]["cp"]]["type"] = "mgmt"
1364 default_user
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1367 mgmt_access
["default_user"] = default_user
1369 required
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1372 mgmt_access
["required"] = required
1374 password_
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}),
1377 mgmt_access
["password"] = password_
1380 db_vnf
["mgmt_access"] = yaml
.safe_dump(mgmt_access
, default_flow_style
=True, width
=256)
1382 db_vnfs
.append(db_vnf
)
1386 {"images": db_images
},
1387 {"flavors": db_flavors
},
1388 {"ip_profiles": db_ip_profiles
},
1390 {"interfaces": db_interfaces
},
1393 logger
.debug("create_vnf Deployment done vnfDict: %s",
1394 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
1395 mydb
.new_rows(db_tables
, uuid_list
)
1396 return vnfd_uuid_list
1397 except NfvoException
:
1399 except Exception as e
:
1400 logger
.error("Exception {}".format(e
))
1401 raise # NfvoException("Exception {}".format(e), httperrors.Bad_Request)
1404 @deprecated("Use new_vnfd_v3")
1405 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
1406 global global_config
1408 # Step 1. Check the VNF descriptor
1409 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
1410 # Step 2. Check tenant exist
1412 if tenant_id
!= "any":
1413 check_tenant(mydb
, tenant_id
)
1414 if "tenant_id" in vnf_descriptor
["vnf"]:
1415 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1416 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1417 httperrors
.Unauthorized
)
1419 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1420 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1421 if global_config
["auto_push_VNF_to_VIMs"]:
1422 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1424 # Step 4. Review the descriptor and add missing fields
1425 #print vnf_descriptor
1426 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1427 vnf_name
= vnf_descriptor
['vnf']['name']
1428 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1429 if "physical" in vnf_descriptor
['vnf']:
1430 del vnf_descriptor
['vnf']['physical']
1431 #print vnf_descriptor
1433 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1434 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1435 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1437 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1438 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1439 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1441 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1442 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1444 VNFCitem
["name"] = vnfc
['name']
1445 VNFCitem
["availability_zone"] = vnfc
.get('availability_zone')
1446 VNFCitem
["description"] = vnfc
.get("description", 'VM {} of the VNF {}'.format(vnfc
['name'],vnf_name
))
1448 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1451 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1452 myflavorDict
["description"] = VNFCitem
["description"]
1453 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1454 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1455 myflavorDict
["disk"] = vnfc
.get("disk", 0)
1456 myflavorDict
["extended"] = {}
1458 devices
= vnfc
.get("devices")
1460 myflavorDict
["extended"]["devices"] = devices
1463 # 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
1464 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1466 # Previous code has been commented
1467 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1468 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1469 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1470 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1472 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1474 # print "Error creating flavor: unknown processor model. Rollback successful."
1475 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1477 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1478 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1480 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1481 myflavorDict
['extended']['numas'] = vnfc
['numas']
1485 # Step 6.2 New flavors are created in the VIM
1486 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1488 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1489 VNFCitem
["flavor_id"] = flavor_id
1490 VNFCDict
[vnfc
['name']] = VNFCitem
1492 logger
.debug("Creating new images in the VIM for each VNFC")
1493 # Step 6.3 New images are created in the VIM
1494 #For each VNFC, we must create the appropriate image.
1495 #This "for" loop might be integrated with the previous one
1496 #In case this integration is made, the VNFCDict might become a VNFClist.
1497 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1498 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1500 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1501 image_dict
['universal_name']=vnfc
.get('image name')
1502 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1503 image_dict
['location']=vnfc
.get('VNFC image')
1504 #image_dict['new_location']=vnfc.get('image location')
1505 image_dict
['checksum']=vnfc
.get('image checksum')
1506 image_metadata_dict
= vnfc
.get('image metadata', None)
1507 image_metadata_str
= None
1508 if image_metadata_dict
is not None:
1509 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1510 image_dict
['metadata']=image_metadata_str
1511 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1512 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1513 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1514 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1515 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1516 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1517 if vnfc
.get("boot-data"):
1518 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1521 # Step 7. Storing the VNF descriptor in the repository
1522 if "descriptor" not in vnf_descriptor
["vnf"]:
1523 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1525 # Step 8. Adding the VNF to the NFVO DB
1526 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1528 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1529 _
, message
= rollback(mydb
, vims
, rollback_list
)
1530 if isinstance(e
, db_base_Exception
):
1531 error_text
= "Exception at database"
1532 elif isinstance(e
, KeyError):
1533 error_text
= "KeyError exception "
1534 e
.http_code
= httperrors
.Internal_Server_Error
1536 error_text
= "Exception at VIM"
1537 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1538 #logger.error("start_scenario %s", error_text)
1539 raise NfvoException(error_text
, e
.http_code
)
1542 @deprecated("Use new_vnfd_v3")
1543 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
1544 global global_config
1546 # Step 1. Check the VNF descriptor
1547 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
1548 # Step 2. Check tenant exist
1550 if tenant_id
!= "any":
1551 check_tenant(mydb
, tenant_id
)
1552 if "tenant_id" in vnf_descriptor
["vnf"]:
1553 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1554 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1555 httperrors
.Unauthorized
)
1557 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1558 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1559 if global_config
["auto_push_VNF_to_VIMs"]:
1560 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1562 # Step 4. Review the descriptor and add missing fields
1563 #print vnf_descriptor
1564 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1565 vnf_name
= vnf_descriptor
['vnf']['name']
1566 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1567 if "physical" in vnf_descriptor
['vnf']:
1568 del vnf_descriptor
['vnf']['physical']
1569 #print vnf_descriptor
1571 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1572 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1573 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1575 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1576 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1577 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1579 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1580 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1582 VNFCitem
["name"] = vnfc
['name']
1583 VNFCitem
["description"] = vnfc
.get("description", 'VM {} of the VNF {}'.format(vnfc
['name'],vnf_name
))
1585 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1588 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1589 myflavorDict
["description"] = VNFCitem
["description"]
1590 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1591 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1592 myflavorDict
["disk"] = vnfc
.get("disk", 0)
1593 myflavorDict
["extended"] = {}
1595 devices
= vnfc
.get("devices")
1597 myflavorDict
["extended"]["devices"] = devices
1600 # 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
1601 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1603 # Previous code has been commented
1604 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1605 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1606 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1607 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1609 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1611 # print "Error creating flavor: unknown processor model. Rollback successful."
1612 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1614 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1615 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1617 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1618 myflavorDict
['extended']['numas'] = vnfc
['numas']
1622 # Step 6.2 New flavors are created in the VIM
1623 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1625 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1626 VNFCitem
["flavor_id"] = flavor_id
1627 VNFCDict
[vnfc
['name']] = VNFCitem
1629 logger
.debug("Creating new images in the VIM for each VNFC")
1630 # Step 6.3 New images are created in the VIM
1631 #For each VNFC, we must create the appropriate image.
1632 #This "for" loop might be integrated with the previous one
1633 #In case this integration is made, the VNFCDict might become a VNFClist.
1634 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1635 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1637 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1638 image_dict
['universal_name']=vnfc
.get('image name')
1639 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1640 image_dict
['location']=vnfc
.get('VNFC image')
1641 #image_dict['new_location']=vnfc.get('image location')
1642 image_dict
['checksum']=vnfc
.get('image checksum')
1643 image_metadata_dict
= vnfc
.get('image metadata', None)
1644 image_metadata_str
= None
1645 if image_metadata_dict
is not None:
1646 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1647 image_dict
['metadata']=image_metadata_str
1648 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1649 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1650 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1651 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1652 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1653 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1654 if vnfc
.get("boot-data"):
1655 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1657 # Step 7. Storing the VNF descriptor in the repository
1658 if "descriptor" not in vnf_descriptor
["vnf"]:
1659 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1661 # Step 8. Adding the VNF to the NFVO DB
1662 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1664 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1665 _
, message
= rollback(mydb
, vims
, rollback_list
)
1666 if isinstance(e
, db_base_Exception
):
1667 error_text
= "Exception at database"
1668 elif isinstance(e
, KeyError):
1669 error_text
= "KeyError exception "
1670 e
.http_code
= httperrors
.Internal_Server_Error
1672 error_text
= "Exception at VIM"
1673 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1674 #logger.error("start_scenario %s", error_text)
1675 raise NfvoException(error_text
, e
.http_code
)
1678 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
1679 #check valid tenant_id
1680 check_tenant(mydb
, tenant_id
)
1683 if tenant_id
!= "any":
1684 where_or
["tenant_id"] = tenant_id
1685 where_or
["public"] = True
1686 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1688 vnf_id
= vnf
["uuid"]
1689 filter_keys
= ('uuid', 'name', 'description', 'public', "tenant_id", "osm_id", "created_at")
1690 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.items() if k
in filter_keys
)
1691 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
1692 data
={'vnf' : filtered_content
}
1694 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
1695 SELECT
=('vms.uuid as uuid', 'vms.osm_id as osm_id', 'vms.name as name', 'vms.description as description',
1697 WHERE
={'vnfs.uuid': vnf_id
} )
1698 if len(content
) != 0:
1699 #raise NfvoException("vnf '{}' not found".format(vnf_id), httperrors.Not_Found)
1700 # change boot_data into boot-data
1702 if vm
.get("boot_data"):
1703 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
1706 data
['vnf']['VNFC'] = content
1707 #TODO: GET all the information from a VNFC and include it in the output.
1710 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
1711 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
1712 WHERE
={'vnfs.uuid': vnf_id
} )
1713 data
['vnf']['nets'] = content
1715 #GET ip-profile for each net
1716 for net
in data
['vnf']['nets']:
1717 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1718 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1719 WHERE
={'net_id': net
["uuid"]} )
1720 if len(ipprofiles
)==1:
1721 net
["ip_profile"] = ipprofiles
[0]
1722 elif len(ipprofiles
)>1:
1723 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), httperrors
.Bad_Request
)
1726 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1728 #GET External Interfaces
1729 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1730 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1731 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1732 WHERE
={'vnfs.uuid': vnf_id
, 'interfaces.external_name<>': None} )
1734 data
['vnf']['external-connections'] = content
1739 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1740 # Check tenant exist
1741 if tenant_id
!= "any":
1742 check_tenant(mydb
, tenant_id
)
1743 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1744 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1748 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1750 if tenant_id
!= "any":
1751 where_or
["tenant_id"] = tenant_id
1752 where_or
["public"] = True
1753 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1754 vnf_id
= vnf
["uuid"]
1756 # "Getting the list of flavors and tenants of the VNF"
1757 flavorList
= get_flavorlist(mydb
, vnf_id
)
1758 if len(flavorList
)==0:
1759 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1761 imageList
= get_imagelist(mydb
, vnf_id
)
1762 if len(imageList
)==0:
1763 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1765 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1767 raise NfvoException("vnf '{}' not found".format(vnf_id
), httperrors
.Not_Found
)
1770 for flavor
in flavorList
:
1771 #check if flavor is used by other vnf
1773 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1775 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1777 #flavor not used, must be deleted
1779 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id': flavor
})
1780 for flavor_vim
in c
:
1781 if not flavor_vim
['created']: # skip this flavor because not created by openmano
1785 for vim
in vims
.values():
1786 if vim
["config"]["datacenter_tenant_id"] == flavor_vim
["datacenter_vim_id"]:
1792 myvim
.delete_flavor(flavor_vim
["vim_id"])
1793 except vimconn
.vimconnNotFoundException
:
1794 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"],
1795 flavor_vim
["datacenter_vim_id"] )
1796 except vimconn
.vimconnException
as e
:
1797 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1798 flavor_vim
["vim_id"], flavor_vim
["datacenter_vim_id"], type(e
).__name
__, str(e
))
1799 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"],
1800 flavor_vim
["datacenter_vim_id"]))
1801 # delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1802 mydb
.delete_row_by_id('flavors', flavor
)
1803 except db_base_Exception
as e
:
1804 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1805 undeletedItems
.append("flavor {}".format(flavor
))
1808 for image
in imageList
:
1810 #check if image is used by other vnf
1811 c
= mydb
.get_rows(FROM
='vms', WHERE
=[{'image_id': image
}, {'image_list LIKE ': '%' + image
+ '%'}])
1813 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1815 #image not used, must be deleted
1817 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1819 if image_vim
["datacenter_vim_id"] not in vims
: # TODO change to datacenter_tenant_id
1821 if image_vim
['created']=='false': #skip this image because not created by openmano
1823 myvim
=vims
[ image_vim
["datacenter_id"] ]
1825 myvim
.delete_image(image_vim
["vim_id"])
1826 except vimconn
.vimconnNotFoundException
as e
:
1827 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1828 except vimconn
.vimconnException
as e
:
1829 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1830 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1831 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1832 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1833 mydb
.delete_row_by_id('images', image
)
1834 except db_base_Exception
as e
:
1835 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1836 undeletedItems
.append("image {}".format(image
))
1838 return vnf_id
+ " " + vnf
["name"]
1840 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1843 @deprecated("Not used")
1844 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1845 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1849 return -httperrors
.Not_Found
, "datacenter '{}' not found".format(datacenter_name
)
1850 myvim
= next(iter(vims
.values()))
1851 result
,servers
= myvim
.get_hosts_info()
1853 return result
, servers
1854 topology
= {'name':myvim
['name'] , 'servers': servers
}
1855 return result
, topology
1858 def get_hosts(mydb
, nfvo_tenant_id
):
1859 vims
= get_vim(mydb
, nfvo_tenant_id
)
1861 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), httperrors
.Not_Found
)
1863 #print "nfvo.datacenter_action() error. Several datacenters found"
1864 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
1865 myvim
= next(iter(vims
.values()))
1867 hosts
= myvim
.get_hosts()
1868 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1870 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1872 server
={'name':host
['name'], 'vms':[]}
1873 for vm
in host
['instances']:
1874 #get internal name and model
1876 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1877 WHERE
={'vim_vm_id':vm
['id']} )
1879 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1881 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1883 except db_base_Exception
as e
:
1884 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1885 datacenter
['Datacenters'][0]['servers'].append(server
)
1886 #return -400, "en construccion"
1888 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1890 except vimconn
.vimconnException
as e
:
1891 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1894 @deprecated("Use new_nsd_v3")
1895 def new_scenario(mydb
, tenant_id
, topo
):
1897 # result, vims = get_vim(mydb, tenant_id)
1899 # return result, vims
1901 if tenant_id
!= "any":
1902 check_tenant(mydb
, tenant_id
)
1903 if "tenant_id" in topo
:
1904 if topo
["tenant_id"] != tenant_id
:
1905 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1906 httperrors
.Unauthorized
)
1910 #1.1: get VNFs and external_networks (other_nets).
1912 other_nets
={} #external_networks, bridge_networks and data_networkds
1913 nodes
= topo
['topology']['nodes']
1914 for k
in nodes
.keys():
1915 if nodes
[k
]['type'] == 'VNF':
1917 vnfs
[k
]['ifaces'] = {}
1918 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1919 other_nets
[k
] = nodes
[k
]
1920 other_nets
[k
]['external']=True
1921 elif nodes
[k
]['type'] == 'network':
1922 other_nets
[k
] = nodes
[k
]
1923 other_nets
[k
]['external']=False
1926 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1927 for name
,vnf
in vnfs
.items():
1928 where
= {"OR": {"tenant_id": tenant_id
, 'public': "true"}}
1930 error_pos
= "'topology':'nodes':'" + name
+ "'"
1932 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1933 where
['uuid'] = vnf
['vnf_id']
1934 if 'VNF model' in vnf
:
1935 error_text
+= " 'VNF model' " + vnf
['VNF model']
1936 where
['name'] = vnf
['VNF model']
1938 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, httperrors
.Bad_Request
)
1940 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1944 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, httperrors
.Not_Found
)
1946 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", httperrors
.Conflict
)
1947 vnf
['uuid']=vnf_db
[0]['uuid']
1948 vnf
['description']=vnf_db
[0]['description']
1949 #get external interfaces
1950 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1951 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1952 WHERE
={'vnfs.uuid':vnf
['uuid'], 'external_name<>': None} )
1953 for ext_iface
in ext_ifaces
:
1954 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1956 #1.4 get list of connections
1957 conections
= topo
['topology']['connections']
1958 conections_list
= []
1959 conections_list_name
= []
1960 for k
in conections
.keys():
1961 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1962 ifaces_list
= conections
[k
]['nodes'].items()
1963 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1965 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1966 for k2
in conection_pair_list
:
1969 con_type
= conections
[k
].get("type", "link")
1970 if con_type
!= "link":
1972 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), httperrors
.Bad_Request
)
1973 other_nets
[k
] = {'external': False}
1974 if conections
[k
].get("graph"):
1975 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1976 ifaces_list
.append( (k
, None) )
1979 if con_type
== "external_network":
1980 other_nets
[k
]['external'] = True
1981 if conections
[k
].get("model"):
1982 other_nets
[k
]["model"] = conections
[k
]["model"]
1984 other_nets
[k
]["model"] = k
1985 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1986 other_nets
[k
]["model"] = con_type
1988 conections_list_name
.append(k
)
1989 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)
1990 #print set(ifaces_list)
1991 #check valid VNF and iface names
1992 for iface
in ifaces_list
:
1993 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1994 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1995 str(k
), iface
[0]), httperrors
.Not_Found
)
1996 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1997 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1998 str(k
), iface
[0], iface
[1]), httperrors
.Not_Found
)
2000 #1.5 unify connections from the pair list to a consolidated list
2002 while index
< len(conections_list
):
2004 while index2
< len(conections_list
):
2005 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
2006 conections_list
[index
] |
= conections_list
[index2
]
2007 del conections_list
[index2
]
2008 del conections_list_name
[index2
]
2011 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
2013 #for k in conections_list:
2018 #1.6 Delete non external nets
2019 # for k in other_nets.keys():
2020 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
2021 # for con in conections_list:
2023 # for index in range(0,len(con)):
2024 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
2025 # for index in delete_indexes:
2028 #1.7: Check external_ports are present at database table datacenter_nets
2029 for k
,net
in other_nets
.items():
2030 error_pos
= "'topology':'nodes':'" + k
+ "'"
2031 if net
['external']==False:
2032 if 'name' not in net
:
2034 if 'model' not in net
:
2035 raise NfvoException("needed a 'model' at " + error_pos
, httperrors
.Bad_Request
)
2036 if net
['model']=='bridge_net':
2037 net
['type']='bridge';
2038 elif net
['model']=='dataplane_net':
2041 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, httperrors
.Not_Found
)
2043 #IF we do not want to check that external network exist at datacenter
2048 # if 'net_id' in net:
2049 # error_text += " 'net_id' " + net['net_id']
2050 # WHERE_['uuid'] = net['net_id']
2051 # if 'model' in net:
2052 # error_text += " 'model' " + net['model']
2053 # WHERE_['name'] = net['model']
2054 # if len(WHERE_) == 0:
2055 # return -httperrors.Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
2056 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
2057 # FROM='datacenter_nets', WHERE=WHERE_ )
2059 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
2061 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
2062 # return -httperrors.Bad_Request, "unknown " +error_text+ " at " + error_pos
2064 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
2065 # return -httperrors.Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
2066 # other_nets[k].update(net_db[0])
2069 net_nb
=0 #Number of nets
2070 for con
in conections_list
:
2071 #check if this is connected to a external net
2075 for index
in range(0,len(con
)):
2076 #check if this is connected to a external net
2077 for net_key
in other_nets
.keys():
2078 if con
[index
][0]==net_key
:
2079 if other_net_index
>=0:
2080 error_text
= "There is some interface connected both to net '{}' and net '{}'".format(
2081 con
[other_net_index
][0], net_key
)
2082 #print "nfvo.new_scenario " + error_text
2083 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2085 other_net_index
= index
2086 net_target
= net_key
2088 #print "other_net_index", other_net_index
2090 if other_net_index
>=0:
2091 del con
[other_net_index
]
2092 #IF we do not want to check that external network exist at datacenter
2093 if other_nets
[net_target
]['external'] :
2094 if "name" not in other_nets
[net_target
]:
2095 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
2096 if other_nets
[net_target
]["type"] == "external_network":
2097 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
2098 other_nets
[net_target
]["type"] = "data"
2100 other_nets
[net_target
]["type"] = "bridge"
2102 # if other_nets[net_target]['external'] :
2103 # 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
2104 # if type_=='data' and other_nets[net_target]['type']=="ptp":
2105 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
2106 # print "nfvo.new_scenario " + error_text
2107 # return -httperrors.Bad_Request, error_text
2110 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
2113 net_type_bridge
=False
2115 net_target
= "__-__net"+str(net_nb
)
2116 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
2117 'description':"net-{} in scenario {}".format(net_nb
,topo
['name']),
2120 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
2121 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
2122 if iface_type
=='mgmt' or iface_type
=='bridge':
2123 net_type_bridge
= True
2125 net_type_data
= True
2126 if net_type_bridge
and net_type_data
:
2127 error_text
= "Error connection interfaces of bridge type with data type. Firs node {}, iface {}".format(iface
[0], iface
[1])
2128 #print "nfvo.new_scenario " + error_text
2129 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2130 elif net_type_bridge
:
2133 type_
='data' if len(con
)>2 else 'ptp'
2134 net_list
[net_target
]['type'] = type_
2137 error_text
= "Error connection node {} : {} does not match any VNF or interface".format(iface
[0], iface
[1])
2138 #print "nfvo.new_scenario " + error_text
2140 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2142 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
2143 #1.8.1 obtain management net
2144 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
2145 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
2146 #1.8.2 check all interfaces from all vnfs
2148 add_mgmt_net
= False
2149 for vnf
in vnfs
.values():
2150 for iface
in vnf
['ifaces'].values():
2151 if iface
['type']=='mgmt' and 'net_key' not in iface
:
2152 #iface not connected
2153 iface
['net_key'] = 'mgmt'
2155 if add_mgmt_net
and 'mgmt' not in net_list
:
2156 net_list
['mgmt']=mgmt_net
[0]
2157 net_list
['mgmt']['external']=True
2158 net_list
['mgmt']['graph']={'visible':False}
2160 net_list
.update(other_nets
)
2162 #print 'net_list', net_list
2167 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
2168 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
2169 'tenant_id':tenant_id
, 'name':topo
['name'],
2170 'description':topo
.get('description',topo
['name']),
2171 'public': topo
.get('public', False)
2177 @deprecated("Use new_nsd_v3")
2178 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
2179 """ This creates a new scenario for version 0.2 and 0.3"""
2180 scenario
= scenario_dict
["scenario"]
2181 if tenant_id
!= "any":
2182 check_tenant(mydb
, tenant_id
)
2183 if "tenant_id" in scenario
:
2184 if scenario
["tenant_id"] != tenant_id
:
2185 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
2186 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
2187 scenario
["tenant_id"], tenant_id
), httperrors
.Unauthorized
)
2191 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
2192 for name
,vnf
in scenario
["vnfs"].items():
2193 where
= {"OR": {"tenant_id": tenant_id
, 'public': "true"}}
2195 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
2197 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
2198 where
['uuid'] = vnf
['vnf_id']
2199 if 'vnf_name' in vnf
:
2200 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
2201 where
['name'] = vnf
['vnf_name']
2203 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, httperrors
.Bad_Request
)
2204 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
2207 if len(vnf_db
) == 0:
2208 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, httperrors
.Not_Found
)
2209 elif len(vnf_db
) > 1:
2210 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", httperrors
.Conflict
)
2211 vnf
['uuid'] = vnf_db
[0]['uuid']
2212 vnf
['description'] = vnf_db
[0]['description']
2214 # get external interfaces
2215 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
2216 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
2217 WHERE
={'vnfs.uuid':vnf
['uuid'], 'external_name<>': None} )
2218 for ext_iface
in ext_ifaces
:
2219 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
2220 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
2222 # 2: Insert net_key and ip_address at every vnf interface
2223 for net_name
, net
in scenario
["networks"].items():
2224 net_type_bridge
= False
2225 net_type_data
= False
2226 for iface_dict
in net
["interfaces"]:
2227 if version
== "0.2":
2228 temp_dict
= iface_dict
2230 elif version
== "0.3":
2231 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
2232 ip_address
= iface_dict
.get('ip_address', None)
2233 for vnf
, iface
in temp_dict
.items():
2234 if vnf
not in scenario
["vnfs"]:
2235 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
2237 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2238 raise NfvoException(error_text
, httperrors
.Not_Found
)
2239 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
2240 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
2241 .format(net_name
, iface
)
2242 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2243 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2244 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
2245 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
2246 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
2247 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2248 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2249 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
2250 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
2251 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
2252 if iface_type
== 'mgmt' or iface_type
== 'bridge':
2253 net_type_bridge
= True
2255 net_type_data
= True
2257 if net_type_bridge
and net_type_data
:
2258 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
2260 # logger.debug("nfvo.new_scenario " + error_text)
2261 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2262 elif net_type_bridge
:
2265 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
2267 if net
.get("implementation"): # for v0.3
2268 if type_
== "bridge" and net
["implementation"] == "underlay":
2269 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
2270 "'network':'{}'".format(net_name
)
2271 # logger.debug(error_text)
2272 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2273 elif type_
!= "bridge" and net
["implementation"] == "overlay":
2274 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
2275 "'network':'{}'".format(net_name
)
2276 # logger.debug(error_text)
2277 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2278 net
.pop("implementation")
2279 if "type" in net
and version
== "0.3": # for v0.3
2280 if type_
== "data" and net
["type"] == "e-line":
2281 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
2282 "'e-line' at 'network':'{}'".format(net_name
)
2283 # logger.debug(error_text)
2284 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2285 elif type_
== "ptp" and net
["type"] == "e-lan":
2289 net
['name'] = net_name
2290 net
['external'] = net
.get('external', False)
2292 # 3: insert at database
2293 scenario
["nets"] = scenario
["networks"]
2294 scenario
['tenant_id'] = tenant_id
2295 scenario_id
= mydb
.new_scenario(scenario
)
2299 def new_nsd_v3(mydb
, tenant_id
, nsd_descriptor
):
2301 Parses an OSM IM nsd_catalog and insert at DB
2304 :param nsd_descriptor:
2305 :return: The list of created NSD ids
2308 mynsd
= nsd_catalog
.nsd()
2310 pybindJSONDecoder
.load_ietf_json(nsd_descriptor
, None, None, obj
=mynsd
, skip_unknown
=True)
2311 except Exception as e
:
2312 raise NfvoException("Error. Invalid NS descriptor format: " + str(e
), httperrors
.Bad_Request
)
2316 db_sce_interfaces
= []
2319 db_sce_rsp_hops
= []
2320 db_sce_classifiers
= []
2321 db_sce_classifier_matches
= []
2323 db_ip_profiles_index
= 0
2326 for nsd_yang
in mynsd
.nsd_catalog
.nsd
.values():
2327 nsd
= nsd_yang
.get()
2330 scenario_uuid
= str(uuid4())
2331 uuid_list
.append(scenario_uuid
)
2332 nsd_uuid_list
.append(scenario_uuid
)
2334 "uuid": scenario_uuid
,
2335 "osm_id": get_str(nsd
, "id", 255),
2336 "name": get_str(nsd
, "name", 255),
2337 "description": get_str(nsd
, "description", 255),
2338 "tenant_id": tenant_id
,
2339 "vendor": get_str(nsd
, "vendor", 255),
2340 "short_name": get_str(nsd
, "short-name", 255),
2341 "descriptor": str(nsd_descriptor
)[:60000],
2343 db_scenarios
.append(db_scenario
)
2345 # table sce_vnfs (constituent-vnfd)
2346 vnf_index2scevnf_uuid
= {}
2347 vnf_index2vnf_uuid
= {}
2348 for vnf
in nsd
.get("constituent-vnfd").values():
2349 existing_vnf
= mydb
.get_rows(FROM
="vnfs", WHERE
={'osm_id': str(vnf
["vnfd-id-ref"])[:255],
2350 'tenant_id': tenant_id
})
2351 if not existing_vnf
:
2352 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'constituent-vnfd':'vnfd-id-ref':"
2353 "'{}'. Reference to a non-existing VNFD in the catalog".format(
2354 str(nsd
["id"]), str(vnf
["vnfd-id-ref"])[:255]),
2355 httperrors
.Bad_Request
)
2356 sce_vnf_uuid
= str(uuid4())
2357 uuid_list
.append(sce_vnf_uuid
)
2359 "uuid": sce_vnf_uuid
,
2360 "scenario_id": scenario_uuid
,
2361 # "name": get_str(vnf, "member-vnf-index", 255),
2362 "name": existing_vnf
[0]["name"][:200] + "." + get_str(vnf
, "member-vnf-index", 50),
2363 "vnf_id": existing_vnf
[0]["uuid"],
2364 "member_vnf_index": str(vnf
["member-vnf-index"]),
2365 # TODO 'start-by-default': True
2367 vnf_index2scevnf_uuid
[str(vnf
['member-vnf-index'])] = sce_vnf_uuid
2368 vnf_index2vnf_uuid
[str(vnf
['member-vnf-index'])] = existing_vnf
[0]["uuid"]
2369 db_sce_vnfs
.append(db_sce_vnf
)
2371 # table ip_profiles (ip-profiles)
2372 ip_profile_name2db_table_index
= {}
2373 for ip_profile
in nsd
.get("ip-profiles").values():
2375 "ip_version": str(ip_profile
["ip-profile-params"].get("ip-version", "ipv4")),
2376 "subnet_address": str(ip_profile
["ip-profile-params"].get("subnet-address")),
2377 "gateway_address": str(ip_profile
["ip-profile-params"].get("gateway-address")),
2378 "dhcp_enabled": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("enabled", True)),
2379 "dhcp_start_address": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("start-address")),
2380 "dhcp_count": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("count")),
2383 for dns
in ip_profile
["ip-profile-params"]["dns-server"].values():
2384 dns_list
.append(str(dns
.get("address")))
2385 db_ip_profile
["dns_address"] = ";".join(dns_list
)
2386 if ip_profile
["ip-profile-params"].get('security-group'):
2387 db_ip_profile
["security_group"] = ip_profile
["ip-profile-params"]['security-group']
2388 ip_profile_name2db_table_index
[str(ip_profile
["name"])] = db_ip_profiles_index
2389 db_ip_profiles_index
+= 1
2390 db_ip_profiles
.append(db_ip_profile
)
2392 # table sce_nets (internal-vld)
2393 for vld
in nsd
.get("vld").values():
2394 sce_net_uuid
= str(uuid4())
2395 uuid_list
.append(sce_net_uuid
)
2397 "uuid": sce_net_uuid
,
2398 "name": get_str(vld
, "name", 255),
2399 "scenario_id": scenario_uuid
,
2401 "multipoint": not vld
.get("type") == "ELINE",
2402 "osm_id": get_str(vld
, "id", 255),
2404 "description": get_str(vld
, "description", 255),
2406 # guess type of network
2407 if vld
.get("mgmt-network"):
2408 db_sce_net
["type"] = "bridge"
2409 db_sce_net
["external"] = True
2410 elif vld
.get("provider-network").get("overlay-type") == "VLAN":
2411 db_sce_net
["type"] = "data"
2413 # later on it will be fixed to bridge or data depending on the type of interfaces attached to it
2414 db_sce_net
["type"] = None
2415 db_sce_nets
.append(db_sce_net
)
2417 # ip-profile, link db_ip_profile with db_sce_net
2418 if vld
.get("ip-profile-ref"):
2419 ip_profile_name
= vld
.get("ip-profile-ref")
2420 if ip_profile_name
not in ip_profile_name2db_table_index
:
2421 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'ip-profile-ref':'{}'."
2422 " Reference to a non-existing 'ip_profiles'".format(
2423 str(nsd
["id"]), str(vld
["id"]), str(vld
["ip-profile-ref"])),
2424 httperrors
.Bad_Request
)
2425 db_ip_profiles
[ip_profile_name2db_table_index
[ip_profile_name
]]["sce_net_id"] = sce_net_uuid
2426 elif vld
.get("vim-network-name"):
2427 db_sce_net
["vim_network_name"] = get_str(vld
, "vim-network-name", 255)
2429 # table sce_interfaces (vld:vnfd-connection-point-ref)
2430 for iface
in vld
.get("vnfd-connection-point-ref").values():
2431 vnf_index
= str(iface
['member-vnf-index-ref'])
2432 # check correct parameters
2433 if vnf_index
not in vnf_index2vnf_uuid
:
2434 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2435 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2436 "'nsd':'constituent-vnfd'".format(
2437 str(nsd
["id"]), str(vld
["id"]), str(iface
["member-vnf-index-ref"])),
2438 httperrors
.Bad_Request
)
2440 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid', 'i.type as iface_type'),
2441 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2442 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2443 'external_name': get_str(iface
, "vnfd-connection-point-ref",
2445 if not existing_ifaces
:
2446 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2447 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2448 "connection-point name at VNFD '{}'".format(
2449 str(nsd
["id"]), str(vld
["id"]), str(iface
["vnfd-connection-point-ref"]),
2450 str(iface
.get("vnfd-id-ref"))[:255]),
2451 httperrors
.Bad_Request
)
2452 interface_uuid
= existing_ifaces
[0]["uuid"]
2453 if existing_ifaces
[0]["iface_type"] == "data":
2454 db_sce_net
["type"] = "data"
2455 sce_interface_uuid
= str(uuid4())
2456 uuid_list
.append(sce_net_uuid
)
2457 iface_ip_address
= None
2458 if iface
.get("ip-address"):
2459 iface_ip_address
= str(iface
.get("ip-address"))
2460 db_sce_interface
= {
2461 "uuid": sce_interface_uuid
,
2462 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2463 "sce_net_id": sce_net_uuid
,
2464 "interface_id": interface_uuid
,
2465 "ip_address": iface_ip_address
,
2467 db_sce_interfaces
.append(db_sce_interface
)
2468 if not db_sce_net
["type"]:
2469 db_sce_net
["type"] = "bridge"
2471 # table sce_vnffgs (vnffgd)
2472 for vnffg
in nsd
.get("vnffgd").values():
2473 sce_vnffg_uuid
= str(uuid4())
2474 uuid_list
.append(sce_vnffg_uuid
)
2476 "uuid": sce_vnffg_uuid
,
2477 "name": get_str(vnffg
, "name", 255),
2478 "scenario_id": scenario_uuid
,
2479 "vendor": get_str(vnffg
, "vendor", 255),
2480 "description": get_str(vld
, "description", 255),
2482 db_sce_vnffgs
.append(db_sce_vnffg
)
2485 for rsp
in vnffg
.get("rsp").values():
2486 sce_rsp_uuid
= str(uuid4())
2487 uuid_list
.append(sce_rsp_uuid
)
2489 "uuid": sce_rsp_uuid
,
2490 "name": get_str(rsp
, "name", 255),
2491 "sce_vnffg_id": sce_vnffg_uuid
,
2492 "id": get_str(rsp
, "id", 255), # only useful to link with classifiers; will be removed later in the code
2494 db_sce_rsps
.append(db_sce_rsp
)
2495 for iface
in rsp
.get("vnfd-connection-point-ref").values():
2496 vnf_index
= str(iface
['member-vnf-index-ref'])
2497 if_order
= int(iface
['order'])
2498 # check correct parameters
2499 if vnf_index
not in vnf_index2vnf_uuid
:
2500 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2501 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2502 "'nsd':'constituent-vnfd'".format(
2503 str(nsd
["id"]), str(rsp
["id"]), str(iface
["member-vnf-index-ref"])),
2504 httperrors
.Bad_Request
)
2506 ingress_existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2507 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2509 'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2510 'external_name': get_str(iface
, "vnfd-ingress-connection-point-ref",
2512 if not ingress_existing_ifaces
:
2513 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2514 "-ref':'vnfd-ingress-connection-point-ref':'{}'. Reference to a non-existing "
2515 "connection-point name at VNFD '{}'".format(
2516 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-ingress-connection-point-ref"]),
2517 str(iface
.get("vnfd-id-ref"))[:255]), httperrors
.Bad_Request
)
2519 egress_existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2520 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2522 'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2523 'external_name': get_str(iface
, "vnfd-egress-connection-point-ref",
2525 if not egress_existing_ifaces
:
2526 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2527 "-ref':'vnfd-egress-connection-point-ref':'{}'. Reference to a non-existing "
2528 "connection-point name at VNFD '{}'".format(
2529 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-egress-connection-point-ref"]),
2530 str(iface
.get("vnfd-id-ref"))[:255]), HTTP_Bad_Request
)
2532 ingress_interface_uuid
= ingress_existing_ifaces
[0]["uuid"]
2533 egress_interface_uuid
= egress_existing_ifaces
[0]["uuid"]
2534 sce_rsp_hop_uuid
= str(uuid4())
2535 uuid_list
.append(sce_rsp_hop_uuid
)
2537 "uuid": sce_rsp_hop_uuid
,
2538 "if_order": if_order
,
2539 "ingress_interface_id": ingress_interface_uuid
,
2540 "egress_interface_id": egress_interface_uuid
,
2541 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2542 "sce_rsp_id": sce_rsp_uuid
,
2544 db_sce_rsp_hops
.append(db_sce_rsp_hop
)
2546 # deal with classifiers
2547 for classifier
in vnffg
.get("classifier").values():
2548 sce_classifier_uuid
= str(uuid4())
2549 uuid_list
.append(sce_classifier_uuid
)
2552 vnf_index
= str(classifier
['member-vnf-index-ref'])
2553 if vnf_index
not in vnf_index2vnf_uuid
:
2554 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'classifier[{}]':'vnfd-connection-point"
2555 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2556 "'nsd':'constituent-vnfd'".format(
2557 str(nsd
["id"]), str(classifier
["id"]), str(classifier
["member-vnf-index-ref"])),
2558 httperrors
.Bad_Request
)
2559 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2560 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2561 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2562 'external_name': get_str(classifier
, "vnfd-connection-point-ref",
2564 if not existing_ifaces
:
2565 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2566 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2567 "connection-point name at VNFD '{}'".format(
2568 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-connection-point-ref"]),
2569 str(iface
.get("vnfd-id-ref"))[:255]),
2570 httperrors
.Bad_Request
)
2571 interface_uuid
= existing_ifaces
[0]["uuid"]
2573 db_sce_classifier
= {
2574 "uuid": sce_classifier_uuid
,
2575 "name": get_str(classifier
, "name", 255),
2576 "sce_vnffg_id": sce_vnffg_uuid
,
2577 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2578 "interface_id": interface_uuid
,
2580 rsp_id
= get_str(classifier
, "rsp-id-ref", 255)
2581 rsp
= next((item
for item
in db_sce_rsps
if item
["id"] == rsp_id
), None)
2582 db_sce_classifier
["sce_rsp_id"] = rsp
["uuid"]
2583 db_sce_classifiers
.append(db_sce_classifier
)
2585 for match
in classifier
.get("match-attributes").values():
2586 sce_classifier_match_uuid
= str(uuid4())
2587 uuid_list
.append(sce_classifier_match_uuid
)
2588 db_sce_classifier_match
= {
2589 "uuid": sce_classifier_match_uuid
,
2590 "ip_proto": get_str(match
, "ip-proto", 2),
2591 "source_ip": get_str(match
, "source-ip-address", 16),
2592 "destination_ip": get_str(match
, "destination-ip-address", 16),
2593 "source_port": get_str(match
, "source-port", 5),
2594 "destination_port": get_str(match
, "destination-port", 5),
2595 "sce_classifier_id": sce_classifier_uuid
,
2597 db_sce_classifier_matches
.append(db_sce_classifier_match
)
2600 # remove unneeded id's in sce_rsps
2601 for rsp
in db_sce_rsps
:
2605 {"scenarios": db_scenarios
},
2606 {"sce_nets": db_sce_nets
},
2607 {"ip_profiles": db_ip_profiles
},
2608 {"sce_vnfs": db_sce_vnfs
},
2609 {"sce_interfaces": db_sce_interfaces
},
2610 {"sce_vnffgs": db_sce_vnffgs
},
2611 {"sce_rsps": db_sce_rsps
},
2612 {"sce_rsp_hops": db_sce_rsp_hops
},
2613 {"sce_classifiers": db_sce_classifiers
},
2614 {"sce_classifier_matches": db_sce_classifier_matches
},
2617 logger
.debug("new_nsd_v3 done: %s",
2618 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
2619 mydb
.new_rows(db_tables
, uuid_list
)
2620 return nsd_uuid_list
2621 except NfvoException
:
2623 except Exception as e
:
2624 logger
.error("Exception {}".format(e
))
2625 raise # NfvoException("Exception {}".format(e), httperrors.Bad_Request)
2628 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
2629 data
["uuid"] = scenario_id
2630 data
["tenant_id"] = tenant_id
2631 c
= mydb
.edit_scenario( data
)
2635 @deprecated("Use create_instance")
2636 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
2637 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2638 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
2639 vims
= {datacenter_id
: myvim
}
2640 myvim_tenant
= myvim
['tenant_id']
2641 datacenter_name
= myvim
['name']
2645 #print "Checking that the scenario_id exists and getting the scenario dictionary"
2646 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
=datacenter_id
)
2647 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
2648 scenarioDict
['datacenter_id'] = datacenter_id
2649 #print '================scenarioDict======================='
2650 #print json.dumps(scenarioDict, indent=4)
2651 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
2653 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
2654 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2656 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
2657 auxNetDict
['scenario'] = {}
2659 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
2660 for sce_net
in scenarioDict
['nets']:
2661 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
2663 myNetName
= "{}.{}".format(instance_scenario_name
, sce_net
['name'])
2664 myNetName
= myNetName
[0:255] #limit length
2665 myNetType
= sce_net
['type']
2667 myNetDict
["name"] = myNetName
2668 myNetDict
["type"] = myNetType
2669 myNetDict
["tenant_id"] = myvim_tenant
2670 myNetIPProfile
= sce_net
.get('ip_profile', None)
2672 #We should use the dictionary as input parameter for new_network
2674 if not sce_net
["external"]:
2675 network_id
, _
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2676 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
2677 sce_net
['vim_id'] = network_id
2678 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
2679 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2680 sce_net
["created"] = True
2682 if sce_net
['vim_id'] == None:
2683 error_text
= "Error, datacenter '{}' does not have external network '{}'.".format(
2684 datacenter_name
, sce_net
['name'])
2685 _
, message
= rollback(mydb
, vims
, rollbackList
)
2686 logger
.error("nfvo.start_scenario: %s", error_text
)
2687 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2688 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
2689 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
2691 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
2692 #For each vnf net, we create it and we add it to instanceNetlist.
2694 for sce_vnf
in scenarioDict
['vnfs']:
2695 for net
in sce_vnf
['nets']:
2696 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
2698 myNetName
= "{}.{}".format(instance_scenario_name
,net
['name'])
2699 myNetName
= myNetName
[0:255] #limit length
2700 myNetType
= net
['type']
2702 myNetDict
["name"] = myNetName
2703 myNetDict
["type"] = myNetType
2704 myNetDict
["tenant_id"] = myvim_tenant
2705 myNetIPProfile
= net
.get('ip_profile', None)
2708 #We should use the dictionary as input parameter for new_network
2709 network_id
, _
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2710 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
2711 net
['vim_id'] = network_id
2712 if sce_vnf
['uuid'] not in auxNetDict
:
2713 auxNetDict
[sce_vnf
['uuid']] = {}
2714 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
2715 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2716 net
["created"] = True
2718 #print "auxNetDict:"
2719 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2721 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
2722 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2724 for sce_vnf
in scenarioDict
['vnfs']:
2725 vnf_availability_zones
= []
2726 for vm
in sce_vnf
['vms']:
2727 vm_av
= vm
.get('availability_zone')
2728 if vm_av
and vm_av
not in vnf_availability_zones
:
2729 vnf_availability_zones
.append(vm_av
)
2731 # check if there is enough availability zones available at vim level.
2732 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
2733 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
2734 raise NfvoException('No enough availability zones at VIM for this deployment', httperrors
.Bad_Request
)
2736 for vm
in sce_vnf
['vms']:
2739 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
2740 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
2741 #myVMDict['description'] = vm['description']
2742 myVMDict
['description'] = myVMDict
['name'][0:99]
2744 myVMDict
['start'] = "no"
2745 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2746 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
2748 #create image at vim in case it not exist
2749 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2750 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
2751 vm
['vim_image_id'] = image_id
2753 #create flavor at vim in case it not exist
2754 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2755 if flavor_dict
['extended']!=None:
2756 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'], Loader
=yaml
.Loader
)
2757 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
2758 vm
['vim_flavor_id'] = flavor_id
2761 myVMDict
['imageRef'] = vm
['vim_image_id']
2762 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2763 myVMDict
['networks'] = []
2764 for iface
in vm
['interfaces']:
2766 if iface
['type']=="data":
2767 netDict
['type'] = iface
['model']
2768 elif "model" in iface
and iface
["model"]!=None:
2769 netDict
['model']=iface
['model']
2770 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2771 #discover type of interface looking at flavor
2772 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2773 for flavor_iface
in numa
.get('interfaces',[]):
2774 if flavor_iface
.get('name') == iface
['internal_name']:
2775 if flavor_iface
['dedicated'] == 'yes':
2776 netDict
['type']="PF" #passthrough
2777 elif flavor_iface
['dedicated'] == 'no':
2778 netDict
['type']="VF" #siov
2779 elif flavor_iface
['dedicated'] == 'yes:sriov':
2780 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2781 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2783 netDict
["use"]=iface
['type']
2784 if netDict
["use"]=="data" and not netDict
.get("type"):
2785 #print "netDict", netDict
2786 #print "iface", iface
2787 e_text
= "Cannot determine the interface type PF or VF of VNF '{}' VM '{}' iface '{}'".format(
2788 sce_vnf
['name'], vm
['name'], iface
['internal_name'])
2789 if flavor_dict
.get('extended')==None:
2790 raise NfvoException(e_text
+ "After database migration some information is not available. \
2791 Try to delete and create the scenarios and VNFs again", httperrors
.Conflict
)
2793 raise NfvoException(e_text
, httperrors
.Internal_Server_Error
)
2794 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2795 netDict
["type"]="virtual"
2796 if "vpci" in iface
and iface
["vpci"] is not None:
2797 netDict
['vpci'] = iface
['vpci']
2798 if "mac" in iface
and iface
["mac"] is not None:
2799 netDict
['mac_address'] = iface
['mac']
2800 if "port-security" in iface
and iface
["port-security"] is not None:
2801 netDict
['port_security'] = iface
['port-security']
2802 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2803 netDict
['floating_ip'] = iface
['floating-ip']
2804 netDict
['name'] = iface
['internal_name']
2805 if iface
['net_id'] is None:
2806 for vnf_iface
in sce_vnf
["interfaces"]:
2809 if vnf_iface
['interface_id']==iface
['uuid']:
2810 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
2813 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2814 #skip bridge ifaces not connected to any net
2815 #if 'net_id' not in netDict or netDict['net_id']==None:
2817 myVMDict
['networks'].append(netDict
)
2818 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2819 #print myVMDict['name']
2820 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2821 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2822 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2824 if 'availability_zone' in myVMDict
:
2825 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
2829 vm_id
, _
= myvim
.new_vminstance(myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2830 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2831 availability_zone_index
=av_index
,
2832 availability_zone_list
=vnf_availability_zones
)
2833 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
2834 vm
['vim_id'] = vm_id
2835 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2836 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2837 for net
in myVMDict
['networks']:
2839 for iface
in vm
['interfaces']:
2840 if net
["name"]==iface
["internal_name"]:
2841 iface
["vim_id"]=net
["vim_id"]
2844 logger
.debug("start scenario Deployment done")
2845 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2846 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
2847 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
2848 return mydb
.get_instance_scenario(instance_id
)
2850 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
2851 _
, message
= rollback(mydb
, vims
, rollbackList
)
2852 if isinstance(e
, db_base_Exception
):
2853 error_text
= "Exception at database"
2855 error_text
= "Exception at VIM"
2856 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2857 #logger.error("start_scenario %s", error_text)
2858 raise NfvoException(error_text
, e
.http_code
)
2860 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
2861 """ join the cloud config information into cloud_config_preserve.
2862 In case of conflict cloud_config_preserve preserves
2865 if not cloud_config_preserve
and not cloud_config
:
2868 new_cloud_config
= {"key-pairs":[], "users":[]}
2870 if cloud_config_preserve
:
2871 for key
in cloud_config_preserve
.get("key-pairs", () ):
2872 if key
not in new_cloud_config
["key-pairs"]:
2873 new_cloud_config
["key-pairs"].append(key
)
2875 for key
in cloud_config
.get("key-pairs", () ):
2876 if key
not in new_cloud_config
["key-pairs"]:
2877 new_cloud_config
["key-pairs"].append(key
)
2878 if not new_cloud_config
["key-pairs"]:
2879 del new_cloud_config
["key-pairs"]
2883 new_cloud_config
["users"] += cloud_config
.get("users", () )
2884 if cloud_config_preserve
:
2885 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
2886 index_to_delete
= []
2887 users
= new_cloud_config
.get("users", [])
2888 for index0
in range(0,len(users
)):
2889 if index0
in index_to_delete
:
2891 for index1
in range(index0
+1,len(users
)):
2892 if index1
in index_to_delete
:
2894 if users
[index0
]["name"] == users
[index1
]["name"]:
2895 index_to_delete
.append(index1
)
2896 for key
in users
[index1
].get("key-pairs",()):
2897 if "key-pairs" not in users
[index0
]:
2898 users
[index0
]["key-pairs"] = [key
]
2899 elif key
not in users
[index0
]["key-pairs"]:
2900 users
[index0
]["key-pairs"].append(key
)
2901 index_to_delete
.sort(reverse
=True)
2902 for index
in index_to_delete
:
2904 if not new_cloud_config
["users"]:
2905 del new_cloud_config
["users"]
2908 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
2909 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
2910 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
2911 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
2914 new_cloud_config
["user-data"] = []
2915 if cloud_config
and cloud_config
.get("user-data"):
2916 if isinstance(cloud_config
["user-data"], list):
2917 new_cloud_config
["user-data"] += cloud_config
["user-data"]
2919 new_cloud_config
["user-data"].append(cloud_config
["user-data"])
2920 if cloud_config_preserve
and cloud_config_preserve
.get("user-data"):
2921 if isinstance(cloud_config_preserve
["user-data"], list):
2922 new_cloud_config
["user-data"] += cloud_config_preserve
["user-data"]
2924 new_cloud_config
["user-data"].append(cloud_config_preserve
["user-data"])
2925 if not new_cloud_config
["user-data"]:
2926 del new_cloud_config
["user-data"]
2929 new_cloud_config
["config-files"] = []
2930 if cloud_config
and cloud_config
.get("config-files") != None:
2931 new_cloud_config
["config-files"] += cloud_config
["config-files"]
2932 if cloud_config_preserve
:
2933 for file in cloud_config_preserve
.get("config-files", ()):
2934 for index
in range(0, len(new_cloud_config
["config-files"])):
2935 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
2936 new_cloud_config
["config-files"][index
] = file
2939 new_cloud_config
["config-files"].append(file)
2940 if not new_cloud_config
["config-files"]:
2941 del new_cloud_config
["config-files"]
2942 return new_cloud_config
2945 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
2946 datacenter_id
= None
2947 datacenter_name
= None
2950 if datacenter_tenant_id
:
2951 thread_id
= datacenter_tenant_id
2952 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
2954 where_
={"td.nfvo_tenant_id": tenant_id
}
2955 if datacenter_id_name
:
2956 if utils
.check_valid_uuid(datacenter_id_name
):
2957 datacenter_id
= datacenter_id_name
2958 where_
["dt.datacenter_id"] = datacenter_id
2960 datacenter_name
= datacenter_id_name
2961 where_
["d.name"] = datacenter_name
2962 if datacenter_tenant_id
:
2963 where_
["dt.uuid"] = datacenter_tenant_id
2964 datacenters
= mydb
.get_rows(
2965 SELECT
=("dt.uuid as datacenter_tenant_id",),
2966 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
2967 "join datacenters as d on d.uuid=dt.datacenter_id",
2969 if len(datacenters
) > 1:
2970 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
2972 thread_id
= datacenters
[0]["datacenter_tenant_id"]
2973 thread
= vim_threads
["running"].get(thread_id
)
2975 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
2976 return thread_id
, thread
2977 except db_base_Exception
as e
:
2978 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
2981 def get_datacenter_uuid(mydb
, tenant_id
, datacenter_id_name
):
2983 if utils
.check_valid_uuid(datacenter_id_name
):
2984 WHERE_dict
['d.uuid'] = datacenter_id_name
2986 WHERE_dict
['d.name'] = datacenter_id_name
2989 WHERE_dict
['nfvo_tenant_id'] = tenant_id
2990 from_
= "tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join datacenter_tenants as" \
2991 " dt on td.datacenter_tenant_id=dt.uuid"
2993 from_
= 'datacenters as d'
2994 vimaccounts
= mydb
.get_rows(FROM
=from_
, SELECT
=("d.uuid as uuid, d.name as name",), WHERE
=WHERE_dict
)
2995 if len(vimaccounts
) == 0:
2996 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
2997 elif len(vimaccounts
)>1:
2998 #print "nfvo.datacenter_action() error. Several datacenters found"
2999 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
3000 return vimaccounts
[0]["uuid"], vimaccounts
[0]["name"]
3003 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
3004 datacenter_id
= None
3005 datacenter_name
= None
3006 if datacenter_id_name
:
3007 if utils
.check_valid_uuid(datacenter_id_name
):
3008 datacenter_id
= datacenter_id_name
3010 datacenter_name
= datacenter_id_name
3011 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
3013 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
3015 #print "nfvo.datacenter_action() error. Several datacenters found"
3016 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
3017 for vim_id
, vim_content
in vims
.items():
3018 return vim_id
, vim_content
3022 """Takes dict d and updates it with the values in dict u.
3023 It merges all depth levels"""
3024 for k
, v
in u
.items():
3025 if isinstance(v
, collections
.Mapping
):
3026 r
= update(d
.get(k
, {}), v
)
3033 def create_instance(mydb
, tenant_id
, instance_dict
):
3034 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
3035 # logger.debug("Creating instance...")
3036 scenario
= instance_dict
["scenario"]
3038 # find main datacenter
3040 myvim_threads_id
= {}
3041 datacenter
= instance_dict
.get("datacenter")
3042 default_wim_account
= instance_dict
.get("wim_account")
3043 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3044 myvims
[default_datacenter_id
] = vim
3045 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
3046 tenant
= mydb
.get_rows_by_id('nfvo_tenants', tenant_id
)
3047 # myvim_tenant = myvim['tenant_id']
3050 # print "Checking that the scenario exists and getting the scenario dictionary"
3051 if isinstance(scenario
, str):
3052 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, datacenter_vim_id
=myvim_threads_id
[default_datacenter_id
],
3053 datacenter_id
=default_datacenter_id
)
3055 scenarioDict
= scenario
3056 scenarioDict
["uuid"] = None
3058 # logger.debug(">>>>>> Dictionaries before merging")
3059 # logger.debug(">>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
3060 # logger.debug(">>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
3062 db_instance_vnfs
= []
3063 db_instance_vms
= []
3064 db_instance_interfaces
= []
3065 db_instance_sfis
= []
3066 db_instance_sfs
= []
3067 db_instance_classifications
= []
3068 db_instance_sfps
= []
3073 instance_name
= instance_dict
["name"]
3074 instance_uuid
= str(uuid4())
3075 uuid_list
.append(instance_uuid
)
3076 db_instance_scenario
= {
3077 "uuid": instance_uuid
,
3078 "name": instance_name
,
3079 "tenant_id": tenant_id
,
3080 "scenario_id": scenarioDict
['uuid'],
3081 "datacenter_id": default_datacenter_id
,
3082 # filled bellow 'datacenter_tenant_id'
3083 "description": instance_dict
.get("description"),
3085 if scenarioDict
.get("cloud-config"):
3086 db_instance_scenario
["cloud_config"] = yaml
.safe_dump(scenarioDict
["cloud-config"],
3087 default_flow_style
=True, width
=256)
3088 instance_action_id
= get_task_id()
3089 db_instance_action
= {
3090 "uuid": instance_action_id
, # same uuid for the instance and the action on create
3091 "tenant_id": tenant_id
,
3092 "instance_id": instance_uuid
,
3093 "description": "CREATE",
3096 # Auxiliary dictionaries from x to y
3097 sce_net2instance
= {}
3098 net2task_id
= {'scenario': {}}
3099 # Mapping between local networks and WIMs
3102 def ip_profile_IM2RO(ip_profile_im
):
3103 # translate from input format to database format
3105 if 'subnet-address' in ip_profile_im
:
3106 ip_profile_ro
['subnet_address'] = ip_profile_im
['subnet-address']
3107 if 'ip-version' in ip_profile_im
:
3108 ip_profile_ro
['ip_version'] = ip_profile_im
['ip-version']
3109 if 'gateway-address' in ip_profile_im
:
3110 ip_profile_ro
['gateway_address'] = ip_profile_im
['gateway-address']
3111 if 'dns-address' in ip_profile_im
:
3112 ip_profile_ro
['dns_address'] = ip_profile_im
['dns-address']
3113 if isinstance(ip_profile_ro
['dns_address'], (list, tuple)):
3114 ip_profile_ro
['dns_address'] = ";".join(ip_profile_ro
['dns_address'])
3115 if 'dhcp' in ip_profile_im
:
3116 ip_profile_ro
['dhcp_start_address'] = ip_profile_im
['dhcp'].get('start-address')
3117 ip_profile_ro
['dhcp_enabled'] = ip_profile_im
['dhcp'].get('enabled', True)
3118 ip_profile_ro
['dhcp_count'] = ip_profile_im
['dhcp'].get('count')
3119 return ip_profile_ro
3121 # logger.debug("Creating instance from scenario-dict:\n%s",
3122 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
3124 # 0 check correct parameters
3125 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).items():
3126 for scenario_net
in scenarioDict
['nets']:
3127 if net_name
== scenario_net
.get("name") or net_name
== scenario_net
.get("osm_id") or net_name
== scenario_net
.get("uuid"):
3130 raise NfvoException("Invalid scenario network name or id '{}' at instance:networks".format(net_name
),
3131 httperrors
.Bad_Request
)
3132 if "sites" not in net_instance_desc
:
3133 net_instance_desc
["sites"] = [ {} ]
3134 site_without_datacenter_field
= False
3135 for site
in net_instance_desc
["sites"]:
3136 if site
.get("datacenter"):
3137 site
["datacenter"], _
= get_datacenter_uuid(mydb
, tenant_id
, site
["datacenter"])
3138 if site
["datacenter"] not in myvims
:
3139 # Add this datacenter to myvims
3140 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
3142 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
3143 site
["datacenter"] = d
# change name to id
3145 if site_without_datacenter_field
:
3146 raise NfvoException("Found more than one entries without datacenter field at "
3147 "instance:networks:{}:sites".format(net_name
), httperrors
.Bad_Request
)
3148 site_without_datacenter_field
= True
3149 site
["datacenter"] = default_datacenter_id
# change name to id
3151 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).items():
3152 for scenario_vnf
in scenarioDict
['vnfs']:
3153 if vnf_name
== scenario_vnf
['member_vnf_index'] or vnf_name
== scenario_vnf
['uuid'] or vnf_name
== scenario_vnf
['name']:
3156 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_name
), httperrors
.Bad_Request
)
3157 if "datacenter" in vnf_instance_desc
:
3158 # Add this datacenter to myvims
3159 vnf_instance_desc
["datacenter"], _
= get_datacenter_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3160 if vnf_instance_desc
["datacenter"] not in myvims
:
3161 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3163 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3164 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
3166 for net_id
, net_instance_desc
in vnf_instance_desc
.get("networks", {}).items():
3167 for scenario_net
in scenario_vnf
['nets']:
3168 if net_id
== scenario_net
['osm_id'] or net_id
== scenario_net
['uuid'] or net_id
== scenario_net
["name"]:
3171 raise NfvoException("Invalid net id or name '{}' at instance:vnfs:networks".format(net_id
), httperrors
.Bad_Request
)
3172 if net_instance_desc
.get("vim-network-name"):
3173 scenario_net
["vim-network-name"] = net_instance_desc
["vim-network-name"]
3174 if net_instance_desc
.get("vim-network-id"):
3175 scenario_net
["vim-network-id"] = net_instance_desc
["vim-network-id"]
3176 if net_instance_desc
.get("name"):
3177 scenario_net
["name"] = net_instance_desc
["name"]
3178 if 'ip-profile' in net_instance_desc
:
3179 ipprofile_db
= ip_profile_IM2RO(net_instance_desc
['ip-profile'])
3180 if 'ip_profile' not in scenario_net
:
3181 scenario_net
['ip_profile'] = ipprofile_db
3183 update(scenario_net
['ip_profile'], ipprofile_db
)
3185 for vdu_id
, vdu_instance_desc
in vnf_instance_desc
.get("vdus", {}).items():
3186 for scenario_vm
in scenario_vnf
['vms']:
3187 if vdu_id
== scenario_vm
['osm_id'] or vdu_id
== scenario_vm
["name"]:
3190 raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id
), httperrors
.Bad_Request
)
3191 scenario_vm
["instance_parameters"] = vdu_instance_desc
3192 for iface_id
, iface_instance_desc
in vdu_instance_desc
.get("interfaces", {}).items():
3193 for scenario_interface
in scenario_vm
['interfaces']:
3194 if iface_id
== scenario_interface
['internal_name'] or iface_id
== scenario_interface
["external_name"]:
3195 scenario_interface
.update(iface_instance_desc
)
3198 raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id
), httperrors
.Bad_Request
)
3200 # 0.1 parse cloud-config parameters
3201 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
3203 # 0.2 merge instance information into scenario
3204 # Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
3205 # However, this is not possible yet.
3206 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).items():
3207 for scenario_net
in scenarioDict
['nets']:
3208 if net_name
== scenario_net
.get("name") or net_name
== scenario_net
.get("osm_id") or net_name
== scenario_net
.get("uuid"):
3209 if "wim_account" in net_instance_desc
and net_instance_desc
["wim_account"] is not None:
3210 scenario_net
["wim_account"] = net_instance_desc
["wim_account"]
3211 if 'ip-profile' in net_instance_desc
:
3212 ipprofile_db
= ip_profile_IM2RO(net_instance_desc
['ip-profile'])
3213 if 'ip_profile' not in scenario_net
:
3214 scenario_net
['ip_profile'] = ipprofile_db
3216 update(scenario_net
['ip_profile'], ipprofile_db
)
3217 for interface
in net_instance_desc
.get('interfaces', ()):
3218 if 'ip_address' in interface
:
3219 for vnf
in scenarioDict
['vnfs']:
3220 if interface
['vnf'] == vnf
['name']:
3221 for vnf_interface
in vnf
['interfaces']:
3222 if interface
['vnf_interface'] == vnf_interface
['external_name']:
3223 vnf_interface
['ip_address'] = interface
['ip_address']
3225 # logger.debug(">>>>>>>> Merged dictionary")
3226 # logger.debug("Creating instance scenario-dict MERGED:\n%s",
3227 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
3229 # 1. Creating new nets (sce_nets) in the VIM"
3230 number_mgmt_networks
= 0
3231 db_instance_nets
= []
3232 for sce_net
in scenarioDict
['nets']:
3233 sce_net_uuid
= sce_net
.get('uuid', sce_net
["name"])
3234 # get involved datacenters where this network need to be created
3235 involved_datacenters
= []
3236 for sce_vnf
in scenarioDict
.get("vnfs", ()):
3237 vnf_datacenter
= sce_vnf
.get("datacenter", default_datacenter_id
)
3238 if vnf_datacenter
in involved_datacenters
:
3240 if sce_vnf
.get("interfaces"):
3241 for sce_vnf_ifaces
in sce_vnf
["interfaces"]:
3242 if sce_vnf_ifaces
.get("sce_net_id") == sce_net
["uuid"]:
3243 involved_datacenters
.append(vnf_datacenter
)
3245 if not involved_datacenters
:
3246 involved_datacenters
.append(default_datacenter_id
)
3247 target_wim_account
= sce_net
.get("wim_account", default_wim_account
)
3250 # TODO: use this information during network creation
3251 wim_account_id
= wim_account_name
= None
3252 if len(involved_datacenters
) > 1 and 'uuid' in sce_net
:
3253 if target_wim_account
is None or target_wim_account
is True: # automatic selection of WIM
3254 # OBS: sce_net without uuid are used internally to VNFs
3255 # and the assumption is that VNFs will not be split among
3256 # different datacenters
3257 wim_account
= wim_engine
.find_suitable_wim_account(
3258 involved_datacenters
, tenant_id
)
3259 wim_account_id
= wim_account
['uuid']
3260 wim_account_name
= wim_account
['name']
3261 wim_usage
[sce_net
['uuid']] = wim_account_id
3262 elif isinstance(target_wim_account
, str): # manual selection of WIM
3263 wim_account
.persist
.get_wim_account_by(target_wim_account
, tenant_id
)
3264 wim_account_id
= wim_account
['uuid']
3265 wim_account_name
= wim_account
['name']
3266 wim_usage
[sce_net
['uuid']] = wim_account_id
3267 else: # not WIM usage
3268 wim_usage
[sce_net
['uuid']] = False
3272 if instance_dict
.get("networks"):
3273 if sce_net
.get("uuid") in instance_dict
["networks"]:
3274 descriptor_net
= instance_dict
["networks"][sce_net
["uuid"]]
3275 descriptor_net_name
= sce_net
["uuid"]
3276 elif sce_net
.get("osm_id") in instance_dict
["networks"]:
3277 descriptor_net
= instance_dict
["networks"][sce_net
["osm_id"]]
3278 descriptor_net_name
= sce_net
["osm_id"]
3279 elif sce_net
["name"] in instance_dict
["networks"]:
3280 descriptor_net
= instance_dict
["networks"][sce_net
["name"]]
3281 descriptor_net_name
= sce_net
["name"]
3282 net_name
= descriptor_net
.get("vim-network-name")
3283 # add datacenters from instantiation parameters
3284 if descriptor_net
.get("sites"):
3285 for site
in descriptor_net
["sites"]:
3286 if site
.get("datacenter") and site
["datacenter"] not in involved_datacenters
:
3287 involved_datacenters
.append(site
["datacenter"])
3288 sce_net2instance
[sce_net_uuid
] = {}
3289 net2task_id
['scenario'][sce_net_uuid
] = {}
3292 related_network
= None
3293 if descriptor_net
.get("use-network"):
3294 target_instance_nets
= mydb
.get_rows(
3296 FROM
="instance_nets",
3297 WHERE
={"instance_scenario_id": descriptor_net
["use-network"]["instance_scenario_id"],
3298 "osm_id": descriptor_net
["use-network"]["osm_id"]},
3300 if not target_instance_nets
:
3301 raise NfvoException(
3302 "Cannot find the target network at instance:networks[{}]:use-network".format(descriptor_net_name
),
3303 httperrors
.Bad_Request
)
3305 use_network
= target_instance_nets
[0]["related"]
3307 if sce_net
["external"]:
3308 number_mgmt_networks
+= 1
3310 for datacenter_id
in involved_datacenters
:
3312 netmap_create
= None
3313 if descriptor_net
.get("sites"):
3314 for site
in descriptor_net
["sites"]:
3315 if site
.get("datacenter") == datacenter_id
:
3316 netmap_use
= site
.get("netmap-use")
3317 netmap_create
= site
.get("netmap-create")
3320 vim
= myvims
[datacenter_id
]
3321 myvim_thread_id
= myvim_threads_id
[datacenter_id
]
3323 net_type
= sce_net
['type']
3325 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} # 'shared': True
3328 if sce_net
["external"]:
3329 net_name
= sce_net
["name"]
3331 net_name
= "{}-{}".format(instance_name
, sce_net
["name"])
3332 net_name
= net_name
[:255] # limit length
3334 if netmap_use
or netmap_create
:
3335 create_network
= False
3336 lookfor_network
= False
3338 lookfor_network
= True
3339 if utils
.check_valid_uuid(netmap_use
):
3340 lookfor_filter
["id"] = netmap_use
3342 lookfor_filter
["name"] = netmap_use
3344 create_network
= True
3345 net_vim_name
= net_name
3346 if isinstance(netmap_create
, str):
3347 net_vim_name
= netmap_create
3348 elif sce_net
.get("vim_network_name"):
3349 create_network
= False
3350 lookfor_network
= True
3351 lookfor_filter
["name"] = sce_net
.get("vim_network_name")
3352 elif sce_net
["external"]:
3353 if sce_net
.get('vim_id'):
3354 # there is a netmap at datacenter_nets database # TODO REVISE!!!!
3355 create_network
= False
3356 lookfor_network
= True
3357 lookfor_filter
["id"] = sce_net
['vim_id']
3358 elif vim
["config"].get("management_network_id") or vim
["config"].get("management_network_name"):
3359 if number_mgmt_networks
> 1:
3360 raise NfvoException("Found several VLD of type mgmt. "
3361 "You must concrete what vim-network must be use for each one",
3362 httperrors
.Bad_Request
)
3363 create_network
= False
3364 lookfor_network
= True
3365 if vim
["config"].get("management_network_id"):
3366 lookfor_filter
["id"] = vim
["config"]["management_network_id"]
3368 lookfor_filter
["name"] = vim
["config"]["management_network_name"]
3370 # There is not a netmap, look at datacenter for a net with this name and create if not found
3371 create_network
= True
3372 lookfor_network
= True
3373 lookfor_filter
["name"] = sce_net
["name"]
3374 net_vim_name
= sce_net
["name"]
3376 net_vim_name
= net_name
3377 create_network
= True
3378 lookfor_network
= False
3382 task_action
= "CREATE"
3383 task_extra
["params"] = (net_vim_name
, net_type
, sce_net
.get('ip_profile', None), wim_account_name
)
3385 task_extra
["find"] = (lookfor_filter
,)
3386 elif lookfor_network
:
3387 task_action
= "FIND"
3388 task_extra
["params"] = (lookfor_filter
,)
3390 # fill database content
3391 net_uuid
= str(uuid4())
3392 uuid_list
.append(net_uuid
)
3393 sce_net2instance
[sce_net_uuid
][datacenter_id
] = net_uuid
3394 if not related_network
: # all db_instance_nets will have same related
3395 related_network
= use_network
or net_uuid
3398 "osm_id": sce_net
.get("osm_id") or sce_net
["name"],
3399 "related": related_network
,
3401 "vim_name": net_vim_name
,
3402 "instance_scenario_id": instance_uuid
,
3403 "sce_net_id": sce_net
.get("uuid"),
3404 "created": create_network
,
3405 'datacenter_id': datacenter_id
,
3406 'datacenter_tenant_id': myvim_thread_id
,
3407 'status': 'BUILD' # if create_network else "ACTIVE"
3409 db_instance_nets
.append(db_net
)
3411 "instance_action_id": instance_action_id
,
3412 "status": "SCHEDULED",
3413 "task_index": task_index
,
3414 "datacenter_vim_id": myvim_thread_id
,
3415 "action": task_action
,
3416 "item": "instance_nets",
3417 "item_id": net_uuid
,
3418 "related": related_network
,
3419 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
3421 net2task_id
['scenario'][sce_net_uuid
][datacenter_id
] = task_index
3423 db_vim_actions
.append(db_vim_action
)
3425 if 'ip_profile' in sce_net
:
3427 'instance_net_id': net_uuid
,
3428 'ip_version': sce_net
['ip_profile']['ip_version'],
3429 'subnet_address': sce_net
['ip_profile']['subnet_address'],
3430 'gateway_address': sce_net
['ip_profile']['gateway_address'],
3431 'dns_address': sce_net
['ip_profile']['dns_address'],
3432 'dhcp_enabled': sce_net
['ip_profile']['dhcp_enabled'],
3433 'dhcp_start_address': sce_net
['ip_profile']['dhcp_start_address'],
3434 'dhcp_count': sce_net
['ip_profile']['dhcp_count'],
3436 db_ip_profiles
.append(db_ip_profile
)
3440 "default_datacenter_id": default_datacenter_id
,
3441 "myvim_threads_id": myvim_threads_id
,
3442 "instance_uuid": instance_uuid
,
3443 "instance_name": instance_name
,
3444 "instance_action_id": instance_action_id
,
3446 "cloud_config": cloud_config
,
3447 "RO_pub_key": tenant
[0].get('RO_pub_key'),
3448 "instance_parameters": instance_dict
,
3451 "task_index": task_index
,
3452 "uuid_list": uuid_list
,
3453 "db_instance_nets": db_instance_nets
,
3454 "db_vim_actions": db_vim_actions
,
3455 "db_ip_profiles": db_ip_profiles
,
3456 "db_instance_vnfs": db_instance_vnfs
,
3457 "db_instance_vms": db_instance_vms
,
3458 "db_instance_interfaces": db_instance_interfaces
,
3459 "net2task_id": net2task_id
,
3460 "sce_net2instance": sce_net2instance
,
3462 # sce_vnf_list = sorted(scenarioDict['vnfs'], key=lambda k: k['name'])
3463 for sce_vnf
in scenarioDict
.get('vnfs', ()): # sce_vnf_list:
3464 instantiate_vnf(mydb
, sce_vnf
, vnf_params
, vnf_params_out
, rollbackList
)
3465 task_index
= vnf_params_out
["task_index"]
3466 uuid_list
= vnf_params_out
["uuid_list"]
3469 # task_depends_on = []
3470 for vnffg
in scenarioDict
.get('vnffgs', ()):
3471 for rsp
in vnffg
['rsps']:
3473 for cp
in rsp
['connection_points']:
3474 count
= mydb
.get_rows(
3476 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_rsp_hops as h "
3477 "on interfaces.uuid=h.ingress_interface_id",
3478 WHERE
={'h.uuid': cp
['uuid']})[0]['count']
3479 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == cp
['sce_vnf_id']), None)
3480 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3482 for instance_vm
in instance_vms
:
3483 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3485 dependencies
.append(action
['task_index'])
3486 # TODO: throw exception if count != len(instance_vms)
3487 # TODO: and action shouldn't ever be None
3489 for i
in range(count
):
3491 sfi_uuid
= str(uuid4())
3493 "ingress_interface_id": cp
["ingress_interface_id"],
3494 "egress_interface_id": cp
["egress_interface_id"]
3496 uuid_list
.append(sfi_uuid
)
3499 "related": sfi_uuid
,
3500 "instance_scenario_id": instance_uuid
,
3501 'sce_rsp_hop_id': cp
['uuid'],
3502 'datacenter_id': datacenter_id
,
3503 'datacenter_tenant_id': myvim_thread_id
,
3504 "vim_sfi_id": None, # vim thread will populate
3506 db_instance_sfis
.append(db_sfi
)
3508 "instance_action_id": instance_action_id
,
3509 "task_index": task_index
,
3510 "datacenter_vim_id": myvim_thread_id
,
3512 "status": "SCHEDULED",
3513 "item": "instance_sfis",
3514 "item_id": sfi_uuid
,
3515 "related": sfi_uuid
,
3516 "extra": yaml
.safe_dump({"params": extra_params
, "depends_on": [dependencies
[i
]]},
3517 default_flow_style
=True, width
=256)
3519 sfis_created
.append(task_index
)
3521 db_vim_actions
.append(db_vim_action
)
3523 sf_uuid
= str(uuid4())
3524 uuid_list
.append(sf_uuid
)
3528 "instance_scenario_id": instance_uuid
,
3529 'sce_rsp_hop_id': cp
['uuid'],
3530 'datacenter_id': datacenter_id
,
3531 'datacenter_tenant_id': myvim_thread_id
,
3532 "vim_sf_id": None, # vim thread will populate
3534 db_instance_sfs
.append(db_sf
)
3536 "instance_action_id": instance_action_id
,
3537 "task_index": task_index
,
3538 "datacenter_vim_id": myvim_thread_id
,
3540 "status": "SCHEDULED",
3541 "item": "instance_sfs",
3544 "extra": yaml
.safe_dump({"params": "", "depends_on": sfis_created
},
3545 default_flow_style
=True, width
=256)
3547 sfs_created
.append(task_index
)
3549 db_vim_actions
.append(db_vim_action
)
3550 classifier
= rsp
['classifier']
3552 # TODO the following ~13 lines can be reused for the sfi case
3553 count
= mydb
.get_rows(
3554 SELECT
=('vms.count'),
3555 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_classifiers as c on interfaces.uuid=c.interface_id",
3556 WHERE
={'c.uuid': classifier
['uuid']})[0]['count']
3557 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == classifier
['sce_vnf_id']), None)
3558 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3560 for instance_vm
in instance_vms
:
3561 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3563 dependencies
.append(action
['task_index'])
3564 # TODO: throw exception if count != len(instance_vms)
3565 # TODO: and action shouldn't ever be None
3566 classifications_created
= []
3567 for i
in range(count
):
3568 for match
in classifier
['matches']:
3569 # create classifications
3570 classification_uuid
= str(uuid4())
3571 uuid_list
.append(classification_uuid
)
3572 db_classification
= {
3573 "uuid": classification_uuid
,
3574 "related": classification_uuid
,
3575 "instance_scenario_id": instance_uuid
,
3576 'sce_classifier_match_id': match
['uuid'],
3577 'datacenter_id': datacenter_id
,
3578 'datacenter_tenant_id': myvim_thread_id
,
3579 "vim_classification_id": None, # vim thread will populate
3581 db_instance_classifications
.append(db_classification
)
3582 classification_params
= {
3583 "ip_proto": match
["ip_proto"],
3584 "source_ip": match
["source_ip"],
3585 "destination_ip": match
["destination_ip"],
3586 "source_port": match
["source_port"],
3587 "destination_port": match
["destination_port"]
3590 "instance_action_id": instance_action_id
,
3591 "task_index": task_index
,
3592 "datacenter_vim_id": myvim_thread_id
,
3594 "status": "SCHEDULED",
3595 "item": "instance_classifications",
3596 "item_id": classification_uuid
,
3597 "related": classification_uuid
,
3598 "extra": yaml
.safe_dump({"params": classification_params
, "depends_on": [dependencies
[i
]]},
3599 default_flow_style
=True, width
=256)
3601 classifications_created
.append(task_index
)
3603 db_vim_actions
.append(db_vim_action
)
3606 sfp_uuid
= str(uuid4())
3607 uuid_list
.append(sfp_uuid
)
3610 "related": sfp_uuid
,
3611 "instance_scenario_id": instance_uuid
,
3612 'sce_rsp_id': rsp
['uuid'],
3613 'datacenter_id': datacenter_id
,
3614 'datacenter_tenant_id': myvim_thread_id
,
3615 "vim_sfp_id": None, # vim thread will populate
3617 db_instance_sfps
.append(db_sfp
)
3619 "instance_action_id": instance_action_id
,
3620 "task_index": task_index
,
3621 "datacenter_vim_id": myvim_thread_id
,
3623 "status": "SCHEDULED",
3624 "item": "instance_sfps",
3625 "item_id": sfp_uuid
,
3626 "related": sfp_uuid
,
3627 "extra": yaml
.safe_dump({"params": "", "depends_on": sfs_created
+ classifications_created
},
3628 default_flow_style
=True, width
=256)
3631 db_vim_actions
.append(db_vim_action
)
3632 db_instance_action
["number_tasks"] = task_index
3635 logger
.debug('wim_usage:\n%s\n\n', pformat(wim_usage
))
3636 wan_links
= wim_engine
.derive_wan_links(wim_usage
, db_instance_nets
, tenant_id
)
3637 wim_actions
= wim_engine
.create_actions(wan_links
)
3638 wim_actions
, db_instance_action
= (
3639 wim_engine
.incorporate_actions(wim_actions
, db_instance_action
))
3642 scenarioDict
["datacenter2tenant"] = myvim_threads_id
3644 db_instance_scenario
['datacenter_tenant_id'] = myvim_threads_id
[default_datacenter_id
]
3645 db_instance_scenario
['datacenter_id'] = default_datacenter_id
3647 {"instance_scenarios": db_instance_scenario
},
3648 {"instance_vnfs": db_instance_vnfs
},
3649 {"instance_nets": db_instance_nets
},
3650 {"ip_profiles": db_ip_profiles
},
3651 {"instance_vms": db_instance_vms
},
3652 {"instance_interfaces": db_instance_interfaces
},
3653 {"instance_actions": db_instance_action
},
3654 {"instance_sfis": db_instance_sfis
},
3655 {"instance_sfs": db_instance_sfs
},
3656 {"instance_classifications": db_instance_classifications
},
3657 {"instance_sfps": db_instance_sfps
},
3658 {"instance_wim_nets": wan_links
},
3659 {"vim_wim_actions": db_vim_actions
+ wim_actions
}
3662 logger
.debug("create_instance done DB tables: %s",
3663 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
3664 mydb
.new_rows(db_tables
, uuid_list
)
3665 for myvim_thread_id
in myvim_threads_id
.values():
3666 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
3668 wim_engine
.dispatch(wim_actions
)
3670 returned_instance
= mydb
.get_instance_scenario(instance_uuid
)
3671 returned_instance
["action_id"] = instance_action_id
3672 return returned_instance
3673 except (NfvoException
, vimconn
.vimconnException
, wimconn
.WimConnectorError
, db_base_Exception
) as e
:
3674 message
= rollback(mydb
, myvims
, rollbackList
)
3675 if isinstance(e
, db_base_Exception
):
3676 error_text
= "database Exception"
3677 elif isinstance(e
, vimconn
.vimconnException
):
3678 error_text
= "VIM Exception"
3679 elif isinstance(e
, wimconn
.WimConnectorError
):
3680 error_text
= "WIM Exception"
3682 error_text
= "Exception"
3683 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
3684 # logger.error("create_instance: %s", error_text)
3686 raise NfvoException(error_text
, e
.http_code
)
3689 def instantiate_vnf(mydb
, sce_vnf
, params
, params_out
, rollbackList
):
3690 default_datacenter_id
= params
["default_datacenter_id"]
3691 myvim_threads_id
= params
["myvim_threads_id"]
3692 instance_uuid
= params
["instance_uuid"]
3693 instance_name
= params
["instance_name"]
3694 instance_action_id
= params
["instance_action_id"]
3695 myvims
= params
["myvims"]
3696 cloud_config
= params
["cloud_config"]
3697 RO_pub_key
= params
["RO_pub_key"]
3699 task_index
= params_out
["task_index"]
3700 uuid_list
= params_out
["uuid_list"]
3701 db_instance_nets
= params_out
["db_instance_nets"]
3702 db_vim_actions
= params_out
["db_vim_actions"]
3703 db_ip_profiles
= params_out
["db_ip_profiles"]
3704 db_instance_vnfs
= params_out
["db_instance_vnfs"]
3705 db_instance_vms
= params_out
["db_instance_vms"]
3706 db_instance_interfaces
= params_out
["db_instance_interfaces"]
3707 net2task_id
= params_out
["net2task_id"]
3708 sce_net2instance
= params_out
["sce_net2instance"]
3710 vnf_net2instance
= {}
3712 # 2. Creating new nets (vnf internal nets) in the VIM"
3713 # For each vnf net, we create it and we add it to instanceNetlist.
3714 if sce_vnf
.get("datacenter"):
3715 datacenter_id
= sce_vnf
["datacenter"]
3716 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
3718 datacenter_id
= default_datacenter_id
3719 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
3720 for net
in sce_vnf
['nets']:
3722 # descriptor_net = instance_dict.get("vnfs", {}).get(sce_vnf["name"], {})
3723 # net_name = descriptor_net.get("name")
3726 net_name
= "{}-{}".format(instance_name
, net
["name"])
3727 net_name
= net_name
[:255] # limit length
3728 net_type
= net
['type']
3730 if sce_vnf
['uuid'] not in vnf_net2instance
:
3731 vnf_net2instance
[sce_vnf
['uuid']] = {}
3732 if sce_vnf
['uuid'] not in net2task_id
:
3733 net2task_id
[sce_vnf
['uuid']] = {}
3734 net2task_id
[sce_vnf
['uuid']][net
['uuid']] = task_index
3736 # fill database content
3737 net_uuid
= str(uuid4())
3738 uuid_list
.append(net_uuid
)
3739 vnf_net2instance
[sce_vnf
['uuid']][net
['uuid']] = net_uuid
3742 "related": net_uuid
,
3744 "vim_name": net_name
,
3745 "instance_scenario_id": instance_uuid
,
3746 "net_id": net
["uuid"],
3748 'datacenter_id': datacenter_id
,
3749 'datacenter_tenant_id': myvim_thread_id
,
3751 db_instance_nets
.append(db_net
)
3754 if net
.get("vim-network-name"):
3755 lookfor_filter
["name"] = net
["vim-network-name"]
3756 if net
.get("vim-network-id"):
3757 lookfor_filter
["id"] = net
["vim-network-id"]
3759 task_action
= "FIND"
3760 task_extra
= {"params": (lookfor_filter
,)}
3762 task_action
= "CREATE"
3763 task_extra
= {"params": (net_name
, net_type
, net
.get('ip_profile', None))}
3766 "instance_action_id": instance_action_id
,
3767 "task_index": task_index
,
3768 "datacenter_vim_id": myvim_thread_id
,
3769 "status": "SCHEDULED",
3770 "action": task_action
,
3771 "item": "instance_nets",
3772 "item_id": net_uuid
,
3773 "related": net_uuid
,
3774 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
3777 db_vim_actions
.append(db_vim_action
)
3779 if 'ip_profile' in net
:
3781 'instance_net_id': net_uuid
,
3782 'ip_version': net
['ip_profile']['ip_version'],
3783 'subnet_address': net
['ip_profile']['subnet_address'],
3784 'gateway_address': net
['ip_profile']['gateway_address'],
3785 'dns_address': net
['ip_profile']['dns_address'],
3786 'dhcp_enabled': net
['ip_profile']['dhcp_enabled'],
3787 'dhcp_start_address': net
['ip_profile']['dhcp_start_address'],
3788 'dhcp_count': net
['ip_profile']['dhcp_count'],
3790 db_ip_profiles
.append(db_ip_profile
)
3792 # print "vnf_net2instance:"
3793 # print yaml.safe_dump(vnf_net2instance, indent=4, default_flow_style=False)
3795 # 3. Creating new vm instances in the VIM
3796 # myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
3798 if sce_vnf
.get('mgmt_access'):
3799 ssh_access
= sce_vnf
['mgmt_access'].get('config-access', {}).get('ssh-access')
3800 vnf_availability_zones
= []
3801 for vm
in sce_vnf
.get('vms'):
3802 vm_av
= vm
.get('availability_zone')
3803 if vm_av
and vm_av
not in vnf_availability_zones
:
3804 vnf_availability_zones
.append(vm_av
)
3806 # check if there is enough availability zones available at vim level.
3807 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
3808 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
3809 raise NfvoException('No enough availability zones at VIM for this deployment', httperrors
.Bad_Request
)
3811 if sce_vnf
.get("datacenter"):
3812 vim
= myvims
[sce_vnf
["datacenter"]]
3813 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
3814 datacenter_id
= sce_vnf
["datacenter"]
3816 vim
= myvims
[default_datacenter_id
]
3817 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
3818 datacenter_id
= default_datacenter_id
3819 sce_vnf
["datacenter_id"] = datacenter_id
3822 vnf_uuid
= str(uuid4())
3823 uuid_list
.append(vnf_uuid
)
3826 'instance_scenario_id': instance_uuid
,
3827 'vnf_id': sce_vnf
['vnf_id'],
3828 'sce_vnf_id': sce_vnf
['uuid'],
3829 'datacenter_id': datacenter_id
,
3830 'datacenter_tenant_id': myvim_thread_id
,
3832 db_instance_vnfs
.append(db_instance_vnf
)
3834 for vm
in sce_vnf
['vms']:
3836 if vm
.get("pdu_type"):
3840 sce_vnf_name
= sce_vnf
['member_vnf_index'] if sce_vnf
['member_vnf_index'] else sce_vnf
['name']
3841 myVMDict
['name'] = "{}-{}-{}".format(instance_name
[:64], sce_vnf_name
[:64], vm
["name"][:64])
3842 myVMDict
['description'] = myVMDict
['name'][0:99]
3844 # myVMDict['start'] = "no"
3845 if vm
.get("instance_parameters") and vm
["instance_parameters"].get("name"):
3846 myVMDict
['name'] = vm
["instance_parameters"].get("name")
3847 myVMDict
['name'] = myVMDict
['name'][0:255] # limit name length
3848 # create image at vim in case it not exist
3849 image_uuid
= vm
['image_id']
3850 if vm
.get("image_list"):
3851 for alternative_image
in vm
["image_list"]:
3852 if alternative_image
["vim_type"] == vim
["config"]["_vim_type_internal"]:
3853 image_uuid
= alternative_image
['image_id']
3855 image_dict
= mydb
.get_table_by_uuid_name("images", image_uuid
)
3856 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
3857 vm
['vim_image_id'] = image_id
3859 # create flavor at vim in case it not exist
3860 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
3861 if flavor_dict
['extended'] != None:
3862 flavor_dict
['extended'] = yaml
.load(flavor_dict
['extended'], Loader
=yaml
.Loader
)
3863 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
3865 # Obtain information for additional disks
3866 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',),
3867 WHERE
={'vim_id': flavor_id
})
3868 if not extended_flavor_dict
:
3869 raise NfvoException("flavor '{}' not found".format(flavor_id
), httperrors
.Not_Found
)
3871 # extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0], Loader=yaml.Loader)
3872 myVMDict
['disks'] = None
3873 extended_info
= extended_flavor_dict
[0]['extended']
3874 if extended_info
!= None:
3875 extended_flavor_dict_yaml
= yaml
.load(extended_info
, Loader
=yaml
.Loader
)
3876 if 'disks' in extended_flavor_dict_yaml
:
3877 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
3878 if vm
.get("instance_parameters") and vm
["instance_parameters"].get("devices"):
3879 for disk
in myVMDict
['disks']:
3880 if disk
.get("name") in vm
["instance_parameters"]["devices"]:
3881 disk
.update(vm
["instance_parameters"]["devices"][disk
.get("name")])
3883 vm
['vim_flavor_id'] = flavor_id
3884 myVMDict
['imageRef'] = vm
['vim_image_id']
3885 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
3886 myVMDict
['availability_zone'] = vm
.get('availability_zone')
3887 myVMDict
['networks'] = []
3888 task_depends_on
= []
3889 # TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
3890 is_management_vm
= False
3892 for iface
in vm
['interfaces']:
3894 if iface
['type'] == "data":
3895 netDict
['type'] = iface
['model']
3896 elif "model" in iface
and iface
["model"] != None:
3897 netDict
['model'] = iface
['model']
3898 # TODO in future, remove this because mac_address will not be set, and the type of PV,VF
3899 # is obtained from iterface table model
3900 # discover type of interface looking at flavor
3901 for numa
in flavor_dict
.get('extended', {}).get('numas', []):
3902 for flavor_iface
in numa
.get('interfaces', []):
3903 if flavor_iface
.get('name') == iface
['internal_name']:
3904 if flavor_iface
['dedicated'] == 'yes':
3905 netDict
['type'] = "PF" # passthrough
3906 elif flavor_iface
['dedicated'] == 'no':
3907 netDict
['type'] = "VF" # siov
3908 elif flavor_iface
['dedicated'] == 'yes:sriov':
3909 netDict
['type'] = "VFnotShared" # sriov but only one sriov on the PF
3910 netDict
["mac_address"] = flavor_iface
.get("mac_address")
3912 netDict
["use"] = iface
['type']
3913 if netDict
["use"] == "data" and not netDict
.get("type"):
3914 # print "netDict", netDict
3915 # print "iface", iface
3916 e_text
= "Cannot determine the interface type PF or VF of VNF '{}' VM '{}' iface '{}'".fromat(
3917 sce_vnf
['name'], vm
['name'], iface
['internal_name'])
3918 if flavor_dict
.get('extended') == None:
3919 raise NfvoException(e_text
+ "After database migration some information is not available. \
3920 Try to delete and create the scenarios and VNFs again", httperrors
.Conflict
)
3922 raise NfvoException(e_text
, httperrors
.Internal_Server_Error
)
3923 if netDict
["use"] == "mgmt":
3924 is_management_vm
= True
3925 netDict
["type"] = "virtual"
3926 if netDict
["use"] == "bridge":
3927 netDict
["type"] = "virtual"
3928 if iface
.get("vpci"):
3929 netDict
['vpci'] = iface
['vpci']
3930 if iface
.get("mac"):
3931 netDict
['mac_address'] = iface
['mac']
3932 if iface
.get("mac_address"):
3933 netDict
['mac_address'] = iface
['mac_address']
3934 if iface
.get("ip_address"):
3935 netDict
['ip_address'] = iface
['ip_address']
3936 if iface
.get("port-security") is not None:
3937 netDict
['port_security'] = iface
['port-security']
3938 if iface
.get("floating-ip") is not None:
3939 netDict
['floating_ip'] = iface
['floating-ip']
3940 netDict
['name'] = iface
['internal_name']
3941 if iface
['net_id'] is None:
3942 for vnf_iface
in sce_vnf
["interfaces"]:
3945 if vnf_iface
['interface_id'] == iface
['uuid']:
3946 netDict
['net_id'] = "TASK-{}".format(
3947 net2task_id
['scenario'][vnf_iface
['sce_net_id']][datacenter_id
])
3948 instance_net_id
= sce_net2instance
[vnf_iface
['sce_net_id']][datacenter_id
]
3949 task_depends_on
.append(net2task_id
['scenario'][vnf_iface
['sce_net_id']][datacenter_id
])
3952 netDict
['net_id'] = "TASK-{}".format(net2task_id
[sce_vnf
['uuid']][iface
['net_id']])
3953 instance_net_id
= vnf_net2instance
[sce_vnf
['uuid']][iface
['net_id']]
3954 task_depends_on
.append(net2task_id
[sce_vnf
['uuid']][iface
['net_id']])
3955 # skip bridge ifaces not connected to any net
3956 if 'net_id' not in netDict
or netDict
['net_id'] == None:
3958 myVMDict
['networks'].append(netDict
)
3961 # 'instance_vm_id': instance_vm_uuid,
3962 "instance_net_id": instance_net_id
,
3963 'interface_id': iface
['uuid'],
3964 # 'vim_interface_id': ,
3965 'type': 'external' if iface
['external_name'] is not None else 'internal',
3966 'ip_address': iface
.get('ip_address'),
3967 'mac_address': iface
.get('mac'),
3968 'floating_ip': int(iface
.get('floating-ip', False)),
3969 'port_security': int(iface
.get('port-security', True))
3971 db_vm_ifaces
.append(db_vm_iface
)
3972 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3973 # print myVMDict['name']
3974 # print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
3975 # print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
3976 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3978 # We add the RO key to cloud_config if vnf will need ssh access
3979 cloud_config_vm
= cloud_config
3980 if is_management_vm
and params
["instance_parameters"].get("mgmt_keys"):
3981 cloud_config_vm
= unify_cloud_config({"key-pairs": params
["instance_parameters"]["mgmt_keys"]},
3984 if vm
.get("instance_parameters") and "mgmt_keys" in vm
["instance_parameters"]:
3985 if vm
["instance_parameters"]["mgmt_keys"]:
3986 cloud_config_vm
= unify_cloud_config({"key-pairs": vm
["instance_parameters"]["mgmt_keys"]},
3989 cloud_config_vm
= unify_cloud_config(cloud_config_vm
, {"key-pairs": [RO_pub_key
]})
3990 if vm
.get("boot_data"):
3991 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config_vm
)
3993 if myVMDict
.get('availability_zone'):
3994 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
3997 for vm_index
in range(0, vm
.get('count', 1)):
3998 vm_name
= myVMDict
['name'] + "-" + str(vm_index
+1)
3999 task_params
= (vm_name
, myVMDict
['description'], myVMDict
.get('start', None),
4000 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'], cloud_config_vm
,
4001 myVMDict
['disks'], av_index
, vnf_availability_zones
)
4002 # put interface uuid back to scenario[vnfs][vms[[interfaces]
4003 for net
in myVMDict
['networks']:
4005 for iface
in vm
['interfaces']:
4006 if net
["name"] == iface
["internal_name"]:
4007 iface
["vim_id"] = net
["vim_id"]
4009 vm_uuid
= str(uuid4())
4010 uuid_list
.append(vm_uuid
)
4014 'instance_vnf_id': vnf_uuid
,
4015 # TODO delete "vim_vm_id": vm_id,
4016 "vm_id": vm
["uuid"],
4017 "vim_name": vm_name
,
4020 db_instance_vms
.append(db_vm
)
4023 for db_vm_iface
in db_vm_ifaces
:
4024 iface_uuid
= str(uuid4())
4025 uuid_list
.append(iface_uuid
)
4026 db_vm_iface_instance
= {
4028 "instance_vm_id": vm_uuid
4030 db_vm_iface_instance
.update(db_vm_iface
)
4031 if db_vm_iface_instance
.get("ip_address"): # increment ip_address
4032 ip
= db_vm_iface_instance
.get("ip_address")
4037 ip
= ip
[i
:] + str(int(ip
[:i
]) + 1)
4038 db_vm_iface_instance
["ip_address"] = ip
4040 db_vm_iface_instance
["ip_address"] = None
4041 db_instance_interfaces
.append(db_vm_iface_instance
)
4042 myVMDict
['networks'][iface_index
]["uuid"] = iface_uuid
4046 "instance_action_id": instance_action_id
,
4047 "task_index": task_index
,
4048 "datacenter_vim_id": myvim_thread_id
,
4050 "status": "SCHEDULED",
4051 "item": "instance_vms",
4054 "extra": yaml
.safe_dump({"params": task_params
, "depends_on": task_depends_on
},
4055 default_flow_style
=True, width
=256)
4058 db_vim_actions
.append(db_vim_action
)
4059 params_out
["task_index"] = task_index
4060 params_out
["uuid_list"] = uuid_list
4063 def delete_instance(mydb
, tenant_id
, instance_id
):
4064 # print "Checking that the instance_id exists and getting the instance dictionary"
4065 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
4066 # print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
4067 tenant_id
= instanceDict
["tenant_id"]
4070 # We need to retrieve the WIM Actions now, before the instance_scenario is
4071 # deleted. The reason for that is that: ON CASCADE rules will delete the
4072 # instance_wim_nets record in the database
4073 wim_actions
= wim_engine
.delete_actions(instance_scenario_id
=instance_id
)
4076 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
4077 # 1. Delete from Database
4078 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
4080 # 2. delete from VIM
4084 vimthread_affected
= {}
4085 net2vm_dependencies
= {}
4088 instance_action_id
= get_task_id()
4090 db_instance_action
= {
4091 "uuid": instance_action_id
, # same uuid for the instance and the action on create
4092 "tenant_id": tenant_id
,
4093 "instance_id": instance_id
,
4094 "description": "DELETE",
4095 # "number_tasks": 0 # filled bellow
4098 # 2.1 deleting VNFFGs
4099 for sfp
in instanceDict
.get('sfps', ()):
4100 vimthread_affected
[sfp
["datacenter_tenant_id"]] = None
4101 datacenter_key
= (sfp
["datacenter_id"], sfp
["datacenter_tenant_id"])
4102 if datacenter_key
not in myvims
:
4104 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sfp
["datacenter_id"], sfp
["datacenter_tenant_id"])
4105 except NfvoException
as e
:
4106 logger
.error(str(e
))
4108 myvim_threads
[datacenter_key
] = myvim_thread
4109 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sfp
["datacenter_id"],
4110 datacenter_tenant_id
=sfp
["datacenter_tenant_id"])
4112 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfp
["datacenter_id"], sfp
["datacenter_tenant_id"]))
4113 myvims
[datacenter_key
] = None
4115 myvims
[datacenter_key
] = next(iter(vims
.values()))
4116 myvim
= myvims
[datacenter_key
]
4117 myvim_thread
= myvim_threads
[datacenter_key
]
4120 error_msg
+= "\n vim_sfp_id={} cannot be deleted because datacenter={} not found".format(sfp
['vim_sfp_id'], sfp
["datacenter_id"])
4122 extra
= {"params": (sfp
['vim_sfp_id'])}
4124 "instance_action_id": instance_action_id
,
4125 "task_index": task_index
,
4126 "datacenter_vim_id": sfp
["datacenter_tenant_id"],
4128 "status": "SCHEDULED",
4129 "item": "instance_sfps",
4130 "item_id": sfp
["uuid"],
4131 "related": sfp
["related"],
4132 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4135 db_vim_actions
.append(db_vim_action
)
4137 for classification
in instanceDict
['classifications']:
4138 vimthread_affected
[classification
["datacenter_tenant_id"]] = None
4139 datacenter_key
= (classification
["datacenter_id"], classification
["datacenter_tenant_id"])
4140 if datacenter_key
not in myvims
:
4142 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, classification
["datacenter_id"], classification
["datacenter_tenant_id"])
4143 except NfvoException
as e
:
4144 logger
.error(str(e
))
4146 myvim_threads
[datacenter_key
] = myvim_thread
4147 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=classification
["datacenter_id"],
4148 datacenter_tenant_id
=classification
["datacenter_tenant_id"])
4150 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(classification
["datacenter_id"],
4151 classification
["datacenter_tenant_id"]))
4152 myvims
[datacenter_key
] = None
4154 myvims
[datacenter_key
] = next(iter(vims
.values()))
4155 myvim
= myvims
[datacenter_key
]
4156 myvim_thread
= myvim_threads
[datacenter_key
]
4159 error_msg
+= "\n vim_classification_id={} cannot be deleted because datacenter={} not found".format(classification
['vim_classification_id'],
4160 classification
["datacenter_id"])
4162 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfps"]
4163 extra
= {"params": (classification
['vim_classification_id']), "depends_on": depends_on
}
4165 "instance_action_id": instance_action_id
,
4166 "task_index": task_index
,
4167 "datacenter_vim_id": classification
["datacenter_tenant_id"],
4169 "status": "SCHEDULED",
4170 "item": "instance_classifications",
4171 "item_id": classification
["uuid"],
4172 "related": classification
["related"],
4173 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4176 db_vim_actions
.append(db_vim_action
)
4178 for sf
in instanceDict
.get('sfs', ()):
4179 vimthread_affected
[sf
["datacenter_tenant_id"]] = None
4180 datacenter_key
= (sf
["datacenter_id"], sf
["datacenter_tenant_id"])
4181 if datacenter_key
not in myvims
:
4183 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sf
["datacenter_id"], sf
["datacenter_tenant_id"])
4184 except NfvoException
as e
:
4185 logger
.error(str(e
))
4187 myvim_threads
[datacenter_key
] = myvim_thread
4188 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sf
["datacenter_id"],
4189 datacenter_tenant_id
=sf
["datacenter_tenant_id"])
4191 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sf
["datacenter_id"], sf
["datacenter_tenant_id"]))
4192 myvims
[datacenter_key
] = None
4194 myvims
[datacenter_key
] = next(iter(vims
.values()))
4195 myvim
= myvims
[datacenter_key
]
4196 myvim_thread
= myvim_threads
[datacenter_key
]
4199 error_msg
+= "\n vim_sf_id={} cannot be deleted because datacenter={} not found".format(sf
['vim_sf_id'], sf
["datacenter_id"])
4201 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfps"]
4202 extra
= {"params": (sf
['vim_sf_id']), "depends_on": depends_on
}
4204 "instance_action_id": instance_action_id
,
4205 "task_index": task_index
,
4206 "datacenter_vim_id": sf
["datacenter_tenant_id"],
4208 "status": "SCHEDULED",
4209 "item": "instance_sfs",
4210 "item_id": sf
["uuid"],
4211 "related": sf
["related"],
4212 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4215 db_vim_actions
.append(db_vim_action
)
4217 for sfi
in instanceDict
.get('sfis', ()):
4218 vimthread_affected
[sfi
["datacenter_tenant_id"]] = None
4219 datacenter_key
= (sfi
["datacenter_id"], sfi
["datacenter_tenant_id"])
4220 if datacenter_key
not in myvims
:
4222 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sfi
["datacenter_id"], sfi
["datacenter_tenant_id"])
4223 except NfvoException
as e
:
4224 logger
.error(str(e
))
4226 myvim_threads
[datacenter_key
] = myvim_thread
4227 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sfi
["datacenter_id"],
4228 datacenter_tenant_id
=sfi
["datacenter_tenant_id"])
4230 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfi
["datacenter_id"], sfi
["datacenter_tenant_id"]))
4231 myvims
[datacenter_key
] = None
4233 myvims
[datacenter_key
] = next(iter(vims
.values()))
4234 myvim
= myvims
[datacenter_key
]
4235 myvim_thread
= myvim_threads
[datacenter_key
]
4238 error_msg
+= "\n vim_sfi_id={} cannot be deleted because datacenter={} not found".format(sfi
['vim_sfi_id'], sfi
["datacenter_id"])
4240 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfs"]
4241 extra
= {"params": (sfi
['vim_sfi_id']), "depends_on": depends_on
}
4243 "instance_action_id": instance_action_id
,
4244 "task_index": task_index
,
4245 "datacenter_vim_id": sfi
["datacenter_tenant_id"],
4247 "status": "SCHEDULED",
4248 "item": "instance_sfis",
4249 "item_id": sfi
["uuid"],
4250 "related": sfi
["related"],
4251 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4254 db_vim_actions
.append(db_vim_action
)
4258 for sce_vnf
in instanceDict
.get('vnfs', ()):
4259 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
4260 vimthread_affected
[sce_vnf
["datacenter_tenant_id"]] = None
4261 if datacenter_key
not in myvims
:
4263 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
4264 except NfvoException
as e
:
4265 logger
.error(str(e
))
4267 myvim_threads
[datacenter_key
] = myvim_thread
4268 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
4269 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
4271 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
4272 sce_vnf
["datacenter_tenant_id"]))
4273 myvims
[datacenter_key
] = None
4275 myvims
[datacenter_key
] = next(iter(vims
.values()))
4276 myvim
= myvims
[datacenter_key
]
4277 myvim_thread
= myvim_threads
[datacenter_key
]
4279 for vm
in sce_vnf
['vms']:
4281 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
4283 sfi_dependencies
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfis"]
4285 "instance_action_id": instance_action_id
,
4286 "task_index": task_index
,
4287 "datacenter_vim_id": sce_vnf
["datacenter_tenant_id"],
4289 "status": "SCHEDULED",
4290 "item": "instance_vms",
4291 "item_id": vm
["uuid"],
4292 "related": vm
["related"],
4293 "extra": yaml
.safe_dump({"params": vm
["interfaces"], "depends_on": sfi_dependencies
},
4294 default_flow_style
=True, width
=256)
4296 db_vim_actions
.append(db_vim_action
)
4297 for interface
in vm
["interfaces"]:
4298 if not interface
.get("instance_net_id"):
4300 if interface
["instance_net_id"] not in net2vm_dependencies
:
4301 net2vm_dependencies
[interface
["instance_net_id"]] = []
4302 net2vm_dependencies
[interface
["instance_net_id"]].append(task_index
)
4307 for net
in instanceDict
['nets']:
4308 vimthread_affected
[net
["datacenter_tenant_id"]] = None
4309 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
4310 if datacenter_key
not in myvims
:
4312 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, net
["datacenter_id"], net
["datacenter_tenant_id"])
4313 except NfvoException
as e
:
4314 logger
.error(str(e
))
4316 myvim_threads
[datacenter_key
] = myvim_thread
4317 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
4318 datacenter_tenant_id
=net
["datacenter_tenant_id"])
4320 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
4321 myvims
[datacenter_key
] = None
4323 myvims
[datacenter_key
] = next(iter(vims
.values()))
4324 myvim
= myvims
[datacenter_key
]
4325 myvim_thread
= myvim_threads
[datacenter_key
]
4328 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
4330 extra
= {"params": (net
['vim_net_id'], net
['sdn_net_id'])}
4331 if net2vm_dependencies
.get(net
["uuid"]):
4332 extra
["depends_on"] = net2vm_dependencies
[net
["uuid"]]
4333 sfi_dependencies
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfis"]
4334 if len(sfi_dependencies
) > 0:
4335 if "depends_on" in extra
:
4336 extra
["depends_on"] += sfi_dependencies
4338 extra
["depends_on"] = sfi_dependencies
4340 "instance_action_id": instance_action_id
,
4341 "task_index": task_index
,
4342 "datacenter_vim_id": net
["datacenter_tenant_id"],
4344 "status": "SCHEDULED",
4345 "item": "instance_nets",
4346 "item_id": net
["uuid"],
4347 "related": net
["related"],
4348 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4351 db_vim_actions
.append(db_vim_action
)
4353 db_instance_action
["number_tasks"] = task_index
4356 wim_actions
, db_instance_action
= (
4357 wim_engine
.incorporate_actions(wim_actions
, db_instance_action
))
4361 {"instance_actions": db_instance_action
},
4362 {"vim_wim_actions": db_vim_actions
+ wim_actions
}
4365 logger
.debug("delete_instance done DB tables: %s",
4366 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
4367 mydb
.new_rows(db_tables
, ())
4368 for myvim_thread_id
in vimthread_affected
.keys():
4369 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
4371 wim_engine
.dispatch(wim_actions
)
4373 if len(error_msg
) > 0:
4374 return 'action_id={} instance {} deleted but some elements could not be deleted, or already deleted '\
4375 '(error: 404) from VIM: {}'.format(instance_action_id
, message
, error_msg
)
4377 return "action_id={} instance {} deleted".format(instance_action_id
, message
)
4379 def get_instance_id(mydb
, tenant_id
, instance_id
):
4381 #check valid tenant_id
4382 check_tenant(mydb
, tenant_id
)
4385 instance_dict
= mydb
.get_instance_scenario(instance_id
, tenant_id
, verbose
=True)
4386 for net
in instance_dict
["nets"]:
4387 if net
.get("sdn_net_id"):
4388 net_sdn
= ovim
.show_network(net
["sdn_net_id"])
4390 "admin_state_up": net_sdn
.get("admin_state_up"),
4391 "flows": net_sdn
.get("flows"),
4392 "last_error": net_sdn
.get("last_error"),
4393 "ports": net_sdn
.get("ports"),
4394 "type": net_sdn
.get("type"),
4395 "status": net_sdn
.get("status"),
4396 "vlan": net_sdn
.get("vlan"),
4398 return instance_dict
4400 @deprecated("Instance is automatically refreshed by vim_threads")
4401 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
4402 '''Refreshes a scenario instance. It modifies instanceDict'''
4404 - result: <0 if there is any unexpected error, n>=0 if no errors where n is the number of vms and nets that couldn't be updated in the database
4407 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
4408 # #print "nfvo.refresh_instance begins"
4409 # #print json.dumps(instanceDict, indent=4)
4411 # #print "Getting the VIM URL and the VIM tenant_id"
4414 # # 1. Getting VIM vm and net list
4415 # vms_updated = [] #List of VM instance uuids in openmano that were updated
4418 # for sce_vnf in instanceDict['vnfs']:
4419 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
4420 # if datacenter_key not in vm_list:
4421 # vm_list[datacenter_key] = []
4422 # if datacenter_key not in myvims:
4423 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
4424 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
4425 # if len(vims) == 0:
4426 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
4427 # myvims[datacenter_key] = None
4429 # myvims[datacenter_key] = next(iter(vims.values()))
4430 # for vm in sce_vnf['vms']:
4431 # vm_list[datacenter_key].append(vm['vim_vm_id'])
4432 # vms_notupdated.append(vm["uuid"])
4434 # nets_updated = [] #List of VM instance uuids in openmano that were updated
4435 # nets_notupdated=[]
4437 # for net in instanceDict['nets']:
4438 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
4439 # if datacenter_key not in net_list:
4440 # net_list[datacenter_key] = []
4441 # if datacenter_key not in myvims:
4442 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
4443 # datacenter_tenant_id=net["datacenter_tenant_id"])
4444 # if len(vims) == 0:
4445 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
4446 # myvims[datacenter_key] = None
4448 # myvims[datacenter_key] = next(iter(vims.values()))
4450 # net_list[datacenter_key].append(net['vim_net_id'])
4451 # nets_notupdated.append(net["uuid"])
4453 # # 1. Getting the status of all VMs
4455 # for datacenter_key in myvims:
4456 # if not vm_list.get(datacenter_key):
4460 # if not myvims[datacenter_key]:
4461 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
4464 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
4466 # except vimconn.vimconnException as e:
4467 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
4468 # failed_message = str(e)
4470 # for vm in vm_list[datacenter_key]:
4471 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
4473 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
4474 # for sce_vnf in instanceDict['vnfs']:
4475 # for vm in sce_vnf['vms']:
4476 # vm_id = vm['vim_vm_id']
4477 # interfaces = vm_dict[vm_id].pop('interfaces', [])
4478 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
4479 # has_mgmt_iface = False
4480 # for iface in vm["interfaces"]:
4481 # if iface["type"]=="mgmt":
4482 # has_mgmt_iface = True
4483 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
4484 # vm_dict[vm_id]['status'] = "ACTIVE"
4485 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
4486 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
4487 # if vm['status'] != vm_dict[vm_id]['status'] or vm.get('error_msg')!=vm_dict[vm_id].get('error_msg') or vm.get('vim_info')!=vm_dict[vm_id].get('vim_info'):
4488 # vm['status'] = vm_dict[vm_id]['status']
4489 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
4490 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
4491 # # 2.1. Update in openmano DB the VMs whose status changed
4493 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
4494 # vms_notupdated.remove(vm["uuid"])
4496 # vms_updated.append(vm["uuid"])
4497 # except db_base_Exception as e:
4498 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
4499 # # 2.2. Update in openmano DB the interface VMs
4500 # for interface in interfaces:
4501 # #translate from vim_net_id to instance_net_id
4502 # network_id_list=[]
4503 # for net in instanceDict['nets']:
4504 # if net["vim_net_id"] == interface["vim_net_id"]:
4505 # network_id_list.append(net["uuid"])
4506 # if not network_id_list:
4508 # del interface["vim_net_id"]
4510 # for network_id in network_id_list:
4511 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
4512 # except db_base_Exception as e:
4513 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
4515 # # 3. Getting the status of all nets
4517 # for datacenter_key in myvims:
4518 # if not net_list.get(datacenter_key):
4521 # failed_message = ""
4522 # if not myvims[datacenter_key]:
4523 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
4526 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
4528 # except vimconn.vimconnException as e:
4529 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
4530 # failed_message = str(e)
4532 # for net in net_list[datacenter_key]:
4533 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
4535 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
4536 # # TODO: update nets inside a vnf
4537 # for net in instanceDict['nets']:
4538 # net_id = net['vim_net_id']
4539 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
4540 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
4541 # if net['status'] != net_dict[net_id]['status'] or net.get('error_msg')!=net_dict[net_id].get('error_msg') or net.get('vim_info')!=net_dict[net_id].get('vim_info'):
4542 # net['status'] = net_dict[net_id]['status']
4543 # net['error_msg'] = net_dict[net_id].get('error_msg')
4544 # net['vim_info'] = net_dict[net_id].get('vim_info')
4545 # # 5.1. Update in openmano DB the nets whose status changed
4547 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
4548 # nets_notupdated.remove(net["uuid"])
4550 # nets_updated.append(net["uuid"])
4551 # except db_base_Exception as e:
4552 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
4554 # # Returns appropriate output
4555 # #print "nfvo.refresh_instance finishes"
4556 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
4557 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
4558 instance_id
= instanceDict
['uuid']
4559 # if len(vms_notupdated)+len(nets_notupdated)>0:
4560 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
4561 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
4563 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
4565 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
4566 #print "Checking that the instance_id exists and getting the instance dictionary"
4567 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
4568 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
4570 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
4571 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
4573 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), httperrors
.Not_Found
)
4574 myvim
= next(iter(vims
.values()))
4579 myvim_threads_id
= {}
4580 if action_dict
.get("vdu-scaling"):
4581 db_instance_vms
= []
4583 db_instance_interfaces
= []
4584 instance_action_id
= get_task_id()
4585 db_instance_action
= {
4586 "uuid": instance_action_id
, # same uuid for the instance and the action on create
4587 "tenant_id": nfvo_tenant
,
4588 "instance_id": instance_id
,
4589 "description": "SCALE",
4591 vm_result
["instance_action_id"] = instance_action_id
4592 vm_result
["created"] = []
4593 vm_result
["deleted"] = []
4595 for vdu
in action_dict
["vdu-scaling"]:
4596 vdu_id
= vdu
.get("vdu-id")
4597 osm_vdu_id
= vdu
.get("osm_vdu_id")
4598 member_vnf_index
= vdu
.get("member-vnf-index")
4599 vdu_count
= vdu
.get("count", 1)
4601 target_vms
= mydb
.get_rows(
4602 FROM
="instance_vms as vms join instance_vnfs as vnfs on vms.instance_vnf_id=vnfs.uuid",
4603 WHERE
={"vms.uuid": vdu_id
},
4604 ORDER_BY
="vms.created_at"
4607 raise NfvoException("Cannot find the vdu with id {}".format(vdu_id
), httperrors
.Not_Found
)
4609 if not osm_vdu_id
and not member_vnf_index
:
4610 raise NfvoException("Invalid input vdu parameters. Must supply either 'vdu-id' of 'osm_vdu_id','member-vnf-index'")
4611 target_vms
= mydb
.get_rows(
4612 # SELECT=("ivms.uuid", "ivnfs.datacenter_id", "ivnfs.datacenter_tenant_id"),
4613 FROM
="instance_vms as ivms join instance_vnfs as ivnfs on ivms.instance_vnf_id=ivnfs.uuid"\
4614 " join sce_vnfs as svnfs on ivnfs.sce_vnf_id=svnfs.uuid"\
4615 " join vms on ivms.vm_id=vms.uuid",
4616 WHERE
={"vms.osm_id": osm_vdu_id
, "svnfs.member_vnf_index": member_vnf_index
,
4617 "ivnfs.instance_scenario_id": instance_id
},
4618 ORDER_BY
="ivms.created_at"
4621 raise NfvoException("Cannot find the vdu with osm_vdu_id {} and member-vnf-index {}".format(osm_vdu_id
, member_vnf_index
), httperrors
.Not_Found
)
4622 vdu_id
= target_vms
[-1]["uuid"]
4623 target_vm
= target_vms
[-1]
4624 datacenter
= target_vm
["datacenter_id"]
4625 myvim_threads_id
[datacenter
], _
= get_vim_thread(mydb
, nfvo_tenant
, datacenter
)
4627 if vdu
["type"] == "delete":
4628 for index
in range(0, vdu_count
):
4629 target_vm
= target_vms
[-1-index
]
4630 vdu_id
= target_vm
["uuid"]
4632 vm_interfaces
= None
4633 for sce_vnf
in instanceDict
['vnfs']:
4634 for vm
in sce_vnf
['vms']:
4635 if vm
["uuid"] == vdu_id
:
4636 # TODO revise this should not be vm["uuid"] instance_vms["vm_id"]
4637 vm_interfaces
= vm
["interfaces"]
4641 "instance_action_id": instance_action_id
,
4642 "task_index": task_index
,
4643 "datacenter_vim_id": target_vm
["datacenter_tenant_id"],
4645 "status": "SCHEDULED",
4646 "item": "instance_vms",
4648 "related": target_vm
["related"],
4649 "extra": yaml
.safe_dump({"params": vm_interfaces
},
4650 default_flow_style
=True, width
=256)
4653 db_vim_actions
.append(db_vim_action
)
4654 vm_result
["deleted"].append(vdu_id
)
4655 # delete from database
4656 db_instance_vms
.append({"TO-DELETE": vdu_id
})
4658 else: # vdu["type"] == "create":
4660 where
= {"item": "instance_vms", "item_id": target_vm
["uuid"], "action": "CREATE"}
4662 vim_action_to_clone
= mydb
.get_rows(FROM
="vim_wim_actions", WHERE
=where
)
4663 if not vim_action_to_clone
:
4664 raise NfvoException("Cannot find the vim_action at database with {}".format(where
), httperrors
.Internal_Server_Error
)
4665 vim_action_to_clone
= vim_action_to_clone
[0]
4666 extra
= yaml
.safe_load(vim_action_to_clone
["extra"])
4668 # generate a new depends_on. Convert format TASK-Y into new format TASK-ACTION-XXXX.XXXX.Y
4669 # TODO do the same for flavor and image when available
4670 task_depends_on
= []
4671 task_params
= extra
["params"]
4672 task_params_networks
= deepcopy(task_params
[5])
4673 for iface
in task_params
[5]:
4674 if iface
["net_id"].startswith("TASK-"):
4675 if "." not in iface
["net_id"]:
4676 task_depends_on
.append("{}.{}".format(vim_action_to_clone
["instance_action_id"],
4677 iface
["net_id"][5:]))
4678 iface
["net_id"] = "TASK-{}.{}".format(vim_action_to_clone
["instance_action_id"],
4679 iface
["net_id"][5:])
4681 task_depends_on
.append(iface
["net_id"][5:])
4682 if "mac_address" in iface
:
4683 del iface
["mac_address"]
4685 vm_ifaces_to_clone
= mydb
.get_rows(FROM
="instance_interfaces", WHERE
={"instance_vm_id": target_vm
["uuid"]})
4686 for index
in range(0, vdu_count
):
4687 vm_uuid
= str(uuid4())
4688 vm_name
= target_vm
.get('vim_name')
4690 suffix
= vm_name
.rfind("-")
4691 vm_name
= vm_name
[:suffix
+1] + str(index
+ 1 + int(vm_name
[suffix
+1:]))
4697 'instance_vnf_id': target_vm
['instance_vnf_id'],
4698 'vm_id': target_vm
['vm_id'],
4699 'vim_name': vm_name
,
4701 db_instance_vms
.append(db_instance_vm
)
4703 for vm_iface
in vm_ifaces_to_clone
:
4704 iface_uuid
= str(uuid4())
4705 iface2iface
[vm_iface
["uuid"]] = iface_uuid
4708 'instance_vm_id': vm_uuid
,
4709 "instance_net_id": vm_iface
["instance_net_id"],
4710 'interface_id': vm_iface
['interface_id'],
4711 'type': vm_iface
['type'],
4712 'floating_ip': vm_iface
['floating_ip'],
4713 'port_security': vm_iface
['port_security']
4715 db_instance_interfaces
.append(db_vm_iface
)
4716 task_params_copy
= deepcopy(task_params
)
4717 for iface
in task_params_copy
[5]:
4718 iface
["uuid"] = iface2iface
[iface
["uuid"]]
4719 # increment ip_address
4720 if "ip_address" in iface
:
4721 ip
= iface
.get("ip_address")
4726 ip
= ip
[i
:] + str(int(ip
[:i
]) + 1)
4727 iface
["ip_address"] = ip
4729 iface
["ip_address"] = None
4731 task_params_copy
[0] = vm_name
4733 "instance_action_id": instance_action_id
,
4734 "task_index": task_index
,
4735 "datacenter_vim_id": vim_action_to_clone
["datacenter_vim_id"],
4737 "status": "SCHEDULED",
4738 "item": "instance_vms",
4743 # TODO examinar parametros, quitar MAC o incrementar. Incrementar IP y colocar las dependencias con ACTION-asdfasd.
4746 "extra": yaml
.safe_dump({"params": task_params_copy
, "depends_on": task_depends_on
}, default_flow_style
=True, width
=256)
4749 db_vim_actions
.append(db_vim_action
)
4750 vm_result
["created"].append(vm_uuid
)
4752 db_instance_action
["number_tasks"] = task_index
4754 {"instance_vms": db_instance_vms
},
4755 {"instance_interfaces": db_instance_interfaces
},
4756 {"instance_actions": db_instance_action
},
4758 # {"instance_sfis": db_instance_sfis},
4759 # {"instance_sfs": db_instance_sfs},
4760 # {"instance_classifications": db_instance_classifications},
4761 # {"instance_sfps": db_instance_sfps},
4762 {"vim_wim_actions": db_vim_actions
}
4764 logger
.debug("create_vdu done DB tables: %s",
4765 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
4766 mydb
.new_rows(db_tables
, [])
4767 for myvim_thread
in myvim_threads_id
.values():
4768 vim_threads
["running"][myvim_thread
].insert_task(db_vim_actions
)
4772 input_vnfs
= action_dict
.pop("vnfs", [])
4773 input_vms
= action_dict
.pop("vms", [])
4774 action_over_all
= True if not input_vnfs
and not input_vms
else False
4775 for sce_vnf
in instanceDict
['vnfs']:
4776 for vm
in sce_vnf
['vms']:
4777 if not action_over_all
and sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
4778 sce_vnf
['member_vnf_index'] not in input_vnfs
and \
4779 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
and \
4780 sce_vnf
['member_vnf_index'] + "-" + vm
['vdu_osm_id'] not in input_vms
: # TODO conside vm_count_index
4783 if "add_public_key" in action_dict
:
4784 if sce_vnf
.get('mgmt_access'):
4785 mgmt_access
= yaml
.load(sce_vnf
['mgmt_access'], Loader
=yaml
.Loader
)
4786 if not input_vms
and mgmt_access
.get("vdu-id") != vm
['vdu_osm_id']:
4788 default_user
= mgmt_access
.get("default-user")
4789 password
= mgmt_access
.get("password")
4790 if mgmt_access
.get(vm
['vdu_osm_id']):
4791 default_user
= mgmt_access
[vm
['vdu_osm_id']].get("default-user", default_user
)
4792 password
= mgmt_access
[vm
['vdu_osm_id']].get("password", password
)
4794 tenant
= mydb
.get_rows_by_id('nfvo_tenants', nfvo_tenant
)
4796 if 'ip_address' in vm
:
4797 mgmt_ip
= vm
['ip_address'].split(';')
4798 priv_RO_key
= decrypt_key(tenant
[0]['encrypted_RO_priv_key'], tenant
[0]['uuid'])
4799 data
= myvim
.inject_user_key(mgmt_ip
[0], action_dict
.get('user', default_user
),
4800 action_dict
['add_public_key'],
4801 password
=password
, ro_key
=priv_RO_key
)
4802 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4803 "description": "Public key injected",
4808 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4809 httperrors
.Internal_Server_Error
)
4811 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4812 httperrors
.Internal_Server_Error
)
4814 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
4815 if "console" in action_dict
:
4816 if not global_config
["http_console_proxy"]:
4817 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4818 "description": "{protocol}//{ip}:{port}/{suffix}".format(
4819 protocol
=data
["protocol"],
4820 ip
= data
["server"],
4821 port
= data
["port"],
4822 suffix
= data
["suffix"]),
4826 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
4827 vm_result
[ vm
['uuid'] ] = {"vim_result": -httperrors
.Unauthorized
,
4828 "description": "this console is only reachable by local interface",
4833 #print "console data", data
4835 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
4836 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4837 "description": "{protocol}//{ip}:{port}/{suffix}".format(
4838 protocol
=data
["protocol"],
4839 ip
= global_config
["http_console_host"],
4840 port
= console_thread
.port
,
4841 suffix
= data
["suffix"]),
4845 except NfvoException
as e
:
4846 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
4850 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
4852 except vimconn
.vimconnException
as e
:
4853 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
4856 if vm_ok
==0: #all goes wrong
4861 def instance_action_get(mydb
, nfvo_tenant
, instance_id
, action_id
):
4863 if nfvo_tenant
and nfvo_tenant
!= "any":
4864 filter["tenant_id"] = nfvo_tenant
4865 if instance_id
and instance_id
!= "any":
4866 filter["instance_id"] = instance_id
4868 filter["uuid"] = action_id
4869 rows
= mydb
.get_rows(FROM
="instance_actions", WHERE
=filter)
4872 raise NfvoException("Not found any action with this criteria", httperrors
.Not_Found
)
4873 vim_wim_actions
= mydb
.get_rows(FROM
="vim_wim_actions", WHERE
={"instance_action_id": action_id
})
4874 rows
[0]["vim_wim_actions"] = vim_wim_actions
4875 # for backward compatibility set vim_actions = vim_wim_actions
4876 rows
[0]["vim_actions"] = vim_wim_actions
4877 return {"actions": rows
}
4880 def create_or_use_console_proxy_thread(console_server
, console_port
):
4881 #look for a non-used port
4882 console_thread_key
= console_server
+ ":" + str(console_port
)
4883 if console_thread_key
in global_config
["console_thread"]:
4884 #global_config["console_thread"][console_thread_key].start_timeout()
4885 return global_config
["console_thread"][console_thread_key
]
4887 for port
in global_config
["console_port_iterator"]():
4888 #print "create_or_use_console_proxy_thread() port:", port
4889 if port
in global_config
["console_ports"]:
4892 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
4894 global_config
["console_thread"][console_thread_key
] = clithread
4895 global_config
["console_ports"][port
] = console_thread_key
4897 except cli
.ConsoleProxyExceptionPortUsed
as e
:
4898 #port used, try with onoher
4900 except cli
.ConsoleProxyException
as e
:
4901 raise NfvoException(str(e
), httperrors
.Bad_Request
)
4902 raise NfvoException("Not found any free 'http_console_ports'", httperrors
.Conflict
)
4905 def check_tenant(mydb
, tenant_id
):
4906 '''check that tenant exists at database'''
4907 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
4909 raise NfvoException("tenant '{}' not found".format(tenant_id
), httperrors
.Not_Found
)
4912 def new_tenant(mydb
, tenant_dict
):
4914 tenant_uuid
= str(uuid4())
4915 tenant_dict
['uuid'] = tenant_uuid
4917 pub_key
, priv_key
= create_RO_keypair(tenant_uuid
)
4918 tenant_dict
['RO_pub_key'] = pub_key
4919 tenant_dict
['encrypted_RO_priv_key'] = priv_key
4920 mydb
.new_row("nfvo_tenants", tenant_dict
, confidential_data
=True)
4921 except db_base_Exception
as e
:
4922 raise NfvoException("Error creating the new tenant: {} ".format(tenant_dict
['name']) + str(e
), e
.http_code
)
4925 def delete_tenant(mydb
, tenant
):
4926 #get nfvo_tenant info
4928 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
4929 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
4930 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
4933 def new_datacenter(mydb
, datacenter_descriptor
):
4934 sdn_port_mapping
= None
4935 if "config" in datacenter_descriptor
:
4936 sdn_port_mapping
= datacenter_descriptor
["config"].pop("sdn-port-mapping", None)
4937 datacenter_descriptor
["config"] = yaml
.safe_dump(datacenter_descriptor
["config"], default_flow_style
=True,
4939 # Check that datacenter-type is correct
4940 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
4941 # module_info = None
4944 plugin_name
= "rovim_" + datacenter_type
4945 if plugin_name
not in plugins
:
4946 _load_vim_plugin(plugin_name
)
4948 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True, confidential_data
=True)
4949 if sdn_port_mapping
:
4951 datacenter_sdn_port_mapping_set(mydb
, None, datacenter_id
, sdn_port_mapping
)
4952 except Exception as e
:
4953 mydb
.delete_row_by_id("datacenters", datacenter_id
) # Rollback
4955 return datacenter_id
4958 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
4959 # obtain data, check that only one exist
4960 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
4963 datacenter_id
= datacenter
['uuid']
4964 where
= {'uuid': datacenter
['uuid']}
4965 remove_port_mapping
= False
4966 new_sdn_port_mapping
= None
4967 if "config" in datacenter_descriptor
:
4968 if datacenter_descriptor
['config'] != None:
4970 new_config_dict
= datacenter_descriptor
["config"]
4971 if "sdn-port-mapping" in new_config_dict
:
4972 remove_port_mapping
= True
4973 new_sdn_port_mapping
= new_config_dict
.pop("sdn-port-mapping")
4974 # delete null fields
4976 for k
in new_config_dict
:
4977 if new_config_dict
[k
] is None:
4979 if k
== 'sdn-controller':
4980 remove_port_mapping
= True
4982 config_text
= datacenter
.get("config")
4985 config_dict
= yaml
.load(config_text
, Loader
=yaml
.Loader
)
4986 config_dict
.update(new_config_dict
)
4987 # delete null fields
4990 except Exception as e
:
4991 raise NfvoException("Bad format at datacenter:config " + str(e
), httperrors
.Bad_Request
)
4993 datacenter_descriptor
["config"] = yaml
.safe_dump(config_dict
, default_flow_style
=True, width
=256)
4995 datacenter_descriptor
["config"] = None
4996 if remove_port_mapping
:
4998 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_id
)
4999 except ovimException
as e
:
5000 raise NfvoException("Error deleting datacenter-port-mapping " + str(e
), httperrors
.Conflict
)
5002 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
5003 if new_sdn_port_mapping
:
5005 datacenter_sdn_port_mapping_set(mydb
, None, datacenter_id
, new_sdn_port_mapping
)
5006 except ovimException
as e
:
5008 mydb
.update_rows('datacenters', datacenter
, where
)
5009 raise NfvoException("Error adding datacenter-port-mapping " + str(e
), httperrors
.Conflict
)
5010 return datacenter_id
5013 def delete_datacenter(mydb
, datacenter
):
5014 #get nfvo_tenant info
5015 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
5016 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
5018 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_dict
['uuid'])
5019 except ovimException
as e
:
5020 raise NfvoException("Error deleting datacenter-port-mapping " + str(e
))
5021 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
5024 def create_vim_account(mydb
, nfvo_tenant
, datacenter_id
, name
=None, vim_id
=None, vim_tenant
=None, vim_tenant_name
=None,
5025 vim_username
=None, vim_password
=None, config
=None):
5026 # get datacenter info
5028 if not datacenter_id
:
5030 raise NfvoException("You must provide 'vim_id", http_code
=httperrors
.Bad_Request
)
5031 datacenter_id
= vim_id
5032 datacenter_id
, datacenter_name
= get_datacenter_uuid(mydb
, None, datacenter_id
)
5034 create_vim_tenant
= True if not vim_tenant
and not vim_tenant_name
else False
5036 # get nfvo_tenant info
5037 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
5038 if vim_tenant_name
==None:
5039 vim_tenant_name
=tenant_dict
['name']
5041 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
5042 # #check that this association does not exist before
5043 # tenants_datacenters = mydb.get_rows(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict)
5044 # if len(tenants_datacenters)>0:
5045 # raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id, tenant_dict['uuid']), httperrors.Conflict)
5047 vim_tenant_id_exist_atdb
=False
5048 if not create_vim_tenant
:
5049 where_
={"datacenter_id": datacenter_id
}
5050 if vim_tenant
!=None:
5051 where_
["vim_tenant_id"] = vim_tenant
5052 if vim_tenant_name
!=None:
5053 where_
["vim_tenant_name"] = vim_tenant_name
5054 #check if vim_tenant_id is already at database
5055 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
5056 if len(datacenter_tenants_dict
)>=1:
5057 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
5058 vim_tenant_id_exist_atdb
=True
5059 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
5061 datacenter_tenants_dict
= {}
5062 #insert at table datacenter_tenants
5063 else: #if vim_tenant==None:
5064 #create tenant at VIM if not provided
5066 _
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
, vim_user
=vim_username
,
5067 vim_passwd
=vim_password
)
5068 datacenter_name
= myvim
["name"]
5069 vim_tenant
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
5070 except vimconn
.vimconnException
as e
:
5071 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), httperrors
.Internal_Server_Error
)
5072 datacenter_tenants_dict
= {}
5073 datacenter_tenants_dict
["created"]="true"
5075 #fill datacenter_tenants table
5076 if not vim_tenant_id_exist_atdb
:
5077 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant
5078 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
5079 datacenter_tenants_dict
["user"] = vim_username
5080 datacenter_tenants_dict
["passwd"] = vim_password
5081 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
5083 datacenter_tenants_dict
["name"] = name
5085 datacenter_tenants_dict
["name"] = datacenter_name
5087 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
5088 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True, confidential_data
=True)
5089 datacenter_tenants_dict
["uuid"] = id_
5091 #fill tenants_datacenters table
5092 datacenter_tenant_id
= datacenter_tenants_dict
["uuid"]
5093 tenants_datacenter_dict
["datacenter_tenant_id"] = datacenter_tenant_id
5094 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
5097 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
5098 new_thread
= vim_thread(task_lock
, plugins
, thread_name
, datacenter_name
, datacenter_tenant_id
,
5099 db
=db
, db_lock
=db_lock
, ovim
=ovim
)
5101 thread_id
= datacenter_tenants_dict
["uuid"]
5102 vim_threads
["running"][thread_id
] = new_thread
5104 except vimconn
.vimconnException
as e
:
5105 raise NfvoException(str(e
), httperrors
.Bad_Request
)
5108 def edit_vim_account(mydb
, nfvo_tenant
, datacenter_tenant_id
, datacenter_id
=None, name
=None, vim_tenant
=None,
5109 vim_tenant_name
=None, vim_username
=None, vim_password
=None, config
=None):
5111 # get vim_account; check is valid for this tenant
5112 from_
= "datacenter_tenants as dt JOIN tenants_datacenters as td ON dt.uuid=td.datacenter_tenant_id"
5113 where_
= {"td.nfvo_tenant_id": nfvo_tenant
}
5114 if datacenter_tenant_id
:
5115 where_
["dt.uuid"] = datacenter_tenant_id
5117 where_
["dt.datacenter_id"] = datacenter_id
5118 vim_accounts
= mydb
.get_rows(SELECT
="dt.uuid as uuid, config", FROM
=from_
, WHERE
=where_
)
5119 if not vim_accounts
:
5120 raise NfvoException("vim_account not found for this tenant", http_code
=httperrors
.Not_Found
)
5121 elif len(vim_accounts
) > 1:
5122 raise NfvoException("found more than one vim_account for this tenant", http_code
=httperrors
.Conflict
)
5123 datacenter_tenant_id
= vim_accounts
[0]["uuid"]
5124 original_config
= vim_accounts
[0]["config"]
5128 original_config_dict
= yaml
.load(original_config
, Loader
=yaml
.Loader
)
5129 original_config_dict
.update(config
)
5130 update
["config"] = yaml
.safe_dump(original_config_dict
, default_flow_style
=True, width
=256)
5132 update_
['name'] = name
5134 update_
['vim_tenant_id'] = vim_tenant
5136 update_
['vim_tenant_name'] = vim_tenant_name
5138 update_
['user'] = vim_username
5140 update_
['passwd'] = vim_password
5142 mydb
.update_rows("datacenter_tenants", UPDATE
=update_
, WHERE
={"uuid": datacenter_tenant_id
})
5144 vim_threads
["running"][datacenter_tenant_id
].insert_task("reload")
5145 return datacenter_tenant_id
5147 def delete_vim_account(mydb
, tenant_id
, vim_account_id
, datacenter
=None):
5148 #get nfvo_tenant info
5149 if not tenant_id
or tenant_id
=="any":
5152 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
5153 tenant_uuid
= tenant_dict
['uuid']
5155 #check that this association exist before
5156 tenants_datacenter_dict
= {}
5158 datacenter_id
, _
= get_datacenter_uuid(mydb
, tenant_uuid
, datacenter
)
5159 tenants_datacenter_dict
["datacenter_id"] = datacenter_id
5160 elif vim_account_id
:
5161 tenants_datacenter_dict
["datacenter_tenant_id"] = vim_account_id
5163 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
5164 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
5165 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
5166 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), httperrors
.Not_Found
)
5168 #delete this association
5169 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
5171 #get vim_tenant info and deletes
5173 for tenant_datacenter_item
in tenant_datacenter_list
:
5174 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
5175 #try to delete vim:tenant
5177 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
5178 if vim_tenant_dict
['created']=='true':
5179 #delete tenant at VIM if created by NFVO
5181 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5182 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
5183 except vimconn
.vimconnException
as e
:
5184 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
5185 logger
.warn(warning
)
5186 except db_base_Exception
as e
:
5187 logger
.error("Cannot delete datacenter_tenants " + str(e
))
5188 pass # the error will be caused because dependencies, vim_tenant can not be deleted
5189 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
5190 thread
= vim_threads
["running"].get(thread_id
)
5192 thread
.insert_task("exit")
5193 vim_threads
["deleting"][thread_id
] = thread
5194 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
5197 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
5199 #get datacenter info
5200 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5202 if 'check-connectivity' in action_dict
:
5204 myvim
.check_vim_connectivity()
5205 except vimconn
.vimconnException
as e
:
5206 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
5207 raise NfvoException(str(e
), e
.http_code
)
5208 elif 'net-update' in action_dict
:
5210 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
5212 except vimconn
.vimconnException
as e
:
5213 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
5214 raise NfvoException(str(e
), httperrors
.Internal_Server_Error
)
5215 #update nets Change from VIM format to NFVO format
5218 net_nfvo
={'datacenter_id': datacenter_id
}
5219 net_nfvo
['name'] = net
['name']
5220 #net_nfvo['description']= net['name']
5221 net_nfvo
['vim_net_id'] = net
['id']
5222 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
5223 net_nfvo
['shared'] = net
['shared']
5224 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
5225 net_list
.append(net_nfvo
)
5226 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
5227 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
5229 elif 'net-edit' in action_dict
:
5230 net
= action_dict
['net-edit'].pop('net')
5231 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
5232 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
5233 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
5235 elif 'net-delete' in action_dict
:
5236 net
= action_dict
['net-deelte'].get('net')
5237 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
5238 result
= mydb
.delete_row(FROM
='datacenter_nets',
5239 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
5243 raise NfvoException("Unknown action " + str(action_dict
), httperrors
.Bad_Request
)
5246 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
5247 #get datacenter info
5248 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5250 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
5251 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
5252 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
5256 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
5257 #get datacenter info
5258 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5261 action_dict
= action_dict
["netmap"]
5262 if 'vim_id' in action_dict
:
5263 filter_dict
["id"] = action_dict
['vim_id']
5264 if 'vim_name' in action_dict
:
5265 filter_dict
["name"] = action_dict
['vim_name']
5267 filter_dict
["shared"] = True
5270 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
5271 except vimconn
.vimconnException
as e
:
5272 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
5273 raise NfvoException(str(e
), httperrors
.Internal_Server_Error
)
5274 if len(vim_nets
)>1 and action_dict
:
5275 raise NfvoException("more than two networks found, specify with vim_id", httperrors
.Conflict
)
5276 elif len(vim_nets
)==0: # and action_dict:
5277 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), httperrors
.Not_Found
)
5279 for net
in vim_nets
:
5280 net_nfvo
={'datacenter_id': datacenter_id
}
5281 if action_dict
and "name" in action_dict
:
5282 net_nfvo
['name'] = action_dict
['name']
5284 net_nfvo
['name'] = net
['name']
5285 #net_nfvo['description']= net['name']
5286 net_nfvo
['vim_net_id'] = net
['id']
5287 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
5288 net_nfvo
['shared'] = net
['shared']
5289 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
5291 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
5292 net_nfvo
["status"] = "OK"
5293 net_nfvo
["uuid"] = net_id
5294 except db_base_Exception
as e
:
5298 net_nfvo
["status"] = "FAIL: " + str(e
)
5299 net_list
.append(net_nfvo
)
5302 def get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
):
5303 # obtain all network data
5305 if utils
.check_valid_uuid(network_id
):
5306 filter_dict
= {"id": network_id
}
5308 filter_dict
= {"name": network_id
}
5310 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5311 network
= myvim
.get_network_list(filter_dict
=filter_dict
)
5312 except vimconn
.vimconnException
as e
:
5313 raise NfvoException("Not possible to get_sdn_net_id from VIM: {}".format(str(e
)), e
.http_code
)
5315 # ensure the network is defined
5316 if len(network
) == 0:
5317 raise NfvoException("Network {} is not present in the system".format(network_id
),
5318 httperrors
.Bad_Request
)
5320 # ensure there is only one network with the provided name
5321 if len(network
) > 1:
5322 raise NfvoException("Multiple networks present in vim identified by {}".format(network_id
), httperrors
.Bad_Request
)
5324 # ensure it is a dataplane network
5325 if network
[0]['type'] != 'data':
5328 # ensure we use the id
5329 network_id
= network
[0]['id']
5331 # search in dabase mano_db in table instance nets for the sdn_net_id that corresponds to the vim_net_id==network_id
5332 # and with instance_scenario_id==NULL
5333 #search_dict = {'vim_net_id': network_id, 'instance_scenario_id': None}
5334 search_dict
= {'vim_net_id': network_id
}
5337 #sdn_network_id = mydb.get_rows(SELECT=('sdn_net_id',), FROM='instance_nets', WHERE=search_dict)[0]['sdn_net_id']
5338 result
= mydb
.get_rows(SELECT
=('sdn_net_id',), FROM
='instance_nets', WHERE
=search_dict
)
5339 except db_base_Exception
as e
:
5340 raise NfvoException("db_base_Exception obtaining SDN network to associated to vim network {}".format(
5341 network_id
) + str(e
), e
.http_code
)
5345 if net
['sdn_net_id'] != None:
5347 sdn_net_id
= net
['sdn_net_id']
5349 if sdn_net_counter
== 0:
5351 elif sdn_net_counter
== 1:
5354 raise NfvoException("More than one SDN network is associated to vim network {}".format(
5355 network_id
), httperrors
.Internal_Server_Error
)
5357 def get_sdn_controller_id(mydb
, datacenter
):
5358 # Obtain sdn controller id
5359 config
= mydb
.get_rows(SELECT
=('config',), FROM
='datacenters', WHERE
={'uuid': datacenter
})[0].get('config', '{}')
5363 return yaml
.load(config
, Loader
=yaml
.Loader
).get('sdn-controller')
5365 def vim_net_sdn_attach(mydb
, tenant_id
, datacenter
, network_id
, descriptor
):
5367 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
5368 if not sdn_network_id
:
5369 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
), httperrors
.Internal_Server_Error
)
5371 #Obtain sdn controller id
5372 controller_id
= get_sdn_controller_id(mydb
, datacenter
)
5373 if not controller_id
:
5374 raise NfvoException("No SDN controller is set for datacenter {}".format(datacenter
), httperrors
.Internal_Server_Error
)
5376 #Obtain sdn controller info
5377 sdn_controller
= ovim
.show_of_controller(controller_id
)
5380 'name': 'external_port',
5381 'net_id': sdn_network_id
,
5382 'ofc_id': controller_id
,
5383 'switch_dpid': sdn_controller
['dpid'],
5384 'switch_port': descriptor
['port']
5387 if 'vlan' in descriptor
:
5388 port_data
['vlan'] = descriptor
['vlan']
5389 if 'mac' in descriptor
:
5390 port_data
['mac'] = descriptor
['mac']
5392 result
= ovim
.new_port(port_data
)
5393 except ovimException
as e
:
5394 raise NfvoException("ovimException attaching SDN network {} to vim network {}".format(
5395 sdn_network_id
, network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5396 except db_base_Exception
as e
:
5397 raise NfvoException("db_base_Exception attaching SDN network to vim network {}".format(
5398 network_id
) + str(e
), e
.http_code
)
5400 return 'Port uuid: '+ result
5402 def vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, network_id
, port_id
=None):
5404 filter = {'uuid': port_id
}
5406 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
5407 if not sdn_network_id
:
5408 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
),
5409 httperrors
.Internal_Server_Error
)
5410 #in case no port_id is specified only ports marked as 'external_port' will be detached
5411 filter = {'name': 'external_port', 'net_id': sdn_network_id
}
5414 port_list
= ovim
.get_ports(columns
={'uuid'}, filter=filter)
5415 except ovimException
as e
:
5416 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
5417 httperrors
.Internal_Server_Error
)
5419 if len(port_list
) == 0:
5420 raise NfvoException("No ports attached to the network {} were found with the requested criteria".format(network_id
),
5421 httperrors
.Bad_Request
)
5424 for port
in port_list
:
5426 port_uuid_list
.append(port
['uuid'])
5427 ovim
.delete_port(port
['uuid'])
5428 except ovimException
as e
:
5429 raise NfvoException("ovimException deleting port {} for net {}. ".format(port
['uuid'], network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5431 return 'Detached ports uuid: {}'.format(','.join(port_uuid_list
))
5433 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
5434 #get datacenter info
5435 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5438 if utils
.check_valid_uuid(name
):
5439 filter_dict
["id"] = name
5441 filter_dict
["name"] = name
5443 if item
=="networks":
5444 #filter_dict['tenant_id'] = myvim['tenant_id']
5445 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
5447 if len(content
) == 0:
5448 raise NfvoException("Network {} is not present in the system. ".format(name
),
5449 httperrors
.Bad_Request
)
5451 #Update the networks with the attached ports
5453 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, net
['id'])
5454 if sdn_network_id
!= None:
5456 #port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan'}, filter={'name': 'external_port', 'net_id': sdn_network_id})
5457 port_list
= ovim
.get_ports(columns
={'uuid', 'switch_port', 'vlan','name'}, filter={'net_id': sdn_network_id
})
5458 except ovimException
as e
:
5459 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5460 #Remove field name and if port name is external_port save it as 'type'
5461 for port
in port_list
:
5462 if port
['name'] == 'external_port':
5463 port
['type'] = "External"
5465 net
['sdn_network_id'] = sdn_network_id
5466 net
['sdn_attached_ports'] = port_list
5468 elif item
=="tenants":
5469 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
5470 elif item
== "images":
5472 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
5474 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5475 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
5476 if name
and len(content
)==1:
5477 return {item
[:-1]: content
[0]}
5478 elif name
and len(content
)==0:
5479 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.items())),
5482 return {item
: content
}
5483 except vimconn
.vimconnException
as e
:
5484 print("vim_action Not possible to get_{}_list from VIM: {} ".format(item
, str(e
)))
5485 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
5488 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
5489 #get datacenter info
5490 if tenant_id
== "any":
5493 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5495 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
5496 logger
.debug("vim_action_delete vim response: " + str(content
))
5497 items
= next(iter(content
.values()))
5498 if type(items
)==list and len(items
)==0:
5499 raise NfvoException("Not found " + item
, httperrors
.Not_Found
)
5500 elif type(items
)==list and len(items
)>1:
5501 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), httperrors
.Not_Found
)
5502 else: # it is a dict
5503 item_id
= items
["id"]
5504 item_name
= str(items
.get("name"))
5507 if item
=="networks":
5508 # If there is a SDN network associated to the vim-network, proceed to clear the relationship and delete it
5509 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, item_id
)
5510 if sdn_network_id
!= None:
5511 #Delete any port attachment to this network
5513 port_list
= ovim
.get_ports(columns
={'uuid'}, filter={'net_id': sdn_network_id
})
5514 except ovimException
as e
:
5515 raise NfvoException(
5516 "ovimException obtaining external ports for net {}. ".format(sdn_network_id
) + str(e
),
5517 httperrors
.Internal_Server_Error
)
5519 # By calling one by one all ports to be detached we ensure that not only the external_ports get detached
5520 for port
in port_list
:
5521 vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, item_id
, port
['uuid'])
5523 #Delete from 'instance_nets' the correspondence between the vim-net-id and the sdn-net-id
5525 mydb
.delete_row(FROM
='instance_nets', WHERE
={'instance_scenario_id': None,
5526 'sdn_net_id': sdn_network_id
,
5527 'vim_net_id': item_id
})
5528 except db_base_Exception
as e
:
5529 raise NfvoException("Error deleting correspondence for VIM/SDN dataplane networks{}: {}".format(
5530 item_id
, e
), e
.http_code
)
5532 #Delete the SDN network
5534 ovim
.delete_network(sdn_network_id
)
5535 except ovimException
as e
:
5536 logger
.error("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
), exc_info
=True)
5537 raise NfvoException("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
),
5538 httperrors
.Internal_Server_Error
)
5540 content
= myvim
.delete_network(item_id
)
5541 elif item
=="tenants":
5542 content
= myvim
.delete_tenant(item_id
)
5543 elif item
== "images":
5544 content
= myvim
.delete_image(item_id
)
5546 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5547 except vimconn
.vimconnException
as e
:
5548 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
5549 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
5551 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
5554 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
5555 #get datacenter info
5556 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
5557 if tenant_id
== "any":
5559 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5561 if item
=="networks":
5562 net
= descriptor
["network"]
5563 net_name
= net
.pop("name")
5564 net_type
= net
.pop("type", "bridge")
5565 net_public
= net
.pop("shared", False)
5566 net_ipprofile
= net
.pop("ip_profile", None)
5567 net_vlan
= net
.pop("vlan", None)
5568 content
, _
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
5570 #If the datacenter has a SDN controller defined and the network is of dataplane type, then create the sdn network
5571 if get_sdn_controller_id(mydb
, datacenter
) != None and (net_type
== 'data' or net_type
== 'ptp'):
5572 #obtain datacenter_tenant_id
5573 datacenter_tenant_id
= mydb
.get_rows(SELECT
=('uuid',),
5574 FROM
='datacenter_tenants',
5575 WHERE
={'datacenter_id': datacenter
})[0]['uuid']
5578 sdn_network
['vlan'] = net_vlan
5579 sdn_network
['type'] = net_type
5580 sdn_network
['name'] = net_name
5581 sdn_network
['region'] = datacenter_tenant_id
5582 ovim_content
= ovim
.new_network(sdn_network
)
5583 except ovimException
as e
:
5584 logger
.error("ovimException creating SDN network={} ".format(
5585 sdn_network
) + str(e
), exc_info
=True)
5586 raise NfvoException("ovimException creating SDN network={} ".format(sdn_network
) + str(e
),
5587 httperrors
.Internal_Server_Error
)
5589 # Save entry in in dabase mano_db in table instance_nets to stablish a dictionary vim_net_id <->sdn_net_id
5590 # use instance_scenario_id=None to distinguish from real instaces of nets
5591 correspondence
= {'instance_scenario_id': None,
5592 'sdn_net_id': ovim_content
,
5593 'vim_net_id': content
,
5594 'datacenter_tenant_id': datacenter_tenant_id
5597 mydb
.new_row('instance_nets', correspondence
, add_uuid
=True)
5598 except db_base_Exception
as e
:
5599 raise NfvoException("Error saving correspondence for VIM/SDN dataplane networks{}: {}".format(
5600 correspondence
, e
), e
.http_code
)
5601 elif item
=="tenants":
5602 tenant
= descriptor
["tenant"]
5603 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
5605 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5606 except vimconn
.vimconnException
as e
:
5607 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
5609 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
5611 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
5612 data
= ovim
.new_of_controller(sdn_controller
)
5613 logger
.debug('New SDN controller created with uuid {}'.format(data
))
5616 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
5617 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
5618 msg
= 'SDN controller {} updated'.format(data
)
5622 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
5623 if controller_id
== None:
5624 data
= ovim
.get_of_controllers()
5626 data
= ovim
.show_of_controller(controller_id
)
5628 msg
= 'SDN controller list:\n {}'.format(data
)
5632 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
5633 select_
= ('uuid', 'config')
5634 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
5635 for datacenter
in datacenters
:
5636 if datacenter
['config']:
5637 config
= yaml
.load(datacenter
['config'], Loader
=yaml
.Loader
)
5638 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
5639 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), httperrors
.Conflict
)
5641 data
= ovim
.delete_of_controller(controller_id
)
5642 msg
= 'SDN controller {} deleted'.format(data
)
5646 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
5647 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
5648 if len(controller
) < 1:
5649 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), httperrors
.Not_Found
)
5652 sdn_controller_id
= yaml
.load(controller
[0]["config"], Loader
=yaml
.Loader
)["sdn-controller"]
5654 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), httperrors
.Bad_Request
)
5656 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
5657 switch_dpid
= sdn_controller
["dpid"]
5660 for compute_node
in sdn_port_mapping
:
5661 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
5663 element
["compute_node"] = compute_node
["compute_node"]
5664 for port
in compute_node
["ports"]:
5665 pci
= port
.get("pci")
5666 element
["switch_port"] = port
.get("switch_port")
5667 element
["switch_mac"] = port
.get("switch_mac")
5668 if not element
["switch_port"] and not element
["switch_mac"]:
5669 raise NfvoException ("The mapping must contain 'switch_port' or 'switch_mac'", httperrors
.Bad_Request
)
5670 for pci_expanded
in utils
.expand_brackets(pci
):
5671 element
["pci"] = pci_expanded
5672 maps
.append(dict(element
))
5674 return ovim
.set_of_port_mapping(maps
, ofc_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, region
=datacenter_id
)
5676 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
5677 maps
= ovim
.get_of_port_mappings(db_filter
={"region": datacenter_id
})
5680 "sdn-controller": None,
5681 "datacenter-id": datacenter_id
,
5683 "ports_mapping": list()
5686 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
5687 if datacenter
['config']:
5688 config
= yaml
.load(datacenter
['config'], Loader
=yaml
.Loader
)
5689 if 'sdn-controller' in config
:
5690 controller_id
= config
['sdn-controller']
5691 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
5692 result
["sdn-controller"] = controller_id
5693 result
["dpid"] = sdn_controller
["dpid"]
5695 if result
["sdn-controller"] == None:
5696 raise NfvoException("SDN controller is not defined for datacenter {}".format(datacenter_id
), httperrors
.Bad_Request
)
5697 if result
["dpid"] == None:
5698 raise NfvoException("It was not possible to determine DPID for SDN controller {}".format(result
["sdn-controller"]),
5699 httperrors
.Internal_Server_Error
)
5704 ports_correspondence_dict
= dict()
5706 if result
["sdn-controller"] != link
["ofc_id"]:
5707 raise NfvoException("The sdn-controller specified for different port mappings differ", httperrors
.Internal_Server_Error
)
5708 if result
["dpid"] != link
["switch_dpid"]:
5709 raise NfvoException("The dpid specified for different port mappings differ", httperrors
.Internal_Server_Error
)
5711 element
["pci"] = link
["pci"]
5712 if link
["switch_port"]:
5713 element
["switch_port"] = link
["switch_port"]
5714 if link
["switch_mac"]:
5715 element
["switch_mac"] = link
["switch_mac"]
5717 if not link
["compute_node"] in ports_correspondence_dict
:
5719 content
["compute_node"] = link
["compute_node"]
5720 content
["ports"] = list()
5721 ports_correspondence_dict
[link
["compute_node"]] = content
5723 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
5725 for key
in sorted(ports_correspondence_dict
):
5726 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
5730 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
5731 return ovim
.clear_of_port_mapping(db_filter
={"region":datacenter_id
})
5733 def create_RO_keypair(tenant_id
):
5735 Creates a public / private keys for a RO tenant and returns their values
5737 tenant_id: ID of the tenant
5739 public_key: Public key for the RO tenant
5740 private_key: Encrypted private key for RO tenant
5744 key
= RSA
.generate(bits
)
5746 public_key
= key
.publickey().exportKey('OpenSSH')
5747 if isinstance(public_key
, ValueError):
5748 raise NfvoException("Unable to create public key: {}".format(public_key
), httperrors
.Internal_Server_Error
)
5749 private_key
= key
.exportKey(passphrase
=tenant_id
, pkcs
=8)
5750 except (ValueError, NameError) as e
:
5751 raise NfvoException("Unable to create private key: {}".format(e
), httperrors
.Internal_Server_Error
)
5752 return public_key
, private_key
5754 def decrypt_key (key
, tenant_id
):
5756 Decrypts an encrypted RSA key
5758 key: Private key to be decrypted
5759 tenant_id: ID of the tenant
5761 unencrypted_key: Unencrypted private key for RO tenant
5764 key
= RSA
.importKey(key
,tenant_id
)
5765 unencrypted_key
= key
.exportKey('PEM')
5766 if isinstance(unencrypted_key
, ValueError):
5767 raise NfvoException("Unable to decrypt the private key: {}".format(unencrypted_key
), httperrors
.Internal_Server_Error
)
5768 except ValueError as e
:
5769 raise NfvoException("Unable to decrypt the private key: {}".format(e
), httperrors
.Internal_Server_Error
)
5770 return unencrypted_key