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 osm_ro
.sdn
import Sdn
, SdnException
as ovimException
49 # from lib_osm_openvim.ovim import ovimException
50 # from unittest.mock import MagicMock
51 # class ovimException(Exception):
55 from Crypto
.PublicKey
import RSA
57 import osm_im
.vnfd
as vnfd_catalog
58 import osm_im
.nsd
as nsd_catalog
59 from pyangbind
.lib
.serialise
import pybindJSONDecoder
60 from copy
import deepcopy
61 from pkg_resources
import iter_entry_points
65 from .wim
import sdnconn
66 from .wim
.wimconn_fake
import FakeConnector
67 from .wim
.failing_connector
import FailingConnector
68 from .http_tools
import errors
as httperrors
69 from .wim
.engine
import WimEngine
70 from .wim
.persistence
import WimPersistence
71 from copy
import deepcopy
72 from pprint
import pformat
79 global sdnconn_imported
82 global default_volume_size
83 default_volume_size
= '5' #size in GB
88 plugins
= {} # dictionary with VIM type as key, loaded module as value
89 vim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-VIMs
90 vim_persistent_info
= {}
92 sdnconn_imported
= {} # dictionary with WIM type as key, loaded module as value
93 wim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-WIMs
94 wim_persistent_info
= {}
97 logger
= logging
.getLogger('openmano.nfvo')
104 class NfvoException(httperrors
.HttpMappedError
):
105 """Common Class for NFVO errors"""
107 def _load_plugin(name
, type="vim"):
108 # type can be vim or sdn
111 for v
in iter_entry_points('osm_ro{}.plugins'.format(type), name
):
112 plugins
[name
] = v
.load()
113 except Exception as e
:
114 logger
.critical("Cannot load osm_{}: {}".format(name
, e
))
116 plugins
[name
] = FailingConnector("Cannot load osm_{}: {}".format(name
, e
))
117 if name
and name
not in plugins
:
118 error_text
= "Cannot load a module for {t} type '{n}'. The plugin 'osm_{n}' has not been" \
119 " registered".format(t
=type, n
=name
)
120 logger
.critical(error_text
)
121 plugins
[name
] = FailingConnector(error_text
)
122 # raise NfvoException("Cannot load a module for {t} type '{n}'. The plugin 'osm_{n}' has not been registered".
123 # format(t=type, n=name), httperrors.Bad_Request)
128 if task_id
<= last_task_id
:
129 task_id
= last_task_id
+ 0.000001
130 last_task_id
= task_id
131 return "ACTION-{:.6f}".format(task_id
)
132 # return (t.strftime("%Y%m%dT%H%M%S.{}%Z", t.localtime(task_id))).format(int((task_id % 1)*1e6))
135 def new_task(name
, params
, depends
=None):
137 task_id
= get_task_id()
138 task
= {"status": "enqueued", "id": task_id
, "name": name
, "params": params
}
140 task
["depends"] = depends
145 return True if id[:5] == "TASK-" else False
148 def get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_name
, tenant_id
):
149 name
= datacenter_name
[:16]
150 if name
not in vim_threads
["names"]:
151 vim_threads
["names"].append(name
)
154 name
= datacenter_name
[:16] + "." + tenant_name
[:16]
155 if name
not in vim_threads
["names"]:
156 vim_threads
["names"].append(name
)
159 vim_threads
["names"].append(name
)
163 def get_non_used_wim_name(wim_name
, wim_id
, tenant_name
, tenant_id
):
165 if name
not in wim_threads
["names"]:
166 wim_threads
["names"].append(name
)
168 name
= wim_name
[:16] + "." + tenant_name
[:16]
169 if name
not in wim_threads
["names"]:
170 wim_threads
["names"].append(name
)
172 name
= wim_id
+ "-" + tenant_id
173 wim_threads
["names"].append(name
)
177 def start_service(mydb
, persistence
=None, wim
=None):
178 global db
, global_config
, plugins
, ovim
179 db
= nfvo_db
.nfvo_db(lock
=db_lock
)
181 db
.connect(global_config
['db_host'], global_config
['db_user'], global_config
['db_passwd'], global_config
['db_name'])
183 persistence
= persistence
or WimPersistence(db
)
186 if "rosdn_fake" not in plugins
:
187 plugins
["rosdn_fake"] = FakeConnector
188 # starts ovim library
189 ovim
= Sdn(db
, plugins
)
192 wim_engine
= wim
or WimEngine(persistence
, plugins
)
193 wim_engine
.ovim
= ovim
197 #delete old unneeded vim_wim_actions
201 from_
= 'tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join '\
202 'datacenter_tenants as dt on td.datacenter_tenant_id=dt.uuid'
203 select_
= ('type', 'd.config as config', 'd.uuid as datacenter_id', 'vim_url', 'vim_url_admin',
204 'd.name as datacenter_name', 'dt.uuid as datacenter_tenant_id',
205 'dt.vim_tenant_name as vim_tenant_name', 'dt.vim_tenant_id as vim_tenant_id',
206 'user', 'passwd', 'dt.config as dt_config', 'nfvo_tenant_id')
207 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
)
209 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
210 'datacenter_id': vim
.get('datacenter_id')}
212 extra
.update(yaml
.load(vim
["config"], Loader
=yaml
.Loader
))
213 if vim
.get('dt_config'):
214 extra
.update(yaml
.load(vim
["dt_config"], Loader
=yaml
.Loader
))
215 plugin_name
= "rovim_" + vim
["type"]
216 if plugin_name
not in plugins
:
217 _load_plugin(plugin_name
, type="vim")
219 thread_id
= vim
['datacenter_tenant_id']
220 vim_persistent_info
[thread_id
] = {}
223 # return -httperrors.Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
224 myvim
= plugins
[plugin_name
].vimconnector(
225 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
226 tenant_id
=vim
['vim_tenant_id'], tenant_name
=vim
['vim_tenant_name'],
227 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
228 user
=vim
['user'], passwd
=vim
['passwd'],
229 config
=extra
, persistent_info
=vim_persistent_info
[thread_id
]
231 except vimconn
.vimconnException
as e
:
233 logger
.error("Cannot launch thread for VIM {} '{}': {}".format(vim
['datacenter_name'],
234 vim
['datacenter_id'], e
))
235 except Exception as e
:
236 logger
.critical("Cannot launch thread for VIM {} '{}': {}".format(vim
['datacenter_name'],
237 vim
['datacenter_id'], e
))
238 # raise NfvoException("Error at VIM {}; {}: {}".format(vim["type"], type(e).__name__, e),
239 # httperrors.Internal_Server_Error)
240 thread_name
= get_non_used_vim_name(vim
['datacenter_name'], vim
['datacenter_id'], vim
['vim_tenant_name'],
241 vim
['vim_tenant_id'])
242 new_thread
= vim_thread(task_lock
, plugins
, thread_name
, None,
243 vim
['datacenter_tenant_id'], db
=db
)
245 vim_threads
["running"][thread_id
] = new_thread
246 wims
= mydb
.get_rows(FROM
="wim_accounts join wims on wim_accounts.wim_id=wims.uuid",
247 WHERE
={"sdn": "true"},
248 SELECT
=("wim_accounts.uuid as uuid", "type", "wim_accounts.name as name"))
250 plugin_name
= "rosdn_" + wim
["type"]
251 if plugin_name
not in plugins
:
252 _load_plugin(plugin_name
, type="sdn")
254 thread_id
= wim
['uuid']
255 thread_name
= get_non_used_vim_name(wim
['name'], wim
['uuid'], wim
['uuid'], None)
256 new_thread
= vim_thread(task_lock
, plugins
, thread_name
, wim
['uuid'], None, db
=db
)
258 vim_threads
["running"][thread_id
] = new_thread
259 wim_engine
.start_threads()
260 except db_base_Exception
as e
:
261 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
262 except ovimException
as e
:
264 if message
[:22] == "DATABASE wrong version":
265 message
= "DATABASE wrong version of lib_osm_openvim {msg} -d{dbname} -u{dbuser} -p{dbpass} {ver}' "\
266 "at host {dbhost}".format(
267 msg
=message
[22:-3], dbname
=global_config
["db_ovim_name"],
268 dbuser
=global_config
["db_ovim_user"], dbpass
=global_config
["db_ovim_passwd"],
269 ver
=message
[-3:-1], dbhost
=global_config
["db_ovim_host"])
270 raise NfvoException(message
, httperrors
.Bad_Request
)
274 global ovim
, global_config
277 for thread_id
, thread
in vim_threads
["running"].items():
278 thread
.insert_task("exit")
279 vim_threads
["deleting"][thread_id
] = thread
280 vim_threads
["running"] = {}
283 wim_engine
.stop_threads()
285 if global_config
and global_config
.get("console_thread"):
286 for thread
in global_config
["console_thread"]:
287 thread
.terminate
= True
290 return ("openmanod version {} {}\n(c) Copyright Telefonica".format(global_config
["version"],
291 global_config
["version_date"] ))
295 Clean unused or old entries at database to avoid unlimited growing
296 :param mydb: database connector
299 # get and delete unused vim_wim_actions: all elements deleted, one week before, instance not present
300 now
= t
.time()-3600*24*7
301 instance_action_id
= None
304 actions_to_delete
= mydb
.get_rows(
305 SELECT
=("item", "item_id", "instance_action_id"),
306 FROM
="vim_wim_actions as va join instance_actions as ia on va.instance_action_id=ia.uuid "
307 "left join instance_scenarios as i on ia.instance_id=i.uuid",
308 WHERE
={"va.action": "DELETE", "va.modified_at<": now
, "i.uuid": None,
309 "va.status": ("DONE", "SUPERSEDED")},
312 for to_delete
in actions_to_delete
:
313 mydb
.delete_row(FROM
="vim_wim_actions", WHERE
=to_delete
)
314 if instance_action_id
!= to_delete
["instance_action_id"]:
315 instance_action_id
= to_delete
["instance_action_id"]
316 mydb
.delete_row(FROM
="instance_actions", WHERE
={"uuid": instance_action_id
})
317 nb_deleted
+= len(actions_to_delete
)
318 if len(actions_to_delete
) < 100:
321 mydb
.update_rows("vim_wim_actions", UPDATE
={"worker": None}, WHERE
={"worker<>": None})
324 logger
.debug("Removed {} unused vim_wim_actions".format(nb_deleted
))
327 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
329 return result, content:
330 <0, error_text upon error
331 nb_records, flavor_list on success
334 WHERE_dict
['vnf_id'] = vnf_id
335 if nfvo_tenant
is not None:
336 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
338 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
339 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
340 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
341 #print "get_flavor_list result:", result
342 #print "get_flavor_list content:", content
344 for flavor
in flavors
:
345 flavorList
.append(flavor
['flavor_id'])
349 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
351 Get used images of all vms belonging to this VNFD
352 :param mydb: database conector
353 :param vnf_id: vnfd uuid
354 :param nfvo_tenant: tenant, not used
355 :return: The list of image uuid used
358 vms
= mydb
.get_rows(SELECT
=('image_id','image_list'), FROM
='vms', WHERE
={'vnf_id': vnf_id
})
360 if vm
["image_id"] and vm
["image_id"] not in image_list
:
361 image_list
.append(vm
["image_id"])
363 vm_image_list
= yaml
.load(vm
["image_list"], Loader
=yaml
.Loader
)
364 for image_dict
in vm_image_list
:
365 if image_dict
["image_id"] not in image_list
:
366 image_list
.append(image_dict
["image_id"])
370 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
371 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None, ignore_errors
=False):
372 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
373 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
374 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
375 raise exception upon error
379 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
380 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
381 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
382 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
383 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
384 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
385 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
386 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'
387 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
388 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
389 'user','passwd', 'dt.config as dt_config')
391 from_
= 'datacenters as d'
392 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
394 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
397 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
398 'datacenter_id': vim
.get('datacenter_id'),
399 '_vim_type_internal': vim
.get('type')}
401 extra
.update(yaml
.load(vim
["config"], Loader
=yaml
.Loader
))
402 if vim
.get('dt_config'):
403 extra
.update(yaml
.load(vim
["dt_config"], Loader
=yaml
.Loader
))
404 plugin_name
= "rovim_" + vim
["type"]
405 if plugin_name
not in plugins
:
407 _load_plugin(plugin_name
, type="vim")
408 except NfvoException
as e
:
410 logger
.error("{}".format(e
))
415 if 'datacenter_tenant_id' in vim
:
416 thread_id
= vim
["datacenter_tenant_id"]
417 if thread_id
not in vim_persistent_info
:
418 vim_persistent_info
[thread_id
] = {}
419 persistent_info
= vim_persistent_info
[thread_id
]
423 # return -httperrors.Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
424 vim_dict
[vim
['datacenter_id']] = plugins
[plugin_name
].vimconnector(
425 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
426 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
),
427 tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
428 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
429 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
430 config
=extra
, persistent_info
=persistent_info
432 except Exception as e
:
434 logger
.error("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)))
436 http_code
= httperrors
.Internal_Server_Error
437 if isinstance(e
, vimconn
.vimconnException
):
438 http_code
= e
.http_code
439 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), http_code
)
441 except db_base_Exception
as e
:
442 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
445 def rollback(mydb
, vims
, rollback_list
):
447 #delete things by reverse order
448 for i
in range(len(rollback_list
)-1, -1, -1):
449 item
= rollback_list
[i
]
450 if item
["where"]=="vim":
451 if item
["vim_id"] not in vims
:
453 if is_task_id(item
["uuid"]):
455 vim
= vims
[item
["vim_id"]]
457 if item
["what"]=="image":
458 vim
.delete_image(item
["uuid"])
459 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_vim_id": vim
["id"], "vim_id":item
["uuid"]})
460 elif item
["what"]=="flavor":
461 vim
.delete_flavor(item
["uuid"])
462 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_vim_id": vim
["id"], "vim_id":item
["uuid"]})
463 elif item
["what"]=="network":
464 vim
.delete_network(item
["uuid"])
465 elif item
["what"]=="vm":
466 vim
.delete_vminstance(item
["uuid"])
467 except vimconn
.vimconnException
as e
:
468 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
469 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
470 except db_base_Exception
as e
:
471 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
475 if item
["what"]=="image":
476 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
477 elif item
["what"]=="flavor":
478 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
479 except db_base_Exception
as e
:
480 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
481 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
482 if len(undeleted_items
)==0:
483 return True," Rollback successful."
485 return False," Rollback fails to delete: " + str(undeleted_items
)
488 def check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1):
490 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
492 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
494 #dataplane interfaces
495 for numa
in vnfc
.get("numas",() ):
496 for interface
in numa
.get("interfaces",()):
497 if interface
["name"] in name_dict
:
499 "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
500 vnfc
["name"], interface
["name"]),
501 httperrors
.Bad_Request
)
502 name_dict
[ interface
["name"] ] = "underlay"
504 for interface
in vnfc
.get("bridge-ifaces",() ):
505 if interface
["name"] in name_dict
:
507 "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
508 vnfc
["name"], interface
["name"]),
509 httperrors
.Bad_Request
)
510 name_dict
[ interface
["name"] ] = "overlay"
511 vnfc_interfaces
[ vnfc
["name"] ] = name_dict
512 # check bood-data info
513 # if "boot-data" in vnfc:
514 # # check that user-data is incompatible with users and config-files
515 # if (vnfc["boot-data"].get("users") or vnfc["boot-data"].get("config-files")) and vnfc["boot-data"].get("user-data"):
516 # raise NfvoException(
517 # "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
518 # httperrors.Bad_Request)
520 #check if the info in external_connections matches with the one in the vnfcs
522 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
523 if external_connection
["name"] in name_list
:
525 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
526 external_connection
["name"]),
527 httperrors
.Bad_Request
)
528 name_list
.append(external_connection
["name"])
529 if external_connection
["VNFC"] not in vnfc_interfaces
:
531 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
532 external_connection
["name"], external_connection
["VNFC"]),
533 httperrors
.Bad_Request
)
535 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
537 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
538 external_connection
["name"],
539 external_connection
["local_iface_name"]),
540 httperrors
.Bad_Request
)
542 #check if the info in internal_connections matches with the one in the vnfcs
544 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
545 if internal_connection
["name"] in name_list
:
547 "Error at vnf:internal-connections:name, value '{}' already used as an internal-connection".format(
548 internal_connection
["name"]),
549 httperrors
.Bad_Request
)
550 name_list
.append(internal_connection
["name"])
551 #We should check that internal-connections of type "ptp" have only 2 elements
553 if len(internal_connection
["elements"])>2 and (internal_connection
.get("type") == "ptp" or internal_connection
.get("type") == "e-line"):
555 "Error at 'vnf:internal-connections[name:'{}']:elements', size must be 2 for a '{}' type. Consider change it to '{}' type".format(
556 internal_connection
["name"],
557 'ptp' if vnf_descriptor_version
==1 else 'e-line',
558 'data' if vnf_descriptor_version
==1 else "e-lan"),
559 httperrors
.Bad_Request
)
560 for port
in internal_connection
["elements"]:
562 iface
= port
["local_iface_name"]
563 if vnf
not in vnfc_interfaces
:
565 "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
566 internal_connection
["name"], vnf
),
567 httperrors
.Bad_Request
)
568 if iface
not in vnfc_interfaces
[ vnf
]:
570 "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
571 internal_connection
["name"], iface
),
572 httperrors
.Bad_Request
)
573 return -httperrors
.Bad_Request
,
574 if vnf_descriptor_version
==1 and "type" not in internal_connection
:
575 if vnfc_interfaces
[vnf
][iface
] == "overlay":
576 internal_connection
["type"] = "bridge"
578 internal_connection
["type"] = "data"
579 if vnf_descriptor_version
==2 and "implementation" not in internal_connection
:
580 if vnfc_interfaces
[vnf
][iface
] == "overlay":
581 internal_connection
["implementation"] = "overlay"
583 internal_connection
["implementation"] = "underlay"
584 if (internal_connection
.get("type") == "data" or internal_connection
.get("type") == "ptp" or \
585 internal_connection
.get("implementation") == "underlay") and vnfc_interfaces
[vnf
][iface
] == "overlay":
587 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
588 internal_connection
["name"],
589 iface
, 'bridge' if vnf_descriptor_version
==1 else 'overlay',
590 'data' if vnf_descriptor_version
==1 else 'underlay'),
591 httperrors
.Bad_Request
)
592 if (internal_connection
.get("type") == "bridge" or internal_connection
.get("implementation") == "overlay") and \
593 vnfc_interfaces
[vnf
][iface
] == "underlay":
595 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
596 internal_connection
["name"], iface
,
597 'data' if vnf_descriptor_version
==1 else 'underlay',
598 'bridge' if vnf_descriptor_version
==1 else 'overlay'),
599 httperrors
.Bad_Request
)
602 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=None):
604 if only_create_at_vim
:
605 image_mano_id
= image_dict
['uuid']
606 if return_on_error
== None:
607 return_on_error
= True
609 if image_dict
['location']:
610 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
612 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
614 image_mano_id
= images
[0]['uuid']
616 #create image in MANO DB
617 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
618 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
619 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
621 #temp_image_dict['location'] = image_dict.get('new_location') if image_dict['location'] is None
622 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
623 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
624 #create image at every vim
625 for vim_id
,vim
in vims
.items():
626 datacenter_vim_id
= vim
["config"]["datacenter_tenant_id"]
627 image_created
="false"
629 image_db
= mydb
.get_rows(FROM
="datacenters_images",
630 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'image_id': image_mano_id
})
631 #look at VIM if this image exist
633 if image_dict
['location'] is not None:
634 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
637 filter_dict
['name'] = image_dict
['universal_name']
638 if image_dict
.get('checksum') != None:
639 filter_dict
['checksum'] = image_dict
['checksum']
640 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
641 vim_images
= vim
.get_image_list(filter_dict
)
642 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
643 if len(vim_images
) > 1:
644 raise vimconn
.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict
)), httperrors
.Conflict
)
645 elif len(vim_images
) == 0:
646 raise vimconn
.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict
)))
648 #logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
649 image_vim_id
= vim_images
[0]['id']
651 except vimconn
.vimconnNotFoundException
as e
:
652 #Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
654 #image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
655 if image_dict
['location']:
656 image_vim_id
= vim
.new_image(image_dict
)
657 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
660 #If we reach this point, then the image has image name, and optionally checksum, and could not be found
661 raise vimconn
.vimconnException(str(e
))
662 except vimconn
.vimconnException
as e
:
664 logger
.error("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
667 logger
.warn("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
669 except vimconn
.vimconnException
as e
:
671 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
673 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
676 #if we reach here, the image has been created or existed
678 #add new vim_id at datacenters_images
679 mydb
.new_row('datacenters_images', {'datacenter_vim_id': datacenter_vim_id
,
680 'image_id':image_mano_id
,
681 'vim_id': image_vim_id
,
682 'created':image_created
})
683 elif image_db
[0]["vim_id"]!=image_vim_id
:
684 #modify existing vim_id at datacenters_images
685 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_vim_id':vim_id
, 'image_id':image_mano_id
})
687 return image_vim_id
if only_create_at_vim
else image_mano_id
690 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
691 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',0),
692 'ram':flavor_dict
.get('ram'),
693 'vcpus':flavor_dict
.get('vcpus'),
695 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
696 del flavor_dict
['extended']
697 if 'extended' in flavor_dict
:
698 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
700 #look if flavor exist
701 if only_create_at_vim
:
702 flavor_mano_id
= flavor_dict
['uuid']
703 if return_on_error
== None:
704 return_on_error
= True
706 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
708 flavor_mano_id
= flavors
[0]['uuid']
711 #create one by one the images of aditional disks
712 dev_image_list
=[] #list of images
713 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
715 for device
in flavor_dict
['extended'].get('devices',[]):
716 if "image" not in device
and "image name" not in device
:
719 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
720 image_dict
['universal_name']=device
.get('image name')
721 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
722 image_dict
['location']=device
.get('image')
723 #image_dict['new_location']=vnfc.get('image location')
724 image_dict
['checksum']=device
.get('image checksum')
725 image_metadata_dict
= device
.get('image metadata', None)
726 image_metadata_str
= None
727 if image_metadata_dict
!= None:
728 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
729 image_dict
['metadata']=image_metadata_str
730 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
731 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
732 dev_image_list
.append(image_id
)
734 temp_flavor_dict
['name'] = flavor_dict
['name']
735 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
736 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
737 flavor_mano_id
= content
738 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
739 #create flavor at every vim
740 if 'uuid' in flavor_dict
:
741 del flavor_dict
['uuid']
743 for vim_id
,vim
in vims
.items():
744 datacenter_vim_id
= vim
["config"]["datacenter_tenant_id"]
745 flavor_created
="false"
747 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors",
748 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
})
749 #look at VIM if this flavor exist SKIPPED
750 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
752 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
756 # Create the flavor in VIM
757 # Translate images at devices from MANO id to VIM id
759 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
760 # make a copy of original devices
763 for device
in flavor_dict
["extended"].get("devices",[]):
766 devices_original
.append(dev
)
767 if 'image' in device
:
769 if 'image metadata' in device
:
770 del device
['image metadata']
771 if 'image checksum' in device
:
772 del device
['image checksum']
774 for index
in range(0,len(devices_original
)) :
775 device
=devices_original
[index
]
776 if "image" not in device
and "image name" not in device
:
777 # if 'size' in device:
778 disk_list
.append({'size': device
.get('size', default_volume_size
), 'name': device
.get('name')})
781 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
782 image_dict
['universal_name']=device
.get('image name')
783 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
784 image_dict
['location']=device
.get('image')
785 # image_dict['new_location']=device.get('image location')
786 image_dict
['checksum']=device
.get('image checksum')
787 image_metadata_dict
= device
.get('image metadata', None)
788 image_metadata_str
= None
789 if image_metadata_dict
!= None:
790 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
791 image_dict
['metadata']=image_metadata_str
792 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
793 image_dict
["uuid"]=image_mano_id
794 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
796 #save disk information (image must be based on and size
797 disk_list
.append({'image_id': image_vim_id
, 'size': device
.get('size', default_volume_size
)})
799 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
802 #check that this vim_id exist in VIM, if not create
803 flavor_vim_id
=flavor_db
[0]["vim_id"]
805 vim
.get_flavor(flavor_vim_id
)
806 continue #flavor exist
807 except vimconn
.vimconnException
:
809 #create flavor at vim
810 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
813 flavor_vim_id
=vim
.get_flavor_id_from_data(flavor_dict
)
814 flavor_created
="false"
815 except vimconn
.vimconnException
as e
:
818 if not flavor_vim_id
:
819 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
820 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
821 flavor_created
="true"
822 except vimconn
.vimconnException
as e
:
824 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
826 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
829 #if reach here the flavor has been create or exist
830 if len(flavor_db
)==0:
831 #add new vim_id at datacenters_flavors
832 extended_devices_yaml
= None
833 if len(disk_list
) > 0:
834 extended_devices
= dict()
835 extended_devices
['disks'] = disk_list
836 extended_devices_yaml
= yaml
.safe_dump(extended_devices
,default_flow_style
=True,width
=256)
837 mydb
.new_row('datacenters_flavors',
838 {'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
, 'vim_id': flavor_vim_id
,
839 'created': flavor_created
, 'extended': extended_devices_yaml
})
840 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
841 #modify existing vim_id at datacenters_flavors
842 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
},
843 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
})
845 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
848 def get_str(obj
, field
, length
):
850 Obtain the str value,
855 value
= obj
.get(field
)
856 if value
is not None:
857 value
= str(value
)[:length
]
860 def _lookfor_or_create_image(db_image
, mydb
, descriptor
):
862 fill image content at db_image dictionary. Check if the image with this image and checksum exist
863 :param db_image: dictionary to insert data
864 :param mydb: database connector
865 :param descriptor: yang descriptor
866 :return: uuid if the image exist at DB, or None if a new image must be created with the data filled at db_image
869 db_image
["name"] = get_str(descriptor
, "image", 255)
870 db_image
["checksum"] = get_str(descriptor
, "image-checksum", 32)
871 if not db_image
["checksum"]: # Ensure that if empty string, None is stored
872 db_image
["checksum"] = None
873 if db_image
["name"].startswith("/"):
874 db_image
["location"] = db_image
["name"]
875 existing_images
= mydb
.get_rows(FROM
="images", WHERE
={'location': db_image
["location"]})
877 db_image
["universal_name"] = db_image
["name"]
878 existing_images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name': db_image
['universal_name'],
879 'checksum': db_image
['checksum']})
881 return existing_images
[0]["uuid"]
883 image_uuid
= str(uuid4())
884 db_image
["uuid"] = image_uuid
887 def get_resource_allocation_params(quota_descriptor
):
889 read the quota_descriptor from vnfd and fetch the resource allocation properties from the descriptor object
890 :param quota_descriptor: cpu/mem/vif/disk-io quota descriptor
891 :return: quota params for limit, reserve, shares from the descriptor object
894 if quota_descriptor
.get("limit"):
895 quota
["limit"] = int(quota_descriptor
["limit"])
896 if quota_descriptor
.get("reserve"):
897 quota
["reserve"] = int(quota_descriptor
["reserve"])
898 if quota_descriptor
.get("shares"):
899 quota
["shares"] = int(quota_descriptor
["shares"])
902 def new_vnfd_v3(mydb
, tenant_id
, vnf_descriptor
):
904 Parses an OSM IM vnfd_catalog and insert at DB
907 :param vnf_descriptor:
908 :return: The list of cretated vnf ids
911 myvnfd
= vnfd_catalog
.vnfd()
913 pybindJSONDecoder
.load_ietf_json(vnf_descriptor
, None, None, obj
=myvnfd
, path_helper
=True,
915 except Exception as e
:
916 raise NfvoException("Error. Invalid VNF descriptor format " + str(e
), httperrors
.Bad_Request
)
924 db_ip_profiles_index
= 0
928 vnfd_catalog_descriptor
= vnf_descriptor
.get("vnfd:vnfd-catalog")
929 if not vnfd_catalog_descriptor
:
930 vnfd_catalog_descriptor
= vnf_descriptor
.get("vnfd-catalog")
931 vnfd_descriptor_list
= vnfd_catalog_descriptor
.get("vnfd")
932 if not vnfd_descriptor_list
:
933 vnfd_descriptor_list
= vnfd_catalog_descriptor
.get("vnfd:vnfd")
934 for vnfd_yang
in myvnfd
.vnfd_catalog
.vnfd
.values():
935 vnfd
= vnfd_yang
.get()
938 vnf_uuid
= str(uuid4())
939 uuid_list
.append(vnf_uuid
)
940 vnfd_uuid_list
.append(vnf_uuid
)
941 vnfd_id
= get_str(vnfd
, "id", 255)
945 "name": get_str(vnfd
, "name", 255),
946 "description": get_str(vnfd
, "description", 255),
947 "tenant_id": tenant_id
,
948 "vendor": get_str(vnfd
, "vendor", 255),
949 "short_name": get_str(vnfd
, "short-name", 255),
950 "descriptor": str(vnf_descriptor
)[:60000]
953 for vnfd_descriptor
in vnfd_descriptor_list
:
954 if vnfd_descriptor
["id"] == str(vnfd
["id"]):
957 # table ip_profiles (ip-profiles)
958 ip_profile_name2db_table_index
= {}
959 for ip_profile
in vnfd
.get("ip-profiles").values():
961 "ip_version": str(ip_profile
["ip-profile-params"].get("ip-version", "ipv4")),
962 "subnet_address": str(ip_profile
["ip-profile-params"].get("subnet-address")),
963 "gateway_address": str(ip_profile
["ip-profile-params"].get("gateway-address")),
964 "dhcp_enabled": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("enabled", True)),
965 "dhcp_start_address": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("start-address")),
966 "dhcp_count": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("count")),
969 for dns
in ip_profile
["ip-profile-params"]["dns-server"].values():
970 dns_list
.append(str(dns
.get("address")))
971 db_ip_profile
["dns_address"] = ";".join(dns_list
)
972 if ip_profile
["ip-profile-params"].get('security-group'):
973 db_ip_profile
["security_group"] = ip_profile
["ip-profile-params"]['security-group']
974 ip_profile_name2db_table_index
[str(ip_profile
["name"])] = db_ip_profiles_index
975 db_ip_profiles_index
+= 1
976 db_ip_profiles
.append(db_ip_profile
)
978 # table nets (internal-vld)
979 net_id2uuid
= {} # for mapping interface with network
980 for vld
in vnfd
.get("internal-vld").values():
981 net_uuid
= str(uuid4())
982 uuid_list
.append(net_uuid
)
984 "name": get_str(vld
, "name", 255),
987 "description": get_str(vld
, "description", 255),
988 "osm_id": get_str(vld
, "id", 255),
989 "type": "bridge", # TODO adjust depending on connection point type
991 net_id2uuid
[vld
.get("id")] = net_uuid
992 db_nets
.append(db_net
)
993 # ip-profile, link db_ip_profile with db_sce_net
994 if vld
.get("ip-profile-ref"):
995 ip_profile_name
= vld
.get("ip-profile-ref")
996 if ip_profile_name
not in ip_profile_name2db_table_index
:
997 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vld[{}]':'ip-profile-ref':"
998 "'{}'. Reference to a non-existing 'ip_profiles'".format(
999 str(vnfd
["id"]), str(vld
["id"]), str(vld
["ip-profile-ref"])),
1000 httperrors
.Bad_Request
)
1001 db_ip_profiles
[ip_profile_name2db_table_index
[ip_profile_name
]]["net_id"] = net_uuid
1002 else: #check no ip-address has been defined
1003 for icp
in vld
.get("internal-connection-point").values():
1004 if icp
.get("ip-address"):
1005 raise NfvoException("Error at 'vnfd[{}]':'vld[{}]':'internal-connection-point[{}]' "
1006 "contains an ip-address but no ip-profile has been defined at VLD".format(
1007 str(vnfd
["id"]), str(vld
["id"]), str(icp
["id"])),
1008 httperrors
.Bad_Request
)
1010 # connection points vaiable declaration
1011 cp_name2iface_uuid
= {}
1013 cp_name2vm_uuid
= {}
1014 cp_name2db_interface
= {}
1015 vdu_id2cp_name
= {} # stored only when one external connection point is presented at this VDU
1019 vdu_id2db_table_index
= {}
1021 for vdu
in vnfd
.get("vdu").values():
1023 for vdu_descriptor
in vnfd_descriptor
["vdu"]:
1024 if vdu_descriptor
["id"] == str(vdu
["id"]):
1026 vm_uuid
= str(uuid4())
1027 uuid_list
.append(vm_uuid
)
1028 vdu_id
= get_str(vdu
, "id", 255)
1032 "name": get_str(vdu
, "name", 255),
1033 "description": get_str(vdu
, "description", 255),
1034 "pdu_type": get_str(vdu
, "pdu-type", 255),
1037 vdu_id2uuid
[db_vm
["osm_id"]] = vm_uuid
1038 vdu_id2db_table_index
[db_vm
["osm_id"]] = db_vms_index
1039 if vdu
.get("count"):
1040 db_vm
["count"] = int(vdu
["count"])
1043 image_present
= False
1044 if vdu
.get("image"):
1045 image_present
= True
1047 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, vdu
)
1049 image_uuid
= db_image
["uuid"]
1050 db_images
.append(db_image
)
1051 db_vm
["image_id"] = image_uuid
1052 if vdu
.get("alternative-images"):
1053 vm_alternative_images
= []
1054 for alt_image
in vdu
.get("alternative-images").values():
1056 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, alt_image
)
1058 image_uuid
= db_image
["uuid"]
1059 db_images
.append(db_image
)
1060 vm_alternative_images
.append({
1061 "image_id": image_uuid
,
1062 "vim_type": str(alt_image
["vim-type"]),
1063 # "universal_name": str(alt_image["image"]),
1064 # "checksum": str(alt_image["image-checksum"]) if alt_image.get("image-checksum") else None
1067 db_vm
["image_list"] = yaml
.safe_dump(vm_alternative_images
, default_flow_style
=True, width
=256)
1071 if vdu
.get("volumes"):
1072 for volume_key
in vdu
["volumes"]:
1073 volume
= vdu
["volumes"][volume_key
]
1074 if not image_present
:
1075 # Convert the first volume to vnfc.image
1076 image_present
= True
1078 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, volume
)
1080 image_uuid
= db_image
["uuid"]
1081 db_images
.append(db_image
)
1082 db_vm
["image_id"] = image_uuid
1084 # Add Openmano devices
1085 device
= {"name": str(volume
.get("name"))}
1086 device
["type"] = str(volume
.get("device-type"))
1087 if volume
.get("size"):
1088 device
["size"] = int(volume
["size"])
1089 if volume
.get("image"):
1090 device
["image name"] = str(volume
["image"])
1091 if volume
.get("image-checksum"):
1092 device
["image checksum"] = str(volume
["image-checksum"])
1094 devices
.append(device
)
1096 if not db_vm
.get("image_id"):
1097 if not db_vm
["pdu_type"]:
1098 raise NfvoException("Not defined image for VDU")
1099 # create a fake image
1103 if vdu
.get("cloud-init"):
1104 boot_data
["user-data"] = str(vdu
["cloud-init"])
1105 elif vdu
.get("cloud-init-file"):
1106 # TODO Where this file content is present???
1107 # boot_data["user-data"] = vnfd_yang.files[vdu["cloud-init-file"]]
1108 boot_data
["user-data"] = str(vdu
["cloud-init-file"])
1110 if vdu
.get("supplemental-boot-data"):
1111 if vdu
["supplemental-boot-data"].get('boot-data-drive'):
1112 boot_data
['boot-data-drive'] = True
1113 if vdu
["supplemental-boot-data"].get('config-file'):
1114 om_cfgfile_list
= list()
1115 for custom_config_file
in vdu
["supplemental-boot-data"]['config-file'].values():
1116 # TODO Where this file content is present???
1117 cfg_source
= str(custom_config_file
["source"])
1118 om_cfgfile_list
.append({"dest": custom_config_file
["dest"],
1119 "content": cfg_source
})
1120 boot_data
['config-files'] = om_cfgfile_list
1122 db_vm
["boot_data"] = yaml
.safe_dump(boot_data
, default_flow_style
=True, width
=256)
1124 db_vms
.append(db_vm
)
1127 # table interfaces (internal/external interfaces)
1128 flavor_epa_interfaces
= []
1129 # for iface in chain(vdu.get("internal-interface").values(), vdu.get("external-interface").values()):
1130 for iface
in vdu
.get("interface").values():
1131 flavor_epa_interface
= {}
1132 iface_uuid
= str(uuid4())
1133 uuid_list
.append(iface_uuid
)
1136 "internal_name": get_str(iface
, "name", 255),
1139 flavor_epa_interface
["name"] = db_interface
["internal_name"]
1140 if iface
.get("virtual-interface").get("vpci"):
1141 db_interface
["vpci"] = get_str(iface
.get("virtual-interface"), "vpci", 12)
1142 flavor_epa_interface
["vpci"] = db_interface
["vpci"]
1144 if iface
.get("virtual-interface").get("bandwidth"):
1145 bps
= int(iface
.get("virtual-interface").get("bandwidth"))
1146 db_interface
["bw"] = int(math
.ceil(bps
/ 1000000.0))
1147 flavor_epa_interface
["bandwidth"] = "{} Mbps".format(db_interface
["bw"])
1149 if iface
.get("virtual-interface").get("type") == "OM-MGMT":
1150 db_interface
["type"] = "mgmt"
1151 elif iface
.get("virtual-interface").get("type") in ("VIRTIO", "E1000", "PARAVIRT"):
1152 db_interface
["type"] = "bridge"
1153 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1154 elif iface
.get("virtual-interface").get("type") in ("SR-IOV", "PCI-PASSTHROUGH"):
1155 db_interface
["type"] = "data"
1156 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1157 flavor_epa_interface
["dedicated"] = "no" if iface
["virtual-interface"]["type"] == "SR-IOV" \
1159 flavor_epa_interfaces
.append(flavor_epa_interface
)
1161 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vdu[{}]':'interface':'virtual"
1162 "-interface':'type':'{}'. Interface type is not supported".format(
1163 vnfd_id
, vdu_id
, iface
.get("virtual-interface").get("type")),
1164 httperrors
.Bad_Request
)
1166 if iface
.get("mgmt-interface"):
1167 db_interface
["type"] = "mgmt"
1169 if iface
.get("external-connection-point-ref"):
1171 cp
= vnfd
.get("connection-point")[iface
.get("external-connection-point-ref")]
1172 db_interface
["external_name"] = get_str(cp
, "name", 255)
1173 cp_name2iface_uuid
[db_interface
["external_name"]] = iface_uuid
1174 cp_name2vdu_id
[db_interface
["external_name"]] = vdu_id
1175 cp_name2vm_uuid
[db_interface
["external_name"]] = vm_uuid
1176 cp_name2db_interface
[db_interface
["external_name"]] = db_interface
1177 for cp_descriptor
in vnfd_descriptor
["connection-point"]:
1178 if cp_descriptor
["name"] == db_interface
["external_name"]:
1183 if vdu_id
in vdu_id2cp_name
:
1184 vdu_id2cp_name
[vdu_id
] = None # more than two connecdtion point for this VDU
1186 vdu_id2cp_name
[vdu_id
] = db_interface
["external_name"]
1189 if str(cp_descriptor
.get("port-security-enabled")).lower() == "false":
1190 db_interface
["port_security"] = 0
1191 elif str(cp_descriptor
.get("port-security-enabled")).lower() == "true":
1192 db_interface
["port_security"] = 1
1194 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1195 "'interface[{iface}]':'vnfd-connection-point-ref':'{cp}' is not present"
1196 " at connection-point".format(
1197 vnf
=vnfd_id
, vdu
=vdu_id
, iface
=iface
["name"],
1198 cp
=iface
.get("vnfd-connection-point-ref")),
1199 httperrors
.Bad_Request
)
1200 elif iface
.get("internal-connection-point-ref"):
1202 for icp_descriptor
in vdu_descriptor
["internal-connection-point"]:
1203 if icp_descriptor
["id"] == str(iface
.get("internal-connection-point-ref")):
1206 raise KeyError("does not exist at vdu:internal-connection-point")
1209 for vld
in vnfd
.get("internal-vld").values():
1210 for cp
in vld
.get("internal-connection-point").values():
1211 if cp
.get("id-ref") == iface
.get("internal-connection-point-ref"):
1213 raise KeyError("is referenced by more than one 'internal-vld'")
1217 raise KeyError("is not referenced by any 'internal-vld'")
1219 db_interface
["net_id"] = net_id2uuid
[icp_vld
.get("id")]
1220 if str(icp_descriptor
.get("port-security-enabled")).lower() == "false":
1221 db_interface
["port_security"] = 0
1222 elif str(icp_descriptor
.get("port-security-enabled")).lower() == "true":
1223 db_interface
["port_security"] = 1
1224 if icp
.get("ip-address"):
1225 if not icp_vld
.get("ip-profile-ref"):
1227 db_interface
["ip_address"] = str(icp
.get("ip-address"))
1228 except KeyError as e
:
1229 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1230 "'interface[{iface}]':'internal-connection-point-ref':'{cp}'"
1232 vnf
=vnfd_id
, vdu
=vdu_id
, iface
=iface
["name"],
1233 cp
=iface
.get("internal-connection-point-ref"), msg
=str(e
)),
1234 httperrors
.Bad_Request
)
1235 if iface
.get("position"):
1236 db_interface
["created_at"] = int(iface
.get("position")) * 50
1237 if iface
.get("mac-address"):
1238 db_interface
["mac"] = str(iface
.get("mac-address"))
1239 db_interfaces
.append(db_interface
)
1243 "name": get_str(vdu
, "name", 250) + "-flv",
1244 "vcpus": int(vdu
["vm-flavor"].get("vcpu-count", 1)),
1245 "ram": int(vdu
["vm-flavor"].get("memory-mb", 1)),
1246 "disk": int(vdu
["vm-flavor"].get("storage-gb", 0)),
1248 # TODO revise the case of several numa-node-policy node
1252 extended
["devices"] = devices
1253 if flavor_epa_interfaces
:
1254 numa
["interfaces"] = flavor_epa_interfaces
1255 if vdu
.get("guest-epa"): # TODO or dedicated_int:
1256 epa_vcpu_set
= False
1257 if vdu
["guest-epa"].get("numa-node-policy"): # TODO or dedicated_int:
1258 numa_node_policy
= vdu
["guest-epa"].get("numa-node-policy")
1259 if numa_node_policy
.get("node"):
1260 numa_node
= next(iter(numa_node_policy
["node"].values()))
1261 if numa_node
.get("num-cores"):
1262 numa
["cores"] = numa_node
["num-cores"]
1264 if numa_node
.get("paired-threads"):
1265 if numa_node
["paired-threads"].get("num-paired-threads"):
1266 numa
["paired-threads"] = int(numa_node
["paired-threads"]["num-paired-threads"])
1268 if len(numa_node
["paired-threads"].get("paired-thread-ids")):
1269 numa
["paired-threads-id"] = []
1270 for pair
in numa_node
["paired-threads"]["paired-thread-ids"].values():
1271 numa
["paired-threads-id"].append(
1272 (str(pair
["thread-a"]), str(pair
["thread-b"]))
1274 if numa_node
.get("num-threads"):
1275 numa
["threads"] = int(numa_node
["num-threads"])
1277 if numa_node
.get("memory-mb"):
1278 numa
["memory"] = max(int(numa_node
["memory-mb"] / 1024), 1)
1279 if vdu
["guest-epa"].get("mempage-size"):
1280 if vdu
["guest-epa"]["mempage-size"] != "SMALL":
1281 numa
["memory"] = max(int(db_flavor
["ram"] / 1024), 1)
1282 if vdu
["guest-epa"].get("cpu-pinning-policy") and not epa_vcpu_set
:
1283 if vdu
["guest-epa"]["cpu-pinning-policy"] == "DEDICATED":
1284 if vdu
["guest-epa"].get("cpu-thread-pinning-policy") and \
1285 vdu
["guest-epa"]["cpu-thread-pinning-policy"] != "PREFER":
1286 numa
["cores"] = max(db_flavor
["vcpus"], 1)
1288 numa
["threads"] = max(db_flavor
["vcpus"], 1)
1290 if vdu
["guest-epa"].get("cpu-quota") and not epa_vcpu_set
:
1291 cpuquota
= get_resource_allocation_params(vdu
["guest-epa"].get("cpu-quota"))
1293 extended
["cpu-quota"] = cpuquota
1294 if vdu
["guest-epa"].get("mem-quota"):
1295 vduquota
= get_resource_allocation_params(vdu
["guest-epa"].get("mem-quota"))
1297 extended
["mem-quota"] = vduquota
1298 if vdu
["guest-epa"].get("disk-io-quota"):
1299 diskioquota
= get_resource_allocation_params(vdu
["guest-epa"].get("disk-io-quota"))
1301 extended
["disk-io-quota"] = diskioquota
1302 if vdu
["guest-epa"].get("vif-quota"):
1303 vifquota
= get_resource_allocation_params(vdu
["guest-epa"].get("vif-quota"))
1305 extended
["vif-quota"] = vifquota
1307 extended
["numas"] = [numa
]
1309 extended_text
= yaml
.safe_dump(extended
, default_flow_style
=True, width
=256)
1310 db_flavor
["extended"] = extended_text
1311 # look if flavor exist
1312 temp_flavor_dict
= {'disk': db_flavor
.get('disk', 0),
1313 'ram': db_flavor
.get('ram'),
1314 'vcpus': db_flavor
.get('vcpus'),
1315 'extended': db_flavor
.get('extended')
1317 existing_flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
1318 if existing_flavors
:
1319 flavor_uuid
= existing_flavors
[0]["uuid"]
1321 flavor_uuid
= str(uuid4())
1322 uuid_list
.append(flavor_uuid
)
1323 db_flavor
["uuid"] = flavor_uuid
1324 db_flavors
.append(db_flavor
)
1325 db_vm
["flavor_id"] = flavor_uuid
1327 # VNF affinity and antiaffinity
1328 for pg
in vnfd
.get("placement-groups").values():
1329 pg_name
= get_str(pg
, "name", 255)
1330 for vdu
in pg
.get("member-vdus").values():
1331 vdu_id
= get_str(vdu
, "member-vdu-ref", 255)
1332 if vdu_id
not in vdu_id2db_table_index
:
1333 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'placement-groups[{pg}]':"
1334 "'member-vdus':'{vdu}'. Reference to a non-existing vdu".format(
1335 vnf
=vnfd_id
, pg
=pg_name
, vdu
=vdu_id
),
1336 httperrors
.Bad_Request
)
1337 db_vms
[vdu_id2db_table_index
[vdu_id
]]["availability_zone"] = pg_name
1338 # TODO consider the case of isolation and not colocation
1339 # if pg.get("strategy") == "ISOLATION":
1341 # VNF mgmt configuration
1342 if vnfd
["mgmt-interface"].get("vdu-id"):
1343 mgmt_vdu_id
= get_str(vnfd
["mgmt-interface"], "vdu-id", 255)
1344 if mgmt_vdu_id
not in vdu_id2uuid
:
1345 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'vdu-id':"
1346 "'{vdu}'. Reference to a non-existing vdu".format(
1347 vnf
=vnfd_id
, vdu
=mgmt_vdu_id
),
1348 httperrors
.Bad_Request
)
1349 mgmt_access
["vm_id"] = vdu_id2uuid
[mgmt_vdu_id
]
1350 mgmt_access
["vdu-id"] = mgmt_vdu_id
1351 # if only one cp is defined by this VDU, mark this interface as of type "mgmt"
1352 if vdu_id2cp_name
.get(mgmt_vdu_id
):
1353 if cp_name2db_interface
[vdu_id2cp_name
[mgmt_vdu_id
]]:
1354 cp_name2db_interface
[vdu_id2cp_name
[mgmt_vdu_id
]]["type"] = "mgmt"
1356 if vnfd
["mgmt-interface"].get("ip-address"):
1357 mgmt_access
["ip-address"] = str(vnfd
["mgmt-interface"].get("ip-address"))
1358 if vnfd
["mgmt-interface"].get("cp"):
1359 if vnfd
["mgmt-interface"]["cp"] not in cp_name2iface_uuid
:
1360 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'cp'['{cp}']. "
1361 "Reference to a non-existing connection-point".format(
1362 vnf
=vnfd_id
, cp
=vnfd
["mgmt-interface"]["cp"]),
1363 httperrors
.Bad_Request
)
1364 mgmt_access
["vm_id"] = cp_name2vm_uuid
[vnfd
["mgmt-interface"]["cp"]]
1365 mgmt_access
["interface_id"] = cp_name2iface_uuid
[vnfd
["mgmt-interface"]["cp"]]
1366 mgmt_access
["vdu-id"] = cp_name2vdu_id
[vnfd
["mgmt-interface"]["cp"]]
1367 # mark this interface as of type mgmt
1368 if cp_name2db_interface
[vnfd
["mgmt-interface"]["cp"]]:
1369 cp_name2db_interface
[vnfd
["mgmt-interface"]["cp"]]["type"] = "mgmt"
1371 default_user
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1374 mgmt_access
["default_user"] = default_user
1376 required
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1379 mgmt_access
["required"] = required
1381 password_
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}),
1384 mgmt_access
["password"] = password_
1387 db_vnf
["mgmt_access"] = yaml
.safe_dump(mgmt_access
, default_flow_style
=True, width
=256)
1389 db_vnfs
.append(db_vnf
)
1393 {"images": db_images
},
1394 {"flavors": db_flavors
},
1395 {"ip_profiles": db_ip_profiles
},
1397 {"interfaces": db_interfaces
},
1400 logger
.debug("create_vnf Deployment done vnfDict: %s",
1401 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
1402 mydb
.new_rows(db_tables
, uuid_list
)
1403 return vnfd_uuid_list
1404 except NfvoException
:
1406 except Exception as e
:
1407 logger
.error("Exception {}".format(e
))
1408 raise # NfvoException("Exception {}".format(e), httperrors.Bad_Request)
1411 @deprecated("Use new_vnfd_v3")
1412 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
1413 global global_config
1415 # Step 1. Check the VNF descriptor
1416 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
1417 # Step 2. Check tenant exist
1419 if tenant_id
!= "any":
1420 check_tenant(mydb
, tenant_id
)
1421 if "tenant_id" in vnf_descriptor
["vnf"]:
1422 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1423 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1424 httperrors
.Unauthorized
)
1426 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1427 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1428 if global_config
["auto_push_VNF_to_VIMs"]:
1429 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1431 # Step 4. Review the descriptor and add missing fields
1432 #print vnf_descriptor
1433 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1434 vnf_name
= vnf_descriptor
['vnf']['name']
1435 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1436 if "physical" in vnf_descriptor
['vnf']:
1437 del vnf_descriptor
['vnf']['physical']
1438 #print vnf_descriptor
1440 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1441 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1442 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1444 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1445 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1446 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1448 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1449 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1451 VNFCitem
["name"] = vnfc
['name']
1452 VNFCitem
["availability_zone"] = vnfc
.get('availability_zone')
1453 VNFCitem
["description"] = vnfc
.get("description", 'VM {} of the VNF {}'.format(vnfc
['name'],vnf_name
))
1455 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1458 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1459 myflavorDict
["description"] = VNFCitem
["description"]
1460 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1461 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1462 myflavorDict
["disk"] = vnfc
.get("disk", 0)
1463 myflavorDict
["extended"] = {}
1465 devices
= vnfc
.get("devices")
1467 myflavorDict
["extended"]["devices"] = devices
1470 # 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
1471 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1473 # Previous code has been commented
1474 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1475 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1476 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1477 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1479 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1481 # print "Error creating flavor: unknown processor model. Rollback successful."
1482 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1484 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1485 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1487 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1488 myflavorDict
['extended']['numas'] = vnfc
['numas']
1492 # Step 6.2 New flavors are created in the VIM
1493 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1495 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1496 VNFCitem
["flavor_id"] = flavor_id
1497 VNFCDict
[vnfc
['name']] = VNFCitem
1499 logger
.debug("Creating new images in the VIM for each VNFC")
1500 # Step 6.3 New images are created in the VIM
1501 #For each VNFC, we must create the appropriate image.
1502 #This "for" loop might be integrated with the previous one
1503 #In case this integration is made, the VNFCDict might become a VNFClist.
1504 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1505 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1507 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1508 image_dict
['universal_name']=vnfc
.get('image name')
1509 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1510 image_dict
['location']=vnfc
.get('VNFC image')
1511 #image_dict['new_location']=vnfc.get('image location')
1512 image_dict
['checksum']=vnfc
.get('image checksum')
1513 image_metadata_dict
= vnfc
.get('image metadata', None)
1514 image_metadata_str
= None
1515 if image_metadata_dict
is not None:
1516 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1517 image_dict
['metadata']=image_metadata_str
1518 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1519 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1520 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1521 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1522 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1523 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1524 if vnfc
.get("boot-data"):
1525 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1528 # Step 7. Storing the VNF descriptor in the repository
1529 if "descriptor" not in vnf_descriptor
["vnf"]:
1530 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1532 # Step 8. Adding the VNF to the NFVO DB
1533 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1535 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1536 _
, message
= rollback(mydb
, vims
, rollback_list
)
1537 if isinstance(e
, db_base_Exception
):
1538 error_text
= "Exception at database"
1539 elif isinstance(e
, KeyError):
1540 error_text
= "KeyError exception "
1541 e
.http_code
= httperrors
.Internal_Server_Error
1543 error_text
= "Exception at VIM"
1544 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1545 #logger.error("start_scenario %s", error_text)
1546 raise NfvoException(error_text
, e
.http_code
)
1549 @deprecated("Use new_vnfd_v3")
1550 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
1551 global global_config
1553 # Step 1. Check the VNF descriptor
1554 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
1555 # Step 2. Check tenant exist
1557 if tenant_id
!= "any":
1558 check_tenant(mydb
, tenant_id
)
1559 if "tenant_id" in vnf_descriptor
["vnf"]:
1560 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1561 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1562 httperrors
.Unauthorized
)
1564 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1565 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1566 if global_config
["auto_push_VNF_to_VIMs"]:
1567 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1569 # Step 4. Review the descriptor and add missing fields
1570 #print vnf_descriptor
1571 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1572 vnf_name
= vnf_descriptor
['vnf']['name']
1573 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1574 if "physical" in vnf_descriptor
['vnf']:
1575 del vnf_descriptor
['vnf']['physical']
1576 #print vnf_descriptor
1578 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1579 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1580 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1582 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1583 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1584 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1586 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1587 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1589 VNFCitem
["name"] = vnfc
['name']
1590 VNFCitem
["description"] = vnfc
.get("description", 'VM {} of the VNF {}'.format(vnfc
['name'],vnf_name
))
1592 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1595 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1596 myflavorDict
["description"] = VNFCitem
["description"]
1597 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1598 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1599 myflavorDict
["disk"] = vnfc
.get("disk", 0)
1600 myflavorDict
["extended"] = {}
1602 devices
= vnfc
.get("devices")
1604 myflavorDict
["extended"]["devices"] = devices
1607 # 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
1608 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1610 # Previous code has been commented
1611 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1612 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1613 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1614 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1616 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1618 # print "Error creating flavor: unknown processor model. Rollback successful."
1619 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1621 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1622 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1624 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1625 myflavorDict
['extended']['numas'] = vnfc
['numas']
1629 # Step 6.2 New flavors are created in the VIM
1630 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1632 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1633 VNFCitem
["flavor_id"] = flavor_id
1634 VNFCDict
[vnfc
['name']] = VNFCitem
1636 logger
.debug("Creating new images in the VIM for each VNFC")
1637 # Step 6.3 New images are created in the VIM
1638 #For each VNFC, we must create the appropriate image.
1639 #This "for" loop might be integrated with the previous one
1640 #In case this integration is made, the VNFCDict might become a VNFClist.
1641 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1642 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1644 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1645 image_dict
['universal_name']=vnfc
.get('image name')
1646 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1647 image_dict
['location']=vnfc
.get('VNFC image')
1648 #image_dict['new_location']=vnfc.get('image location')
1649 image_dict
['checksum']=vnfc
.get('image checksum')
1650 image_metadata_dict
= vnfc
.get('image metadata', None)
1651 image_metadata_str
= None
1652 if image_metadata_dict
is not None:
1653 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1654 image_dict
['metadata']=image_metadata_str
1655 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1656 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1657 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1658 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1659 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1660 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1661 if vnfc
.get("boot-data"):
1662 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1664 # Step 7. Storing the VNF descriptor in the repository
1665 if "descriptor" not in vnf_descriptor
["vnf"]:
1666 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1668 # Step 8. Adding the VNF to the NFVO DB
1669 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1671 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1672 _
, message
= rollback(mydb
, vims
, rollback_list
)
1673 if isinstance(e
, db_base_Exception
):
1674 error_text
= "Exception at database"
1675 elif isinstance(e
, KeyError):
1676 error_text
= "KeyError exception "
1677 e
.http_code
= httperrors
.Internal_Server_Error
1679 error_text
= "Exception at VIM"
1680 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1681 #logger.error("start_scenario %s", error_text)
1682 raise NfvoException(error_text
, e
.http_code
)
1685 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
1686 #check valid tenant_id
1687 check_tenant(mydb
, tenant_id
)
1690 if tenant_id
!= "any":
1691 where_or
["tenant_id"] = tenant_id
1692 where_or
["public"] = True
1693 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1695 vnf_id
= vnf
["uuid"]
1696 filter_keys
= ('uuid', 'name', 'description', 'public', "tenant_id", "osm_id", "created_at")
1697 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.items() if k
in filter_keys
)
1698 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
1699 data
={'vnf' : filtered_content
}
1701 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
1702 SELECT
=('vms.uuid as uuid', 'vms.osm_id as osm_id', 'vms.name as name', 'vms.description as description',
1704 WHERE
={'vnfs.uuid': vnf_id
} )
1705 if len(content
) != 0:
1706 #raise NfvoException("vnf '{}' not found".format(vnf_id), httperrors.Not_Found)
1707 # change boot_data into boot-data
1709 if vm
.get("boot_data"):
1710 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
1713 data
['vnf']['VNFC'] = content
1714 #TODO: GET all the information from a VNFC and include it in the output.
1717 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
1718 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
1719 WHERE
={'vnfs.uuid': vnf_id
} )
1720 data
['vnf']['nets'] = content
1722 #GET ip-profile for each net
1723 for net
in data
['vnf']['nets']:
1724 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1725 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1726 WHERE
={'net_id': net
["uuid"]} )
1727 if len(ipprofiles
)==1:
1728 net
["ip_profile"] = ipprofiles
[0]
1729 elif len(ipprofiles
)>1:
1730 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), httperrors
.Bad_Request
)
1733 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1735 #GET External Interfaces
1736 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1737 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1738 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1739 WHERE
={'vnfs.uuid': vnf_id
, 'interfaces.external_name<>': None} )
1741 data
['vnf']['external-connections'] = content
1746 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1747 # Check tenant exist
1748 if tenant_id
!= "any":
1749 check_tenant(mydb
, tenant_id
)
1750 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1751 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1755 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1757 if tenant_id
!= "any":
1758 where_or
["tenant_id"] = tenant_id
1759 where_or
["public"] = True
1760 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1761 vnf_id
= vnf
["uuid"]
1763 # "Getting the list of flavors and tenants of the VNF"
1764 flavorList
= get_flavorlist(mydb
, vnf_id
)
1765 if len(flavorList
)==0:
1766 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1768 imageList
= get_imagelist(mydb
, vnf_id
)
1769 if len(imageList
)==0:
1770 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1772 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1774 raise NfvoException("vnf '{}' not found".format(vnf_id
), httperrors
.Not_Found
)
1777 for flavor
in flavorList
:
1778 #check if flavor is used by other vnf
1780 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1782 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1784 #flavor not used, must be deleted
1786 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id': flavor
})
1787 for flavor_vim
in c
:
1788 if not flavor_vim
['created']: # skip this flavor because not created by openmano
1792 for vim
in vims
.values():
1793 if vim
["config"]["datacenter_tenant_id"] == flavor_vim
["datacenter_vim_id"]:
1799 myvim
.delete_flavor(flavor_vim
["vim_id"])
1800 except vimconn
.vimconnNotFoundException
:
1801 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"],
1802 flavor_vim
["datacenter_vim_id"] )
1803 except vimconn
.vimconnException
as e
:
1804 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1805 flavor_vim
["vim_id"], flavor_vim
["datacenter_vim_id"], type(e
).__name
__, str(e
))
1806 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"],
1807 flavor_vim
["datacenter_vim_id"]))
1808 # delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1809 mydb
.delete_row_by_id('flavors', flavor
)
1810 except db_base_Exception
as e
:
1811 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1812 undeletedItems
.append("flavor {}".format(flavor
))
1815 for image
in imageList
:
1817 #check if image is used by other vnf
1818 c
= mydb
.get_rows(FROM
='vms', WHERE
=[{'image_id': image
}, {'image_list LIKE ': '%' + image
+ '%'}])
1820 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1822 #image not used, must be deleted
1824 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1826 if image_vim
["datacenter_vim_id"] not in vims
: # TODO change to datacenter_tenant_id
1828 if image_vim
['created']=='false': #skip this image because not created by openmano
1830 myvim
=vims
[ image_vim
["datacenter_id"] ]
1832 myvim
.delete_image(image_vim
["vim_id"])
1833 except vimconn
.vimconnNotFoundException
as e
:
1834 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1835 except vimconn
.vimconnException
as e
:
1836 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1837 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1838 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1839 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1840 mydb
.delete_row_by_id('images', image
)
1841 except db_base_Exception
as e
:
1842 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1843 undeletedItems
.append("image {}".format(image
))
1845 return vnf_id
+ " " + vnf
["name"]
1847 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1850 @deprecated("Not used")
1851 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1852 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1856 return -httperrors
.Not_Found
, "datacenter '{}' not found".format(datacenter_name
)
1857 myvim
= next(iter(vims
.values()))
1858 result
,servers
= myvim
.get_hosts_info()
1860 return result
, servers
1861 topology
= {'name':myvim
['name'] , 'servers': servers
}
1862 return result
, topology
1865 def get_hosts(mydb
, nfvo_tenant_id
):
1866 vims
= get_vim(mydb
, nfvo_tenant_id
)
1868 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), httperrors
.Not_Found
)
1870 #print "nfvo.datacenter_action() error. Several datacenters found"
1871 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
1872 myvim
= next(iter(vims
.values()))
1874 hosts
= myvim
.get_hosts()
1875 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1877 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1879 server
={'name':host
['name'], 'vms':[]}
1880 for vm
in host
['instances']:
1881 #get internal name and model
1883 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1884 WHERE
={'vim_vm_id':vm
['id']} )
1886 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1888 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1890 except db_base_Exception
as e
:
1891 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1892 datacenter
['Datacenters'][0]['servers'].append(server
)
1893 #return -400, "en construccion"
1895 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1897 except vimconn
.vimconnException
as e
:
1898 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1901 @deprecated("Use new_nsd_v3")
1902 def new_scenario(mydb
, tenant_id
, topo
):
1904 # result, vims = get_vim(mydb, tenant_id)
1906 # return result, vims
1908 if tenant_id
!= "any":
1909 check_tenant(mydb
, tenant_id
)
1910 if "tenant_id" in topo
:
1911 if topo
["tenant_id"] != tenant_id
:
1912 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1913 httperrors
.Unauthorized
)
1917 #1.1: get VNFs and external_networks (other_nets).
1919 other_nets
={} #external_networks, bridge_networks and data_networkds
1920 nodes
= topo
['topology']['nodes']
1921 for k
in nodes
.keys():
1922 if nodes
[k
]['type'] == 'VNF':
1924 vnfs
[k
]['ifaces'] = {}
1925 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1926 other_nets
[k
] = nodes
[k
]
1927 other_nets
[k
]['external']=True
1928 elif nodes
[k
]['type'] == 'network':
1929 other_nets
[k
] = nodes
[k
]
1930 other_nets
[k
]['external']=False
1933 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1934 for name
,vnf
in vnfs
.items():
1935 where
= {"OR": {"tenant_id": tenant_id
, 'public': "true"}}
1937 error_pos
= "'topology':'nodes':'" + name
+ "'"
1939 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1940 where
['uuid'] = vnf
['vnf_id']
1941 if 'VNF model' in vnf
:
1942 error_text
+= " 'VNF model' " + vnf
['VNF model']
1943 where
['name'] = vnf
['VNF model']
1945 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, httperrors
.Bad_Request
)
1947 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1951 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, httperrors
.Not_Found
)
1953 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", httperrors
.Conflict
)
1954 vnf
['uuid']=vnf_db
[0]['uuid']
1955 vnf
['description']=vnf_db
[0]['description']
1956 #get external interfaces
1957 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1958 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1959 WHERE
={'vnfs.uuid':vnf
['uuid'], 'external_name<>': None} )
1960 for ext_iface
in ext_ifaces
:
1961 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1963 #1.4 get list of connections
1964 conections
= topo
['topology']['connections']
1965 conections_list
= []
1966 conections_list_name
= []
1967 for k
in conections
.keys():
1968 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1969 ifaces_list
= conections
[k
]['nodes'].items()
1970 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1972 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1973 for k2
in conection_pair_list
:
1976 con_type
= conections
[k
].get("type", "link")
1977 if con_type
!= "link":
1979 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), httperrors
.Bad_Request
)
1980 other_nets
[k
] = {'external': False}
1981 if conections
[k
].get("graph"):
1982 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1983 ifaces_list
.append( (k
, None) )
1986 if con_type
== "external_network":
1987 other_nets
[k
]['external'] = True
1988 if conections
[k
].get("model"):
1989 other_nets
[k
]["model"] = conections
[k
]["model"]
1991 other_nets
[k
]["model"] = k
1992 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1993 other_nets
[k
]["model"] = con_type
1995 conections_list_name
.append(k
)
1996 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)
1997 #print set(ifaces_list)
1998 #check valid VNF and iface names
1999 for iface
in ifaces_list
:
2000 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
2001 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
2002 str(k
), iface
[0]), httperrors
.Not_Found
)
2003 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
2004 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
2005 str(k
), iface
[0], iface
[1]), httperrors
.Not_Found
)
2007 #1.5 unify connections from the pair list to a consolidated list
2009 while index
< len(conections_list
):
2011 while index2
< len(conections_list
):
2012 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
2013 conections_list
[index
] |
= conections_list
[index2
]
2014 del conections_list
[index2
]
2015 del conections_list_name
[index2
]
2018 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
2020 #for k in conections_list:
2025 #1.6 Delete non external nets
2026 # for k in other_nets.keys():
2027 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
2028 # for con in conections_list:
2030 # for index in range(0,len(con)):
2031 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
2032 # for index in delete_indexes:
2035 #1.7: Check external_ports are present at database table datacenter_nets
2036 for k
,net
in other_nets
.items():
2037 error_pos
= "'topology':'nodes':'" + k
+ "'"
2038 if net
['external']==False:
2039 if 'name' not in net
:
2041 if 'model' not in net
:
2042 raise NfvoException("needed a 'model' at " + error_pos
, httperrors
.Bad_Request
)
2043 if net
['model']=='bridge_net':
2044 net
['type']='bridge';
2045 elif net
['model']=='dataplane_net':
2048 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, httperrors
.Not_Found
)
2050 #IF we do not want to check that external network exist at datacenter
2055 # if 'net_id' in net:
2056 # error_text += " 'net_id' " + net['net_id']
2057 # WHERE_['uuid'] = net['net_id']
2058 # if 'model' in net:
2059 # error_text += " 'model' " + net['model']
2060 # WHERE_['name'] = net['model']
2061 # if len(WHERE_) == 0:
2062 # return -httperrors.Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
2063 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
2064 # FROM='datacenter_nets', WHERE=WHERE_ )
2066 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
2068 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
2069 # return -httperrors.Bad_Request, "unknown " +error_text+ " at " + error_pos
2071 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
2072 # return -httperrors.Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
2073 # other_nets[k].update(net_db[0])
2076 net_nb
=0 #Number of nets
2077 for con
in conections_list
:
2078 #check if this is connected to a external net
2082 for index
in range(0,len(con
)):
2083 #check if this is connected to a external net
2084 for net_key
in other_nets
.keys():
2085 if con
[index
][0]==net_key
:
2086 if other_net_index
>=0:
2087 error_text
= "There is some interface connected both to net '{}' and net '{}'".format(
2088 con
[other_net_index
][0], net_key
)
2089 #print "nfvo.new_scenario " + error_text
2090 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2092 other_net_index
= index
2093 net_target
= net_key
2095 #print "other_net_index", other_net_index
2097 if other_net_index
>=0:
2098 del con
[other_net_index
]
2099 #IF we do not want to check that external network exist at datacenter
2100 if other_nets
[net_target
]['external'] :
2101 if "name" not in other_nets
[net_target
]:
2102 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
2103 if other_nets
[net_target
]["type"] == "external_network":
2104 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
2105 other_nets
[net_target
]["type"] = "data"
2107 other_nets
[net_target
]["type"] = "bridge"
2109 # if other_nets[net_target]['external'] :
2110 # 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
2111 # if type_=='data' and other_nets[net_target]['type']=="ptp":
2112 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
2113 # print "nfvo.new_scenario " + error_text
2114 # return -httperrors.Bad_Request, error_text
2117 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
2120 net_type_bridge
=False
2122 net_target
= "__-__net"+str(net_nb
)
2123 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
2124 'description':"net-{} in scenario {}".format(net_nb
,topo
['name']),
2127 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
2128 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
2129 if iface_type
=='mgmt' or iface_type
=='bridge':
2130 net_type_bridge
= True
2132 net_type_data
= True
2133 if net_type_bridge
and net_type_data
:
2134 error_text
= "Error connection interfaces of bridge type with data type. Firs node {}, iface {}".format(iface
[0], iface
[1])
2135 #print "nfvo.new_scenario " + error_text
2136 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2137 elif net_type_bridge
:
2140 type_
='data' if len(con
)>2 else 'ptp'
2141 net_list
[net_target
]['type'] = type_
2144 error_text
= "Error connection node {} : {} does not match any VNF or interface".format(iface
[0], iface
[1])
2145 #print "nfvo.new_scenario " + error_text
2147 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2149 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
2150 #1.8.1 obtain management net
2151 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
2152 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
2153 #1.8.2 check all interfaces from all vnfs
2155 add_mgmt_net
= False
2156 for vnf
in vnfs
.values():
2157 for iface
in vnf
['ifaces'].values():
2158 if iface
['type']=='mgmt' and 'net_key' not in iface
:
2159 #iface not connected
2160 iface
['net_key'] = 'mgmt'
2162 if add_mgmt_net
and 'mgmt' not in net_list
:
2163 net_list
['mgmt']=mgmt_net
[0]
2164 net_list
['mgmt']['external']=True
2165 net_list
['mgmt']['graph']={'visible':False}
2167 net_list
.update(other_nets
)
2169 #print 'net_list', net_list
2174 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
2175 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
2176 'tenant_id':tenant_id
, 'name':topo
['name'],
2177 'description':topo
.get('description',topo
['name']),
2178 'public': topo
.get('public', False)
2184 @deprecated("Use new_nsd_v3")
2185 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
2186 """ This creates a new scenario for version 0.2 and 0.3"""
2187 scenario
= scenario_dict
["scenario"]
2188 if tenant_id
!= "any":
2189 check_tenant(mydb
, tenant_id
)
2190 if "tenant_id" in scenario
:
2191 if scenario
["tenant_id"] != tenant_id
:
2192 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
2193 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
2194 scenario
["tenant_id"], tenant_id
), httperrors
.Unauthorized
)
2198 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
2199 for name
,vnf
in scenario
["vnfs"].items():
2200 where
= {"OR": {"tenant_id": tenant_id
, 'public': "true"}}
2202 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
2204 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
2205 where
['uuid'] = vnf
['vnf_id']
2206 if 'vnf_name' in vnf
:
2207 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
2208 where
['name'] = vnf
['vnf_name']
2210 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, httperrors
.Bad_Request
)
2211 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
2214 if len(vnf_db
) == 0:
2215 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, httperrors
.Not_Found
)
2216 elif len(vnf_db
) > 1:
2217 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", httperrors
.Conflict
)
2218 vnf
['uuid'] = vnf_db
[0]['uuid']
2219 vnf
['description'] = vnf_db
[0]['description']
2221 # get external interfaces
2222 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
2223 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
2224 WHERE
={'vnfs.uuid':vnf
['uuid'], 'external_name<>': None} )
2225 for ext_iface
in ext_ifaces
:
2226 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
2227 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
2229 # 2: Insert net_key and ip_address at every vnf interface
2230 for net_name
, net
in scenario
["networks"].items():
2231 net_type_bridge
= False
2232 net_type_data
= False
2233 for iface_dict
in net
["interfaces"]:
2234 if version
== "0.2":
2235 temp_dict
= iface_dict
2237 elif version
== "0.3":
2238 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
2239 ip_address
= iface_dict
.get('ip_address', None)
2240 for vnf
, iface
in temp_dict
.items():
2241 if vnf
not in scenario
["vnfs"]:
2242 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
2244 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2245 raise NfvoException(error_text
, httperrors
.Not_Found
)
2246 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
2247 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
2248 .format(net_name
, iface
)
2249 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2250 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2251 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
2252 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
2253 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
2254 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2255 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2256 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
2257 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
2258 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
2259 if iface_type
== 'mgmt' or iface_type
== 'bridge':
2260 net_type_bridge
= True
2262 net_type_data
= True
2264 if net_type_bridge
and net_type_data
:
2265 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
2267 # logger.debug("nfvo.new_scenario " + error_text)
2268 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2269 elif net_type_bridge
:
2272 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
2274 if net
.get("implementation"): # for v0.3
2275 if type_
== "bridge" and net
["implementation"] == "underlay":
2276 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
2277 "'network':'{}'".format(net_name
)
2278 # logger.debug(error_text)
2279 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2280 elif type_
!= "bridge" and net
["implementation"] == "overlay":
2281 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
2282 "'network':'{}'".format(net_name
)
2283 # logger.debug(error_text)
2284 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2285 net
.pop("implementation")
2286 if "type" in net
and version
== "0.3": # for v0.3
2287 if type_
== "data" and net
["type"] == "e-line":
2288 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
2289 "'e-line' at 'network':'{}'".format(net_name
)
2290 # logger.debug(error_text)
2291 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2292 elif type_
== "ptp" and net
["type"] == "e-lan":
2296 net
['name'] = net_name
2297 net
['external'] = net
.get('external', False)
2299 # 3: insert at database
2300 scenario
["nets"] = scenario
["networks"]
2301 scenario
['tenant_id'] = tenant_id
2302 scenario_id
= mydb
.new_scenario(scenario
)
2306 def new_nsd_v3(mydb
, tenant_id
, nsd_descriptor
):
2308 Parses an OSM IM nsd_catalog and insert at DB
2311 :param nsd_descriptor:
2312 :return: The list of created NSD ids
2315 mynsd
= nsd_catalog
.nsd()
2317 pybindJSONDecoder
.load_ietf_json(nsd_descriptor
, None, None, obj
=mynsd
, skip_unknown
=True)
2318 except Exception as e
:
2319 raise NfvoException("Error. Invalid NS descriptor format: " + str(e
), httperrors
.Bad_Request
)
2323 db_sce_interfaces
= []
2326 db_sce_rsp_hops
= []
2327 db_sce_classifiers
= []
2328 db_sce_classifier_matches
= []
2330 db_ip_profiles_index
= 0
2333 for nsd_yang
in mynsd
.nsd_catalog
.nsd
.values():
2334 nsd
= nsd_yang
.get()
2337 scenario_uuid
= str(uuid4())
2338 uuid_list
.append(scenario_uuid
)
2339 nsd_uuid_list
.append(scenario_uuid
)
2341 "uuid": scenario_uuid
,
2342 "osm_id": get_str(nsd
, "id", 255),
2343 "name": get_str(nsd
, "name", 255),
2344 "description": get_str(nsd
, "description", 255),
2345 "tenant_id": tenant_id
,
2346 "vendor": get_str(nsd
, "vendor", 255),
2347 "short_name": get_str(nsd
, "short-name", 255),
2348 "descriptor": str(nsd_descriptor
)[:60000],
2350 db_scenarios
.append(db_scenario
)
2352 # table sce_vnfs (constituent-vnfd)
2353 vnf_index2scevnf_uuid
= {}
2354 vnf_index2vnf_uuid
= {}
2355 for vnf
in nsd
.get("constituent-vnfd").values():
2356 existing_vnf
= mydb
.get_rows(FROM
="vnfs", WHERE
={'osm_id': str(vnf
["vnfd-id-ref"])[:255],
2357 'tenant_id': tenant_id
})
2358 if not existing_vnf
:
2359 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'constituent-vnfd':'vnfd-id-ref':"
2360 "'{}'. Reference to a non-existing VNFD in the catalog".format(
2361 str(nsd
["id"]), str(vnf
["vnfd-id-ref"])[:255]),
2362 httperrors
.Bad_Request
)
2363 sce_vnf_uuid
= str(uuid4())
2364 uuid_list
.append(sce_vnf_uuid
)
2366 "uuid": sce_vnf_uuid
,
2367 "scenario_id": scenario_uuid
,
2368 # "name": get_str(vnf, "member-vnf-index", 255),
2369 "name": existing_vnf
[0]["name"][:200] + "." + get_str(vnf
, "member-vnf-index", 50),
2370 "vnf_id": existing_vnf
[0]["uuid"],
2371 "member_vnf_index": str(vnf
["member-vnf-index"]),
2372 # TODO 'start-by-default': True
2374 vnf_index2scevnf_uuid
[str(vnf
['member-vnf-index'])] = sce_vnf_uuid
2375 vnf_index2vnf_uuid
[str(vnf
['member-vnf-index'])] = existing_vnf
[0]["uuid"]
2376 db_sce_vnfs
.append(db_sce_vnf
)
2378 # table ip_profiles (ip-profiles)
2379 ip_profile_name2db_table_index
= {}
2380 for ip_profile
in nsd
.get("ip-profiles").values():
2382 "ip_version": str(ip_profile
["ip-profile-params"].get("ip-version", "ipv4")),
2383 "subnet_address": str(ip_profile
["ip-profile-params"].get("subnet-address")),
2384 "gateway_address": str(ip_profile
["ip-profile-params"].get("gateway-address")),
2385 "dhcp_enabled": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("enabled", True)),
2386 "dhcp_start_address": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("start-address")),
2387 "dhcp_count": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("count")),
2390 for dns
in ip_profile
["ip-profile-params"]["dns-server"].values():
2391 dns_list
.append(str(dns
.get("address")))
2392 db_ip_profile
["dns_address"] = ";".join(dns_list
)
2393 if ip_profile
["ip-profile-params"].get('security-group'):
2394 db_ip_profile
["security_group"] = ip_profile
["ip-profile-params"]['security-group']
2395 ip_profile_name2db_table_index
[str(ip_profile
["name"])] = db_ip_profiles_index
2396 db_ip_profiles_index
+= 1
2397 db_ip_profiles
.append(db_ip_profile
)
2399 # table sce_nets (internal-vld)
2400 for vld
in nsd
.get("vld").values():
2401 sce_net_uuid
= str(uuid4())
2402 uuid_list
.append(sce_net_uuid
)
2404 "uuid": sce_net_uuid
,
2405 "name": get_str(vld
, "name", 255),
2406 "scenario_id": scenario_uuid
,
2408 "multipoint": not vld
.get("type") == "ELINE",
2409 "osm_id": get_str(vld
, "id", 255),
2411 "description": get_str(vld
, "description", 255),
2413 # guess type of network
2414 if vld
.get("mgmt-network"):
2415 db_sce_net
["type"] = "bridge"
2416 db_sce_net
["external"] = True
2417 elif vld
.get("provider-network").get("overlay-type") == "VLAN":
2418 db_sce_net
["type"] = "data"
2420 # later on it will be fixed to bridge or data depending on the type of interfaces attached to it
2421 db_sce_net
["type"] = None
2422 db_sce_nets
.append(db_sce_net
)
2424 # ip-profile, link db_ip_profile with db_sce_net
2425 if vld
.get("ip-profile-ref"):
2426 ip_profile_name
= vld
.get("ip-profile-ref")
2427 if ip_profile_name
not in ip_profile_name2db_table_index
:
2428 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'ip-profile-ref':'{}'."
2429 " Reference to a non-existing 'ip_profiles'".format(
2430 str(nsd
["id"]), str(vld
["id"]), str(vld
["ip-profile-ref"])),
2431 httperrors
.Bad_Request
)
2432 db_ip_profiles
[ip_profile_name2db_table_index
[ip_profile_name
]]["sce_net_id"] = sce_net_uuid
2433 elif vld
.get("vim-network-name"):
2434 db_sce_net
["vim_network_name"] = get_str(vld
, "vim-network-name", 255)
2436 # table sce_interfaces (vld:vnfd-connection-point-ref)
2437 for iface
in vld
.get("vnfd-connection-point-ref").values():
2438 vnf_index
= str(iface
['member-vnf-index-ref'])
2439 # check correct parameters
2440 if vnf_index
not in vnf_index2vnf_uuid
:
2441 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2442 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2443 "'nsd':'constituent-vnfd'".format(
2444 str(nsd
["id"]), str(vld
["id"]), str(iface
["member-vnf-index-ref"])),
2445 httperrors
.Bad_Request
)
2447 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid', 'i.type as iface_type'),
2448 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2449 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2450 'external_name': get_str(iface
, "vnfd-connection-point-ref",
2452 if not existing_ifaces
:
2453 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2454 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2455 "connection-point name at VNFD '{}'".format(
2456 str(nsd
["id"]), str(vld
["id"]), str(iface
["vnfd-connection-point-ref"]),
2457 str(iface
.get("vnfd-id-ref"))[:255]),
2458 httperrors
.Bad_Request
)
2459 interface_uuid
= existing_ifaces
[0]["uuid"]
2460 if existing_ifaces
[0]["iface_type"] == "data":
2461 db_sce_net
["type"] = "data"
2462 sce_interface_uuid
= str(uuid4())
2463 uuid_list
.append(sce_net_uuid
)
2464 iface_ip_address
= None
2465 if iface
.get("ip-address"):
2466 iface_ip_address
= str(iface
.get("ip-address"))
2467 db_sce_interface
= {
2468 "uuid": sce_interface_uuid
,
2469 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2470 "sce_net_id": sce_net_uuid
,
2471 "interface_id": interface_uuid
,
2472 "ip_address": iface_ip_address
,
2474 db_sce_interfaces
.append(db_sce_interface
)
2475 if not db_sce_net
["type"]:
2476 db_sce_net
["type"] = "bridge"
2478 # table sce_vnffgs (vnffgd)
2479 for vnffg
in nsd
.get("vnffgd").values():
2480 sce_vnffg_uuid
= str(uuid4())
2481 uuid_list
.append(sce_vnffg_uuid
)
2483 "uuid": sce_vnffg_uuid
,
2484 "name": get_str(vnffg
, "name", 255),
2485 "scenario_id": scenario_uuid
,
2486 "vendor": get_str(vnffg
, "vendor", 255),
2487 "description": get_str(vld
, "description", 255),
2489 db_sce_vnffgs
.append(db_sce_vnffg
)
2492 for rsp
in vnffg
.get("rsp").values():
2493 sce_rsp_uuid
= str(uuid4())
2494 uuid_list
.append(sce_rsp_uuid
)
2496 "uuid": sce_rsp_uuid
,
2497 "name": get_str(rsp
, "name", 255),
2498 "sce_vnffg_id": sce_vnffg_uuid
,
2499 "id": get_str(rsp
, "id", 255), # only useful to link with classifiers; will be removed later in the code
2501 db_sce_rsps
.append(db_sce_rsp
)
2502 for iface
in rsp
.get("vnfd-connection-point-ref").values():
2503 vnf_index
= str(iface
['member-vnf-index-ref'])
2504 if_order
= int(iface
['order'])
2505 # check correct parameters
2506 if vnf_index
not in vnf_index2vnf_uuid
:
2507 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2508 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2509 "'nsd':'constituent-vnfd'".format(
2510 str(nsd
["id"]), str(rsp
["id"]), str(iface
["member-vnf-index-ref"])),
2511 httperrors
.Bad_Request
)
2513 ingress_existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2514 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2516 'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2517 'external_name': get_str(iface
, "vnfd-ingress-connection-point-ref",
2519 if not ingress_existing_ifaces
:
2520 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2521 "-ref':'vnfd-ingress-connection-point-ref':'{}'. Reference to a non-existing "
2522 "connection-point name at VNFD '{}'".format(
2523 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-ingress-connection-point-ref"]),
2524 str(iface
.get("vnfd-id-ref"))[:255]), httperrors
.Bad_Request
)
2526 egress_existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2527 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2529 'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2530 'external_name': get_str(iface
, "vnfd-egress-connection-point-ref",
2532 if not egress_existing_ifaces
:
2533 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2534 "-ref':'vnfd-egress-connection-point-ref':'{}'. Reference to a non-existing "
2535 "connection-point name at VNFD '{}'".format(
2536 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-egress-connection-point-ref"]),
2537 str(iface
.get("vnfd-id-ref"))[:255]), HTTP_Bad_Request
)
2539 ingress_interface_uuid
= ingress_existing_ifaces
[0]["uuid"]
2540 egress_interface_uuid
= egress_existing_ifaces
[0]["uuid"]
2541 sce_rsp_hop_uuid
= str(uuid4())
2542 uuid_list
.append(sce_rsp_hop_uuid
)
2544 "uuid": sce_rsp_hop_uuid
,
2545 "if_order": if_order
,
2546 "ingress_interface_id": ingress_interface_uuid
,
2547 "egress_interface_id": egress_interface_uuid
,
2548 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2549 "sce_rsp_id": sce_rsp_uuid
,
2551 db_sce_rsp_hops
.append(db_sce_rsp_hop
)
2553 # deal with classifiers
2554 for classifier
in vnffg
.get("classifier").values():
2555 sce_classifier_uuid
= str(uuid4())
2556 uuid_list
.append(sce_classifier_uuid
)
2559 vnf_index
= str(classifier
['member-vnf-index-ref'])
2560 if vnf_index
not in vnf_index2vnf_uuid
:
2561 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'classifier[{}]':'vnfd-connection-point"
2562 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2563 "'nsd':'constituent-vnfd'".format(
2564 str(nsd
["id"]), str(classifier
["id"]), str(classifier
["member-vnf-index-ref"])),
2565 httperrors
.Bad_Request
)
2566 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2567 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2568 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2569 'external_name': get_str(classifier
, "vnfd-connection-point-ref",
2571 if not existing_ifaces
:
2572 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2573 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2574 "connection-point name at VNFD '{}'".format(
2575 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-connection-point-ref"]),
2576 str(iface
.get("vnfd-id-ref"))[:255]),
2577 httperrors
.Bad_Request
)
2578 interface_uuid
= existing_ifaces
[0]["uuid"]
2580 db_sce_classifier
= {
2581 "uuid": sce_classifier_uuid
,
2582 "name": get_str(classifier
, "name", 255),
2583 "sce_vnffg_id": sce_vnffg_uuid
,
2584 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2585 "interface_id": interface_uuid
,
2587 rsp_id
= get_str(classifier
, "rsp-id-ref", 255)
2588 rsp
= next((item
for item
in db_sce_rsps
if item
["id"] == rsp_id
), None)
2589 db_sce_classifier
["sce_rsp_id"] = rsp
["uuid"]
2590 db_sce_classifiers
.append(db_sce_classifier
)
2592 for match
in classifier
.get("match-attributes").values():
2593 sce_classifier_match_uuid
= str(uuid4())
2594 uuid_list
.append(sce_classifier_match_uuid
)
2595 db_sce_classifier_match
= {
2596 "uuid": sce_classifier_match_uuid
,
2597 "ip_proto": get_str(match
, "ip-proto", 2),
2598 "source_ip": get_str(match
, "source-ip-address", 16),
2599 "destination_ip": get_str(match
, "destination-ip-address", 16),
2600 "source_port": get_str(match
, "source-port", 5),
2601 "destination_port": get_str(match
, "destination-port", 5),
2602 "sce_classifier_id": sce_classifier_uuid
,
2604 db_sce_classifier_matches
.append(db_sce_classifier_match
)
2607 # remove unneeded id's in sce_rsps
2608 for rsp
in db_sce_rsps
:
2612 {"scenarios": db_scenarios
},
2613 {"sce_nets": db_sce_nets
},
2614 {"ip_profiles": db_ip_profiles
},
2615 {"sce_vnfs": db_sce_vnfs
},
2616 {"sce_interfaces": db_sce_interfaces
},
2617 {"sce_vnffgs": db_sce_vnffgs
},
2618 {"sce_rsps": db_sce_rsps
},
2619 {"sce_rsp_hops": db_sce_rsp_hops
},
2620 {"sce_classifiers": db_sce_classifiers
},
2621 {"sce_classifier_matches": db_sce_classifier_matches
},
2624 logger
.debug("new_nsd_v3 done: %s",
2625 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
2626 mydb
.new_rows(db_tables
, uuid_list
)
2627 return nsd_uuid_list
2628 except NfvoException
:
2630 except Exception as e
:
2631 logger
.error("Exception {}".format(e
))
2632 raise # NfvoException("Exception {}".format(e), httperrors.Bad_Request)
2635 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
2636 data
["uuid"] = scenario_id
2637 data
["tenant_id"] = tenant_id
2638 c
= mydb
.edit_scenario( data
)
2642 @deprecated("Use create_instance")
2643 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
2644 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2645 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
2646 vims
= {datacenter_id
: myvim
}
2647 myvim_tenant
= myvim
['tenant_id']
2648 datacenter_name
= myvim
['name']
2652 #print "Checking that the scenario_id exists and getting the scenario dictionary"
2653 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
=datacenter_id
)
2654 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
2655 scenarioDict
['datacenter_id'] = datacenter_id
2656 #print '================scenarioDict======================='
2657 #print json.dumps(scenarioDict, indent=4)
2658 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
2660 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
2661 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2663 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
2664 auxNetDict
['scenario'] = {}
2666 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
2667 for sce_net
in scenarioDict
['nets']:
2668 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
2670 myNetName
= "{}.{}".format(instance_scenario_name
, sce_net
['name'])
2671 myNetName
= myNetName
[0:255] #limit length
2672 myNetType
= sce_net
['type']
2674 myNetDict
["name"] = myNetName
2675 myNetDict
["type"] = myNetType
2676 myNetDict
["tenant_id"] = myvim_tenant
2677 myNetIPProfile
= sce_net
.get('ip_profile', None)
2679 #We should use the dictionary as input parameter for new_network
2681 if not sce_net
["external"]:
2682 network_id
, _
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2683 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
2684 sce_net
['vim_id'] = network_id
2685 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
2686 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2687 sce_net
["created"] = True
2689 if sce_net
['vim_id'] == None:
2690 error_text
= "Error, datacenter '{}' does not have external network '{}'.".format(
2691 datacenter_name
, sce_net
['name'])
2692 _
, message
= rollback(mydb
, vims
, rollbackList
)
2693 logger
.error("nfvo.start_scenario: %s", error_text
)
2694 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2695 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
2696 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
2698 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
2699 #For each vnf net, we create it and we add it to instanceNetlist.
2701 for sce_vnf
in scenarioDict
['vnfs']:
2702 for net
in sce_vnf
['nets']:
2703 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
2705 myNetName
= "{}.{}".format(instance_scenario_name
,net
['name'])
2706 myNetName
= myNetName
[0:255] #limit length
2707 myNetType
= net
['type']
2709 myNetDict
["name"] = myNetName
2710 myNetDict
["type"] = myNetType
2711 myNetDict
["tenant_id"] = myvim_tenant
2712 myNetIPProfile
= net
.get('ip_profile', None)
2715 #We should use the dictionary as input parameter for new_network
2716 network_id
, _
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2717 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
2718 net
['vim_id'] = network_id
2719 if sce_vnf
['uuid'] not in auxNetDict
:
2720 auxNetDict
[sce_vnf
['uuid']] = {}
2721 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
2722 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2723 net
["created"] = True
2725 #print "auxNetDict:"
2726 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2728 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
2729 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2731 for sce_vnf
in scenarioDict
['vnfs']:
2732 vnf_availability_zones
= []
2733 for vm
in sce_vnf
['vms']:
2734 vm_av
= vm
.get('availability_zone')
2735 if vm_av
and vm_av
not in vnf_availability_zones
:
2736 vnf_availability_zones
.append(vm_av
)
2738 # check if there is enough availability zones available at vim level.
2739 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
2740 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
2741 raise NfvoException('No enough availability zones at VIM for this deployment', httperrors
.Bad_Request
)
2743 for vm
in sce_vnf
['vms']:
2746 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
2747 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
2748 #myVMDict['description'] = vm['description']
2749 myVMDict
['description'] = myVMDict
['name'][0:99]
2751 myVMDict
['start'] = "no"
2752 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2753 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
2755 #create image at vim in case it not exist
2756 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2757 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
2758 vm
['vim_image_id'] = image_id
2760 #create flavor at vim in case it not exist
2761 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2762 if flavor_dict
['extended']!=None:
2763 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'], Loader
=yaml
.Loader
)
2764 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
2765 vm
['vim_flavor_id'] = flavor_id
2768 myVMDict
['imageRef'] = vm
['vim_image_id']
2769 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2770 myVMDict
['networks'] = []
2771 for iface
in vm
['interfaces']:
2773 if iface
['type']=="data":
2774 netDict
['type'] = iface
['model']
2775 elif "model" in iface
and iface
["model"]!=None:
2776 netDict
['model']=iface
['model']
2777 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2778 #discover type of interface looking at flavor
2779 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2780 for flavor_iface
in numa
.get('interfaces',[]):
2781 if flavor_iface
.get('name') == iface
['internal_name']:
2782 if flavor_iface
['dedicated'] == 'yes':
2783 netDict
['type']="PF" #passthrough
2784 elif flavor_iface
['dedicated'] == 'no':
2785 netDict
['type']="VF" #siov
2786 elif flavor_iface
['dedicated'] == 'yes:sriov':
2787 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2788 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2790 netDict
["use"]=iface
['type']
2791 if netDict
["use"]=="data" and not netDict
.get("type"):
2792 #print "netDict", netDict
2793 #print "iface", iface
2794 e_text
= "Cannot determine the interface type PF or VF of VNF '{}' VM '{}' iface '{}'".format(
2795 sce_vnf
['name'], vm
['name'], iface
['internal_name'])
2796 if flavor_dict
.get('extended')==None:
2797 raise NfvoException(e_text
+ "After database migration some information is not available. \
2798 Try to delete and create the scenarios and VNFs again", httperrors
.Conflict
)
2800 raise NfvoException(e_text
, httperrors
.Internal_Server_Error
)
2801 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2802 netDict
["type"]="virtual"
2803 if "vpci" in iface
and iface
["vpci"] is not None:
2804 netDict
['vpci'] = iface
['vpci']
2805 if "mac" in iface
and iface
["mac"] is not None:
2806 netDict
['mac_address'] = iface
['mac']
2807 if "port-security" in iface
and iface
["port-security"] is not None:
2808 netDict
['port_security'] = iface
['port-security']
2809 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2810 netDict
['floating_ip'] = iface
['floating-ip']
2811 netDict
['name'] = iface
['internal_name']
2812 if iface
['net_id'] is None:
2813 for vnf_iface
in sce_vnf
["interfaces"]:
2816 if vnf_iface
['interface_id']==iface
['uuid']:
2817 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
2820 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2821 #skip bridge ifaces not connected to any net
2822 #if 'net_id' not in netDict or netDict['net_id']==None:
2824 myVMDict
['networks'].append(netDict
)
2825 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2826 #print myVMDict['name']
2827 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2828 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2829 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2831 if 'availability_zone' in myVMDict
:
2832 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
2836 vm_id
, _
= myvim
.new_vminstance(myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2837 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2838 availability_zone_index
=av_index
,
2839 availability_zone_list
=vnf_availability_zones
)
2840 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
2841 vm
['vim_id'] = vm_id
2842 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2843 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2844 for net
in myVMDict
['networks']:
2846 for iface
in vm
['interfaces']:
2847 if net
["name"]==iface
["internal_name"]:
2848 iface
["vim_id"]=net
["vim_id"]
2851 logger
.debug("start scenario Deployment done")
2852 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2853 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
2854 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
2855 return mydb
.get_instance_scenario(instance_id
)
2857 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
2858 _
, message
= rollback(mydb
, vims
, rollbackList
)
2859 if isinstance(e
, db_base_Exception
):
2860 error_text
= "Exception at database"
2862 error_text
= "Exception at VIM"
2863 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2864 #logger.error("start_scenario %s", error_text)
2865 raise NfvoException(error_text
, e
.http_code
)
2867 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
2868 """ join the cloud config information into cloud_config_preserve.
2869 In case of conflict cloud_config_preserve preserves
2872 if not cloud_config_preserve
and not cloud_config
:
2875 new_cloud_config
= {"key-pairs":[], "users":[]}
2877 if cloud_config_preserve
:
2878 for key
in cloud_config_preserve
.get("key-pairs", () ):
2879 if key
not in new_cloud_config
["key-pairs"]:
2880 new_cloud_config
["key-pairs"].append(key
)
2882 for key
in cloud_config
.get("key-pairs", () ):
2883 if key
not in new_cloud_config
["key-pairs"]:
2884 new_cloud_config
["key-pairs"].append(key
)
2885 if not new_cloud_config
["key-pairs"]:
2886 del new_cloud_config
["key-pairs"]
2890 new_cloud_config
["users"] += cloud_config
.get("users", () )
2891 if cloud_config_preserve
:
2892 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
2893 index_to_delete
= []
2894 users
= new_cloud_config
.get("users", [])
2895 for index0
in range(0,len(users
)):
2896 if index0
in index_to_delete
:
2898 for index1
in range(index0
+1,len(users
)):
2899 if index1
in index_to_delete
:
2901 if users
[index0
]["name"] == users
[index1
]["name"]:
2902 index_to_delete
.append(index1
)
2903 for key
in users
[index1
].get("key-pairs",()):
2904 if "key-pairs" not in users
[index0
]:
2905 users
[index0
]["key-pairs"] = [key
]
2906 elif key
not in users
[index0
]["key-pairs"]:
2907 users
[index0
]["key-pairs"].append(key
)
2908 index_to_delete
.sort(reverse
=True)
2909 for index
in index_to_delete
:
2911 if not new_cloud_config
["users"]:
2912 del new_cloud_config
["users"]
2915 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
2916 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
2917 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
2918 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
2921 new_cloud_config
["user-data"] = []
2922 if cloud_config
and cloud_config
.get("user-data"):
2923 if isinstance(cloud_config
["user-data"], list):
2924 new_cloud_config
["user-data"] += cloud_config
["user-data"]
2926 new_cloud_config
["user-data"].append(cloud_config
["user-data"])
2927 if cloud_config_preserve
and cloud_config_preserve
.get("user-data"):
2928 if isinstance(cloud_config_preserve
["user-data"], list):
2929 new_cloud_config
["user-data"] += cloud_config_preserve
["user-data"]
2931 new_cloud_config
["user-data"].append(cloud_config_preserve
["user-data"])
2932 if not new_cloud_config
["user-data"]:
2933 del new_cloud_config
["user-data"]
2936 new_cloud_config
["config-files"] = []
2937 if cloud_config
and cloud_config
.get("config-files") != None:
2938 new_cloud_config
["config-files"] += cloud_config
["config-files"]
2939 if cloud_config_preserve
:
2940 for file in cloud_config_preserve
.get("config-files", ()):
2941 for index
in range(0, len(new_cloud_config
["config-files"])):
2942 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
2943 new_cloud_config
["config-files"][index
] = file
2946 new_cloud_config
["config-files"].append(file)
2947 if not new_cloud_config
["config-files"]:
2948 del new_cloud_config
["config-files"]
2949 return new_cloud_config
2952 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
2953 datacenter_id
= None
2954 datacenter_name
= None
2957 if datacenter_tenant_id
:
2958 thread_id
= datacenter_tenant_id
2959 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
2961 where_
={"td.nfvo_tenant_id": tenant_id
}
2962 if datacenter_id_name
:
2963 if utils
.check_valid_uuid(datacenter_id_name
):
2964 datacenter_id
= datacenter_id_name
2965 where_
["dt.datacenter_id"] = datacenter_id
2967 datacenter_name
= datacenter_id_name
2968 where_
["d.name"] = datacenter_name
2969 if datacenter_tenant_id
:
2970 where_
["dt.uuid"] = datacenter_tenant_id
2971 datacenters
= mydb
.get_rows(
2972 SELECT
=("dt.uuid as datacenter_tenant_id",),
2973 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
2974 "join datacenters as d on d.uuid=dt.datacenter_id",
2976 if len(datacenters
) > 1:
2977 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
2979 thread_id
= datacenters
[0]["datacenter_tenant_id"]
2980 thread
= vim_threads
["running"].get(thread_id
)
2982 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
2983 return thread_id
, thread
2984 except db_base_Exception
as e
:
2985 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
2988 def get_datacenter_uuid(mydb
, tenant_id
, datacenter_id_name
):
2990 if utils
.check_valid_uuid(datacenter_id_name
):
2991 WHERE_dict
['d.uuid'] = datacenter_id_name
2993 WHERE_dict
['d.name'] = datacenter_id_name
2996 WHERE_dict
['nfvo_tenant_id'] = tenant_id
2997 from_
= "tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join datacenter_tenants as" \
2998 " dt on td.datacenter_tenant_id=dt.uuid"
3000 from_
= 'datacenters as d'
3001 vimaccounts
= mydb
.get_rows(FROM
=from_
, SELECT
=("d.uuid as uuid, d.name as name",), WHERE
=WHERE_dict
)
3002 if len(vimaccounts
) == 0:
3003 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
3004 elif len(vimaccounts
)>1:
3005 #print "nfvo.datacenter_action() error. Several datacenters found"
3006 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
3007 return vimaccounts
[0]["uuid"], vimaccounts
[0]["name"]
3010 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
3011 datacenter_id
= None
3012 datacenter_name
= None
3013 if datacenter_id_name
:
3014 if utils
.check_valid_uuid(datacenter_id_name
):
3015 datacenter_id
= datacenter_id_name
3017 datacenter_name
= datacenter_id_name
3018 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
3020 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
3022 #print "nfvo.datacenter_action() error. Several datacenters found"
3023 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
3024 for vim_id
, vim_content
in vims
.items():
3025 return vim_id
, vim_content
3029 """Takes dict d and updates it with the values in dict u.
3030 It merges all depth levels"""
3031 for k
, v
in u
.items():
3032 if isinstance(v
, collections
.Mapping
):
3033 r
= update(d
.get(k
, {}), v
)
3040 def _get_wim(db
, wim_account_id
):
3041 # get wim from wim_account
3042 wim_accounts
= db
.get_rows(FROM
='wim_accounts', WHERE
={"uuid": wim_account_id
})
3043 if not wim_accounts
:
3044 raise NfvoException("Not found sdn id={}".format(wim_account_id
), http_code
=httperrors
.Not_Found
)
3045 return wim_accounts
[0]["wim_id"]
3048 def create_instance(mydb
, tenant_id
, instance_dict
):
3049 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
3050 # logger.debug("Creating instance...")
3051 scenario
= instance_dict
["scenario"]
3053 # find main datacenter
3055 myvim_threads_id
= {}
3056 datacenter
= instance_dict
.get("datacenter")
3057 default_wim_account
= instance_dict
.get("wim_account")
3058 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3059 myvims
[default_datacenter_id
] = vim
3060 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
3061 tenant
= mydb
.get_rows_by_id('nfvo_tenants', tenant_id
)
3062 # myvim_tenant = myvim['tenant_id']
3065 # print "Checking that the scenario exists and getting the scenario dictionary"
3066 if isinstance(scenario
, str):
3067 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, datacenter_vim_id
=myvim_threads_id
[default_datacenter_id
],
3068 datacenter_id
=default_datacenter_id
)
3070 scenarioDict
= scenario
3071 scenarioDict
["uuid"] = None
3073 # logger.debug(">>>>>> Dictionaries before merging")
3074 # logger.debug(">>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
3075 # logger.debug(">>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
3077 db_instance_vnfs
= []
3078 db_instance_vms
= []
3079 db_instance_interfaces
= []
3080 db_instance_sfis
= []
3081 db_instance_sfs
= []
3082 db_instance_classifications
= []
3083 db_instance_sfps
= []
3088 instance_name
= instance_dict
["name"]
3089 instance_uuid
= str(uuid4())
3090 uuid_list
.append(instance_uuid
)
3091 db_instance_scenario
= {
3092 "uuid": instance_uuid
,
3093 "name": instance_name
,
3094 "tenant_id": tenant_id
,
3095 "scenario_id": scenarioDict
['uuid'],
3096 "datacenter_id": default_datacenter_id
,
3097 # filled bellow 'datacenter_tenant_id'
3098 "description": instance_dict
.get("description"),
3100 if scenarioDict
.get("cloud-config"):
3101 db_instance_scenario
["cloud_config"] = yaml
.safe_dump(scenarioDict
["cloud-config"],
3102 default_flow_style
=True, width
=256)
3103 instance_action_id
= get_task_id()
3104 db_instance_action
= {
3105 "uuid": instance_action_id
, # same uuid for the instance and the action on create
3106 "tenant_id": tenant_id
,
3107 "instance_id": instance_uuid
,
3108 "description": "CREATE",
3111 # Auxiliary dictionaries from x to y
3112 sce_net2wim_instance
= {}
3113 sce_net2instance
= {}
3114 net2task_id
= {'scenario': {}}
3115 # Mapping between local networks and WIMs
3118 def ip_profile_IM2RO(ip_profile_im
):
3119 # translate from input format to database format
3121 if 'subnet-address' in ip_profile_im
:
3122 ip_profile_ro
['subnet_address'] = ip_profile_im
['subnet-address']
3123 if 'ip-version' in ip_profile_im
:
3124 ip_profile_ro
['ip_version'] = ip_profile_im
['ip-version']
3125 if 'gateway-address' in ip_profile_im
:
3126 ip_profile_ro
['gateway_address'] = ip_profile_im
['gateway-address']
3127 if 'dns-address' in ip_profile_im
:
3128 ip_profile_ro
['dns_address'] = ip_profile_im
['dns-address']
3129 if isinstance(ip_profile_ro
['dns_address'], (list, tuple)):
3130 ip_profile_ro
['dns_address'] = ";".join(ip_profile_ro
['dns_address'])
3131 if 'dhcp' in ip_profile_im
:
3132 ip_profile_ro
['dhcp_start_address'] = ip_profile_im
['dhcp'].get('start-address')
3133 ip_profile_ro
['dhcp_enabled'] = ip_profile_im
['dhcp'].get('enabled', True)
3134 ip_profile_ro
['dhcp_count'] = ip_profile_im
['dhcp'].get('count')
3135 return ip_profile_ro
3137 # logger.debug("Creating instance from scenario-dict:\n%s",
3138 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
3140 # 0 check correct parameters
3141 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).items():
3142 for scenario_net
in scenarioDict
['nets']:
3143 if net_name
== scenario_net
.get("name") or net_name
== scenario_net
.get("osm_id") or net_name
== scenario_net
.get("uuid"):
3146 raise NfvoException("Invalid scenario network name or id '{}' at instance:networks".format(net_name
),
3147 httperrors
.Bad_Request
)
3148 if "sites" not in net_instance_desc
:
3149 net_instance_desc
["sites"] = [ {} ]
3150 site_without_datacenter_field
= False
3151 for site
in net_instance_desc
["sites"]:
3152 if site
.get("datacenter"):
3153 site
["datacenter"], _
= get_datacenter_uuid(mydb
, tenant_id
, site
["datacenter"])
3154 if site
["datacenter"] not in myvims
:
3155 # Add this datacenter to myvims
3156 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
3158 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
3159 site
["datacenter"] = d
# change name to id
3161 if site_without_datacenter_field
:
3162 raise NfvoException("Found more than one entries without datacenter field at "
3163 "instance:networks:{}:sites".format(net_name
), httperrors
.Bad_Request
)
3164 site_without_datacenter_field
= True
3165 site
["datacenter"] = default_datacenter_id
# change name to id
3167 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).items():
3168 for scenario_vnf
in scenarioDict
['vnfs']:
3169 if vnf_name
== scenario_vnf
['member_vnf_index'] or vnf_name
== scenario_vnf
['uuid'] or vnf_name
== scenario_vnf
['name']:
3172 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_name
), httperrors
.Bad_Request
)
3173 if "datacenter" in vnf_instance_desc
:
3174 # Add this datacenter to myvims
3175 vnf_instance_desc
["datacenter"], _
= get_datacenter_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3176 if vnf_instance_desc
["datacenter"] not in myvims
:
3177 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3179 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3180 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
3182 for net_id
, net_instance_desc
in vnf_instance_desc
.get("networks", {}).items():
3183 for scenario_net
in scenario_vnf
['nets']:
3184 if net_id
== scenario_net
['osm_id'] or net_id
== scenario_net
['uuid'] or net_id
== scenario_net
["name"]:
3187 raise NfvoException("Invalid net id or name '{}' at instance:vnfs:networks".format(net_id
), httperrors
.Bad_Request
)
3188 if net_instance_desc
.get("vim-network-name"):
3189 scenario_net
["vim-network-name"] = net_instance_desc
["vim-network-name"]
3190 if net_instance_desc
.get("vim-network-id"):
3191 scenario_net
["vim-network-id"] = net_instance_desc
["vim-network-id"]
3192 if net_instance_desc
.get("name"):
3193 scenario_net
["name"] = net_instance_desc
["name"]
3194 if 'ip-profile' in net_instance_desc
:
3195 ipprofile_db
= ip_profile_IM2RO(net_instance_desc
['ip-profile'])
3196 if 'ip_profile' not in scenario_net
:
3197 scenario_net
['ip_profile'] = ipprofile_db
3199 update(scenario_net
['ip_profile'], ipprofile_db
)
3201 for vdu_id
, vdu_instance_desc
in vnf_instance_desc
.get("vdus", {}).items():
3202 for scenario_vm
in scenario_vnf
['vms']:
3203 if vdu_id
== scenario_vm
['osm_id'] or vdu_id
== scenario_vm
["name"]:
3206 raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id
), httperrors
.Bad_Request
)
3207 scenario_vm
["instance_parameters"] = vdu_instance_desc
3208 for iface_id
, iface_instance_desc
in vdu_instance_desc
.get("interfaces", {}).items():
3209 for scenario_interface
in scenario_vm
['interfaces']:
3210 if iface_id
== scenario_interface
['internal_name'] or iface_id
== scenario_interface
["external_name"]:
3211 scenario_interface
.update(iface_instance_desc
)
3214 raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id
), httperrors
.Bad_Request
)
3216 # 0.1 parse cloud-config parameters
3217 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
3219 # 0.2 merge instance information into scenario
3220 # Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
3221 # However, this is not possible yet.
3222 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).items():
3223 for scenario_net
in scenarioDict
['nets']:
3224 if net_name
== scenario_net
.get("name") or net_name
== scenario_net
.get("osm_id") or net_name
== scenario_net
.get("uuid"):
3225 if "wim_account" in net_instance_desc
and net_instance_desc
["wim_account"] is not None:
3226 scenario_net
["wim_account"] = net_instance_desc
["wim_account"]
3227 if 'ip-profile' in net_instance_desc
:
3228 ipprofile_db
= ip_profile_IM2RO(net_instance_desc
['ip-profile'])
3229 if 'ip_profile' not in scenario_net
:
3230 scenario_net
['ip_profile'] = ipprofile_db
3232 update(scenario_net
['ip_profile'], ipprofile_db
)
3233 for interface
in net_instance_desc
.get('interfaces', ()):
3234 if 'ip_address' in interface
:
3235 for vnf
in scenarioDict
['vnfs']:
3236 if interface
['vnf'] == vnf
['name']:
3237 for vnf_interface
in vnf
['interfaces']:
3238 if interface
['vnf_interface'] == vnf_interface
['external_name']:
3239 vnf_interface
['ip_address'] = interface
['ip_address']
3241 # logger.debug(">>>>>>>> Merged dictionary")
3242 # logger.debug("Creating instance scenario-dict MERGED:\n%s",
3243 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
3245 # 1. Creating new nets (sce_nets) in the VIM"
3246 number_mgmt_networks
= 0
3247 db_instance_nets
= []
3248 db_instance_wim_nets
= []
3249 for sce_net
in scenarioDict
['nets']:
3250 sce_net_uuid
= sce_net
.get('uuid', sce_net
["name"])
3251 # get involved datacenters where this network need to be created
3252 involved_datacenters
= []
3253 for sce_vnf
in scenarioDict
.get("vnfs", ()):
3254 vnf_datacenter
= sce_vnf
.get("datacenter", default_datacenter_id
)
3255 if vnf_datacenter
in involved_datacenters
:
3257 if sce_vnf
.get("interfaces"):
3258 for sce_vnf_ifaces
in sce_vnf
["interfaces"]:
3259 if sce_vnf_ifaces
.get("sce_net_id") == sce_net
["uuid"]:
3260 involved_datacenters
.append(vnf_datacenter
)
3262 if not involved_datacenters
:
3263 involved_datacenters
.append(default_datacenter_id
)
3264 target_wim_account
= sce_net
.get("wim_account", default_wim_account
)
3267 # TODO: use this information during network creation
3268 wim_account_id
= wim_account_name
= None
3269 if len(involved_datacenters
) > 1 and 'uuid' in sce_net
:
3270 if target_wim_account
is None or target_wim_account
is True: # automatic selection of WIM
3271 # OBS: sce_net without uuid are used internally to VNFs
3272 # and the assumption is that VNFs will not be split among
3273 # different datacenters
3274 wim_account
= wim_engine
.find_suitable_wim_account(
3275 involved_datacenters
, tenant_id
)
3276 wim_account_id
= wim_account
['uuid']
3277 wim_account_name
= wim_account
['name']
3278 wim_usage
[sce_net
['uuid']] = wim_account_id
3279 elif isinstance(target_wim_account
, str): # manual selection of WIM
3280 wim_account
.persist
.get_wim_account_by(target_wim_account
, tenant_id
)
3281 wim_account_id
= wim_account
['uuid']
3282 wim_account_name
= wim_account
['name']
3283 wim_usage
[sce_net
['uuid']] = wim_account_id
3284 else: # not WIM usage
3285 wim_usage
[sce_net
['uuid']] = False
3289 if instance_dict
.get("networks"):
3290 if sce_net
.get("uuid") in instance_dict
["networks"]:
3291 descriptor_net
= instance_dict
["networks"][sce_net
["uuid"]]
3292 descriptor_net_name
= sce_net
["uuid"]
3293 elif sce_net
.get("osm_id") in instance_dict
["networks"]:
3294 descriptor_net
= instance_dict
["networks"][sce_net
["osm_id"]]
3295 descriptor_net_name
= sce_net
["osm_id"]
3296 elif sce_net
["name"] in instance_dict
["networks"]:
3297 descriptor_net
= instance_dict
["networks"][sce_net
["name"]]
3298 descriptor_net_name
= sce_net
["name"]
3299 net_name
= descriptor_net
.get("vim-network-name")
3300 # add datacenters from instantiation parameters
3301 if descriptor_net
.get("sites"):
3302 for site
in descriptor_net
["sites"]:
3303 if site
.get("datacenter") and site
["datacenter"] not in involved_datacenters
:
3304 involved_datacenters
.append(site
["datacenter"])
3305 sce_net2instance
[sce_net_uuid
] = {}
3306 sce_net2wim_instance
[sce_net_uuid
] = {}
3307 net2task_id
['scenario'][sce_net_uuid
] = {}
3310 related_network
= None
3311 if descriptor_net
.get("use-network"):
3312 target_instance_nets
= mydb
.get_rows(
3314 FROM
="instance_nets",
3315 WHERE
={"instance_scenario_id": descriptor_net
["use-network"]["instance_scenario_id"],
3316 "osm_id": descriptor_net
["use-network"]["osm_id"]},
3318 if not target_instance_nets
:
3319 raise NfvoException(
3320 "Cannot find the target network at instance:networks[{}]:use-network".format(descriptor_net_name
),
3321 httperrors
.Bad_Request
)
3323 use_network
= target_instance_nets
[0]["related"]
3325 if sce_net
["external"]:
3326 number_mgmt_networks
+= 1
3328 for datacenter_id
in involved_datacenters
:
3330 netmap_create
= None
3331 if descriptor_net
.get("sites"):
3332 for site
in descriptor_net
["sites"]:
3333 if site
.get("datacenter") == datacenter_id
:
3334 netmap_use
= site
.get("netmap-use")
3335 netmap_create
= site
.get("netmap-create")
3338 vim
= myvims
[datacenter_id
]
3339 myvim_thread_id
= myvim_threads_id
[datacenter_id
]
3341 net_type
= sce_net
['type']
3343 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} # 'shared': True
3346 if sce_net
["external"]:
3347 net_name
= sce_net
["name"]
3349 net_name
= "{}-{}".format(instance_name
, sce_net
["name"])
3350 net_name
= net_name
[:255] # limit length
3352 if netmap_use
or netmap_create
:
3353 create_network
= False
3354 lookfor_network
= False
3356 lookfor_network
= True
3357 if utils
.check_valid_uuid(netmap_use
):
3358 lookfor_filter
["id"] = netmap_use
3360 lookfor_filter
["name"] = netmap_use
3362 create_network
= True
3363 net_vim_name
= net_name
3364 if isinstance(netmap_create
, str):
3365 net_vim_name
= netmap_create
3366 elif sce_net
.get("vim_network_name"):
3367 create_network
= False
3368 lookfor_network
= True
3369 lookfor_filter
["name"] = sce_net
.get("vim_network_name")
3370 elif sce_net
["external"]:
3371 if sce_net
.get('vim_id'):
3372 # there is a netmap at datacenter_nets database # TODO REVISE!!!!
3373 create_network
= False
3374 lookfor_network
= True
3375 lookfor_filter
["id"] = sce_net
['vim_id']
3376 elif vim
["config"].get("management_network_id") or vim
["config"].get("management_network_name"):
3377 if number_mgmt_networks
> 1:
3378 raise NfvoException("Found several VLD of type mgmt. "
3379 "You must concrete what vim-network must be use for each one",
3380 httperrors
.Bad_Request
)
3381 create_network
= False
3382 lookfor_network
= True
3383 if vim
["config"].get("management_network_id"):
3384 lookfor_filter
["id"] = vim
["config"]["management_network_id"]
3386 lookfor_filter
["name"] = vim
["config"]["management_network_name"]
3388 # There is not a netmap, look at datacenter for a net with this name and create if not found
3389 create_network
= True
3390 lookfor_network
= True
3391 lookfor_filter
["name"] = sce_net
["name"]
3392 net_vim_name
= sce_net
["name"]
3394 net_vim_name
= net_name
3395 create_network
= True
3396 lookfor_network
= False
3400 task_action
= "CREATE"
3401 task_extra
["params"] = (net_vim_name
, net_type
, sce_net
.get('ip_profile', None), wim_account_name
)
3403 task_extra
["find"] = (lookfor_filter
,)
3404 elif lookfor_network
:
3405 task_action
= "FIND"
3406 task_extra
["params"] = (lookfor_filter
,)
3408 # fill database content
3409 net_uuid
= str(uuid4())
3410 uuid_list
.append(net_uuid
)
3411 sce_net2instance
[sce_net_uuid
][datacenter_id
] = net_uuid
3412 if not related_network
: # all db_instance_nets will have same related
3413 related_network
= use_network
or net_uuid
3415 sdn_controller
= vim
.config
.get('sdn-controller')
3416 sce_net2wim_instance
[sce_net_uuid
][datacenter_id
] = None
3417 if sdn_controller
and net_type
in ("data", "ptp"):
3418 wim_id
= _get_wim(mydb
, sdn_controller
)
3419 sdn_net_id
= str(uuid4())
3420 sce_net2wim_instance
[sce_net_uuid
][datacenter_id
] = sdn_net_id
3421 task_extra
["sdn_net_id"] = sdn_net_id
3422 db_instance_wim_nets
.append({
3424 "instance_scenario_id": instance_uuid
,
3425 "sce_net_id": sce_net
.get("uuid"),
3427 "wim_account_id": sdn_controller
,
3428 'status': 'BUILD', # if create_network else "ACTIVE"
3429 "related": related_network
,
3430 'multipoint': True if net_type
=="data" else False,
3431 "created": create_network
, # TODO py3
3434 task_wim_extra
= {"params": [net_type
, wim_account_name
]}
3436 "instance_action_id": instance_action_id
,
3437 "status": "SCHEDULED",
3438 "task_index": task_index
,
3439 # "datacenter_vim_id": myvim_thread_id,
3440 "wim_account_id": sdn_controller
,
3441 "action": task_action
,
3442 "item": "instance_wim_nets",
3443 "item_id": sdn_net_id
,
3444 "related": related_network
,
3445 "extra": yaml
.safe_dump(task_wim_extra
, default_flow_style
=True, width
=256)
3448 db_vim_actions
.append(db_vim_action
)
3451 "osm_id": sce_net
.get("osm_id") or sce_net
["name"],
3452 "related": related_network
,
3454 "vim_name": net_vim_name
,
3455 "instance_scenario_id": instance_uuid
,
3456 "sce_net_id": sce_net
.get("uuid"),
3457 "created": create_network
,
3458 'datacenter_id': datacenter_id
,
3459 'datacenter_tenant_id': myvim_thread_id
,
3460 'status': 'BUILD', # if create_network else "ACTIVE"
3461 'sdn_net_id': sdn_net_id
,
3463 db_instance_nets
.append(db_net
)
3465 "instance_action_id": instance_action_id
,
3466 "status": "SCHEDULED",
3467 "task_index": task_index
,
3468 "datacenter_vim_id": myvim_thread_id
,
3469 "action": task_action
,
3470 "item": "instance_nets",
3471 "item_id": net_uuid
,
3472 "related": related_network
,
3473 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
3475 net2task_id
['scenario'][sce_net_uuid
][datacenter_id
] = task_index
3477 db_vim_actions
.append(db_vim_action
)
3479 if 'ip_profile' in sce_net
:
3481 'instance_net_id': net_uuid
,
3482 'ip_version': sce_net
['ip_profile']['ip_version'],
3483 'subnet_address': sce_net
['ip_profile']['subnet_address'],
3484 'gateway_address': sce_net
['ip_profile']['gateway_address'],
3485 'dns_address': sce_net
['ip_profile']['dns_address'],
3486 'dhcp_enabled': sce_net
['ip_profile']['dhcp_enabled'],
3487 'dhcp_start_address': sce_net
['ip_profile']['dhcp_start_address'],
3488 'dhcp_count': sce_net
['ip_profile']['dhcp_count'],
3490 db_ip_profiles
.append(db_ip_profile
)
3494 "default_datacenter_id": default_datacenter_id
,
3495 "myvim_threads_id": myvim_threads_id
,
3496 "instance_uuid": instance_uuid
,
3497 "instance_name": instance_name
,
3498 "instance_action_id": instance_action_id
,
3500 "cloud_config": cloud_config
,
3501 "RO_pub_key": tenant
[0].get('RO_pub_key'),
3502 "instance_parameters": instance_dict
,
3505 "task_index": task_index
,
3506 "uuid_list": uuid_list
,
3507 "db_instance_nets": db_instance_nets
,
3508 "db_instance_wim_nets": db_instance_wim_nets
,
3509 "db_vim_actions": db_vim_actions
,
3510 "db_ip_profiles": db_ip_profiles
,
3511 "db_instance_vnfs": db_instance_vnfs
,
3512 "db_instance_vms": db_instance_vms
,
3513 "db_instance_interfaces": db_instance_interfaces
,
3514 "net2task_id": net2task_id
,
3515 "sce_net2instance": sce_net2instance
,
3516 "sce_net2wim_instance": sce_net2wim_instance
,
3518 # sce_vnf_list = sorted(scenarioDict['vnfs'], key=lambda k: k['name'])
3519 for sce_vnf
in scenarioDict
.get('vnfs', ()): # sce_vnf_list:
3520 instantiate_vnf(mydb
, sce_vnf
, vnf_params
, vnf_params_out
, rollbackList
)
3521 task_index
= vnf_params_out
["task_index"]
3522 uuid_list
= vnf_params_out
["uuid_list"]
3525 # task_depends_on = []
3526 for vnffg
in scenarioDict
.get('vnffgs', ()):
3527 for rsp
in vnffg
['rsps']:
3529 for cp
in rsp
['connection_points']:
3530 count
= mydb
.get_rows(
3532 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_rsp_hops as h "
3533 "on interfaces.uuid=h.ingress_interface_id",
3534 WHERE
={'h.uuid': cp
['uuid']})[0]['count']
3535 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == cp
['sce_vnf_id']), None)
3536 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3538 for instance_vm
in instance_vms
:
3539 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3541 dependencies
.append(action
['task_index'])
3542 # TODO: throw exception if count != len(instance_vms)
3543 # TODO: and action shouldn't ever be None
3545 for i
in range(count
):
3547 sfi_uuid
= str(uuid4())
3549 "ingress_interface_id": cp
["ingress_interface_id"],
3550 "egress_interface_id": cp
["egress_interface_id"]
3552 uuid_list
.append(sfi_uuid
)
3555 "related": sfi_uuid
,
3556 "instance_scenario_id": instance_uuid
,
3557 'sce_rsp_hop_id': cp
['uuid'],
3558 'datacenter_id': datacenter_id
,
3559 'datacenter_tenant_id': myvim_thread_id
,
3560 "vim_sfi_id": None, # vim thread will populate
3562 db_instance_sfis
.append(db_sfi
)
3564 "instance_action_id": instance_action_id
,
3565 "task_index": task_index
,
3566 "datacenter_vim_id": myvim_thread_id
,
3568 "status": "SCHEDULED",
3569 "item": "instance_sfis",
3570 "item_id": sfi_uuid
,
3571 "related": sfi_uuid
,
3572 "extra": yaml
.safe_dump({"params": extra_params
, "depends_on": [dependencies
[i
]]},
3573 default_flow_style
=True, width
=256)
3575 sfis_created
.append(task_index
)
3577 db_vim_actions
.append(db_vim_action
)
3579 sf_uuid
= str(uuid4())
3580 uuid_list
.append(sf_uuid
)
3584 "instance_scenario_id": instance_uuid
,
3585 'sce_rsp_hop_id': cp
['uuid'],
3586 'datacenter_id': datacenter_id
,
3587 'datacenter_tenant_id': myvim_thread_id
,
3588 "vim_sf_id": None, # vim thread will populate
3590 db_instance_sfs
.append(db_sf
)
3592 "instance_action_id": instance_action_id
,
3593 "task_index": task_index
,
3594 "datacenter_vim_id": myvim_thread_id
,
3596 "status": "SCHEDULED",
3597 "item": "instance_sfs",
3600 "extra": yaml
.safe_dump({"params": "", "depends_on": sfis_created
},
3601 default_flow_style
=True, width
=256)
3603 sfs_created
.append(task_index
)
3605 db_vim_actions
.append(db_vim_action
)
3606 classifier
= rsp
['classifier']
3608 # TODO the following ~13 lines can be reused for the sfi case
3609 count
= mydb
.get_rows(
3610 SELECT
=('vms.count'),
3611 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_classifiers as c on interfaces.uuid=c.interface_id",
3612 WHERE
={'c.uuid': classifier
['uuid']})[0]['count']
3613 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == classifier
['sce_vnf_id']), None)
3614 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3616 for instance_vm
in instance_vms
:
3617 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3619 dependencies
.append(action
['task_index'])
3620 # TODO: throw exception if count != len(instance_vms)
3621 # TODO: and action shouldn't ever be None
3622 classifications_created
= []
3623 for i
in range(count
):
3624 for match
in classifier
['matches']:
3625 # create classifications
3626 classification_uuid
= str(uuid4())
3627 uuid_list
.append(classification_uuid
)
3628 db_classification
= {
3629 "uuid": classification_uuid
,
3630 "related": classification_uuid
,
3631 "instance_scenario_id": instance_uuid
,
3632 'sce_classifier_match_id': match
['uuid'],
3633 'datacenter_id': datacenter_id
,
3634 'datacenter_tenant_id': myvim_thread_id
,
3635 "vim_classification_id": None, # vim thread will populate
3637 db_instance_classifications
.append(db_classification
)
3638 classification_params
= {
3639 "ip_proto": match
["ip_proto"],
3640 "source_ip": match
["source_ip"],
3641 "destination_ip": match
["destination_ip"],
3642 "source_port": match
["source_port"],
3643 "destination_port": match
["destination_port"]
3646 "instance_action_id": instance_action_id
,
3647 "task_index": task_index
,
3648 "datacenter_vim_id": myvim_thread_id
,
3650 "status": "SCHEDULED",
3651 "item": "instance_classifications",
3652 "item_id": classification_uuid
,
3653 "related": classification_uuid
,
3654 "extra": yaml
.safe_dump({"params": classification_params
, "depends_on": [dependencies
[i
]]},
3655 default_flow_style
=True, width
=256)
3657 classifications_created
.append(task_index
)
3659 db_vim_actions
.append(db_vim_action
)
3662 sfp_uuid
= str(uuid4())
3663 uuid_list
.append(sfp_uuid
)
3666 "related": sfp_uuid
,
3667 "instance_scenario_id": instance_uuid
,
3668 'sce_rsp_id': rsp
['uuid'],
3669 'datacenter_id': datacenter_id
,
3670 'datacenter_tenant_id': myvim_thread_id
,
3671 "vim_sfp_id": None, # vim thread will populate
3673 db_instance_sfps
.append(db_sfp
)
3675 "instance_action_id": instance_action_id
,
3676 "task_index": task_index
,
3677 "datacenter_vim_id": myvim_thread_id
,
3679 "status": "SCHEDULED",
3680 "item": "instance_sfps",
3681 "item_id": sfp_uuid
,
3682 "related": sfp_uuid
,
3683 "extra": yaml
.safe_dump({"params": "", "depends_on": sfs_created
+ classifications_created
},
3684 default_flow_style
=True, width
=256)
3687 db_vim_actions
.append(db_vim_action
)
3688 db_instance_action
["number_tasks"] = task_index
3691 logger
.debug('wim_usage:\n%s\n\n', pformat(wim_usage
))
3692 wan_links
= wim_engine
.derive_wan_links(wim_usage
, db_instance_nets
, tenant_id
)
3693 wim_actions
= wim_engine
.create_actions(wan_links
)
3694 wim_actions
, db_instance_action
= (
3695 wim_engine
.incorporate_actions(wim_actions
, db_instance_action
))
3698 scenarioDict
["datacenter2tenant"] = myvim_threads_id
3700 db_instance_scenario
['datacenter_tenant_id'] = myvim_threads_id
[default_datacenter_id
]
3701 db_instance_scenario
['datacenter_id'] = default_datacenter_id
3703 {"instance_scenarios": db_instance_scenario
},
3704 {"instance_vnfs": db_instance_vnfs
},
3705 {"instance_nets": db_instance_nets
},
3706 {"ip_profiles": db_ip_profiles
},
3707 {"instance_vms": db_instance_vms
},
3708 {"instance_interfaces": db_instance_interfaces
},
3709 {"instance_actions": db_instance_action
},
3710 {"instance_sfis": db_instance_sfis
},
3711 {"instance_sfs": db_instance_sfs
},
3712 {"instance_classifications": db_instance_classifications
},
3713 {"instance_sfps": db_instance_sfps
},
3714 {"instance_wim_nets": db_instance_wim_nets
+ wan_links
},
3715 {"vim_wim_actions": db_vim_actions
+ wim_actions
}
3718 logger
.debug("create_instance done DB tables: %s",
3719 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
3720 mydb
.new_rows(db_tables
, uuid_list
)
3721 for myvim_thread_id
in myvim_threads_id
.values():
3722 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
3724 wim_engine
.dispatch(wim_actions
)
3726 returned_instance
= mydb
.get_instance_scenario(instance_uuid
)
3727 returned_instance
["action_id"] = instance_action_id
3728 return returned_instance
3729 except (NfvoException
, vimconn
.vimconnException
, sdnconn
.SdnConnectorError
, db_base_Exception
) as e
:
3730 message
= rollback(mydb
, myvims
, rollbackList
)
3731 if isinstance(e
, db_base_Exception
):
3732 error_text
= "database Exception"
3733 elif isinstance(e
, vimconn
.vimconnException
):
3734 error_text
= "VIM Exception"
3735 elif isinstance(e
, sdnconn
.SdnConnectorError
):
3736 error_text
= "WIM Exception"
3738 error_text
= "Exception"
3739 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
3740 # logger.error("create_instance: %s", error_text)
3742 raise NfvoException(error_text
, e
.http_code
)
3745 def instantiate_vnf(mydb
, sce_vnf
, params
, params_out
, rollbackList
):
3746 default_datacenter_id
= params
["default_datacenter_id"]
3747 myvim_threads_id
= params
["myvim_threads_id"]
3748 instance_uuid
= params
["instance_uuid"]
3749 instance_name
= params
["instance_name"]
3750 instance_action_id
= params
["instance_action_id"]
3751 myvims
= params
["myvims"]
3752 cloud_config
= params
["cloud_config"]
3753 RO_pub_key
= params
["RO_pub_key"]
3755 task_index
= params_out
["task_index"]
3756 uuid_list
= params_out
["uuid_list"]
3757 db_instance_nets
= params_out
["db_instance_nets"]
3758 db_instance_wim_nets
= params_out
["db_instance_wim_nets"]
3759 db_vim_actions
= params_out
["db_vim_actions"]
3760 db_ip_profiles
= params_out
["db_ip_profiles"]
3761 db_instance_vnfs
= params_out
["db_instance_vnfs"]
3762 db_instance_vms
= params_out
["db_instance_vms"]
3763 db_instance_interfaces
= params_out
["db_instance_interfaces"]
3764 net2task_id
= params_out
["net2task_id"]
3765 sce_net2instance
= params_out
["sce_net2instance"]
3766 sce_net2wim_instance
= params_out
["sce_net2wim_instance"]
3768 vnf_net2instance
= {}
3770 # 2. Creating new nets (vnf internal nets) in the VIM"
3771 # For each vnf net, we create it and we add it to instanceNetlist.
3772 if sce_vnf
.get("datacenter"):
3773 vim
= myvims
[sce_vnf
["datacenter"]]
3774 datacenter_id
= sce_vnf
["datacenter"]
3775 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
3777 vim
= myvims
[default_datacenter_id
]
3778 datacenter_id
= default_datacenter_id
3779 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
3780 for net
in sce_vnf
['nets']:
3782 # descriptor_net = instance_dict.get("vnfs", {}).get(sce_vnf["name"], {})
3783 # net_name = descriptor_net.get("name")
3786 net_name
= "{}-{}".format(instance_name
, net
["name"])
3787 net_name
= net_name
[:255] # limit length
3788 net_type
= net
['type']
3790 if sce_vnf
['uuid'] not in vnf_net2instance
:
3791 vnf_net2instance
[sce_vnf
['uuid']] = {}
3792 if sce_vnf
['uuid'] not in net2task_id
:
3793 net2task_id
[sce_vnf
['uuid']] = {}
3795 # fill database content
3796 net_uuid
= str(uuid4())
3797 uuid_list
.append(net_uuid
)
3798 vnf_net2instance
[sce_vnf
['uuid']][net
['uuid']] = net_uuid
3800 sdn_controller
= vim
.config
.get('sdn-controller')
3802 if sdn_controller
and net_type
in ("data", "ptp"):
3803 wim_id
= _get_wim(mydb
, sdn_controller
)
3804 sdn_net_id
= str(uuid4())
3805 db_instance_wim_nets
.append({
3807 "instance_scenario_id": instance_uuid
,
3809 "wim_account_id": sdn_controller
,
3810 'status': 'BUILD', # if create_network else "ACTIVE"
3811 "related": net_uuid
,
3812 'multipoint': True if net_type
== "data" else False,
3813 "created": True, # TODO py3
3819 "related": net_uuid
,
3821 "vim_name": net_name
,
3822 "instance_scenario_id": instance_uuid
,
3823 "net_id": net
["uuid"],
3825 'datacenter_id': datacenter_id
,
3826 'datacenter_tenant_id': myvim_thread_id
,
3827 'sdn_net_id': sdn_net_id
,
3829 db_instance_nets
.append(db_net
)
3832 if net
.get("vim-network-name"):
3833 lookfor_filter
["name"] = net
["vim-network-name"]
3834 if net
.get("vim-network-id"):
3835 lookfor_filter
["id"] = net
["vim-network-id"]
3837 task_action
= "FIND"
3838 task_extra
= {"params": (lookfor_filter
,)}
3840 task_action
= "CREATE"
3841 task_extra
= {"params": (net_name
, net_type
, net
.get('ip_profile', None))}
3843 task_extra
["sdn_net_id"] = sdn_net_id
3846 task_wim_extra
= {"params": [net_type
, None]}
3848 "instance_action_id": instance_action_id
,
3849 "status": "SCHEDULED",
3850 "task_index": task_index
,
3851 # "datacenter_vim_id": myvim_thread_id,
3852 "wim_account_id": sdn_controller
,
3853 "action": task_action
,
3854 "item": "instance_wim_nets",
3855 "item_id": sdn_net_id
,
3856 "related": net_uuid
,
3857 "extra": yaml
.safe_dump(task_wim_extra
, default_flow_style
=True, width
=256)
3860 db_vim_actions
.append(db_vim_action
)
3862 "instance_action_id": instance_action_id
,
3863 "task_index": task_index
,
3864 "datacenter_vim_id": myvim_thread_id
,
3865 "status": "SCHEDULED",
3866 "action": task_action
,
3867 "item": "instance_nets",
3868 "item_id": net_uuid
,
3869 "related": net_uuid
,
3870 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
3872 net2task_id
[sce_vnf
['uuid']][net
['uuid']] = task_index
3874 db_vim_actions
.append(db_vim_action
)
3876 if 'ip_profile' in net
:
3878 'instance_net_id': net_uuid
,
3879 'ip_version': net
['ip_profile']['ip_version'],
3880 'subnet_address': net
['ip_profile']['subnet_address'],
3881 'gateway_address': net
['ip_profile']['gateway_address'],
3882 'dns_address': net
['ip_profile']['dns_address'],
3883 'dhcp_enabled': net
['ip_profile']['dhcp_enabled'],
3884 'dhcp_start_address': net
['ip_profile']['dhcp_start_address'],
3885 'dhcp_count': net
['ip_profile']['dhcp_count'],
3887 db_ip_profiles
.append(db_ip_profile
)
3889 # print "vnf_net2instance:"
3890 # print yaml.safe_dump(vnf_net2instance, indent=4, default_flow_style=False)
3892 # 3. Creating new vm instances in the VIM
3893 # myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
3895 if sce_vnf
.get('mgmt_access'):
3896 ssh_access
= sce_vnf
['mgmt_access'].get('config-access', {}).get('ssh-access')
3897 vnf_availability_zones
= []
3898 for vm
in sce_vnf
.get('vms'):
3899 vm_av
= vm
.get('availability_zone')
3900 if vm_av
and vm_av
not in vnf_availability_zones
:
3901 vnf_availability_zones
.append(vm_av
)
3903 # check if there is enough availability zones available at vim level.
3904 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
3905 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
3906 raise NfvoException('No enough availability zones at VIM for this deployment', httperrors
.Bad_Request
)
3908 if sce_vnf
.get("datacenter"):
3909 vim
= myvims
[sce_vnf
["datacenter"]]
3910 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
3911 datacenter_id
= sce_vnf
["datacenter"]
3913 vim
= myvims
[default_datacenter_id
]
3914 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
3915 datacenter_id
= default_datacenter_id
3916 sce_vnf
["datacenter_id"] = datacenter_id
3919 vnf_uuid
= str(uuid4())
3920 uuid_list
.append(vnf_uuid
)
3923 'instance_scenario_id': instance_uuid
,
3924 'vnf_id': sce_vnf
['vnf_id'],
3925 'sce_vnf_id': sce_vnf
['uuid'],
3926 'datacenter_id': datacenter_id
,
3927 'datacenter_tenant_id': myvim_thread_id
,
3929 db_instance_vnfs
.append(db_instance_vnf
)
3931 for vm
in sce_vnf
['vms']:
3933 if vm
.get("pdu_type"):
3937 sce_vnf_name
= sce_vnf
['member_vnf_index'] if sce_vnf
['member_vnf_index'] else sce_vnf
['name']
3938 myVMDict
['name'] = "{}-{}-{}".format(instance_name
[:64], sce_vnf_name
[:64], vm
["name"][:64])
3939 myVMDict
['description'] = myVMDict
['name'][0:99]
3941 # myVMDict['start'] = "no"
3942 if vm
.get("instance_parameters") and vm
["instance_parameters"].get("name"):
3943 myVMDict
['name'] = vm
["instance_parameters"].get("name")
3944 myVMDict
['name'] = myVMDict
['name'][0:255] # limit name length
3945 # create image at vim in case it not exist
3946 image_uuid
= vm
['image_id']
3947 if vm
.get("image_list"):
3948 for alternative_image
in vm
["image_list"]:
3949 if alternative_image
["vim_type"] == vim
["config"]["_vim_type_internal"]:
3950 image_uuid
= alternative_image
['image_id']
3952 image_dict
= mydb
.get_table_by_uuid_name("images", image_uuid
)
3953 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
3954 vm
['vim_image_id'] = image_id
3956 # create flavor at vim in case it not exist
3957 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
3958 if flavor_dict
['extended'] != None:
3959 flavor_dict
['extended'] = yaml
.load(flavor_dict
['extended'], Loader
=yaml
.Loader
)
3960 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
3962 # Obtain information for additional disks
3963 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',),
3964 WHERE
={'vim_id': flavor_id
})
3965 if not extended_flavor_dict
:
3966 raise NfvoException("flavor '{}' not found".format(flavor_id
), httperrors
.Not_Found
)
3968 # extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0], Loader=yaml.Loader)
3969 myVMDict
['disks'] = None
3970 extended_info
= extended_flavor_dict
[0]['extended']
3971 if extended_info
!= None:
3972 extended_flavor_dict_yaml
= yaml
.load(extended_info
, Loader
=yaml
.Loader
)
3973 if 'disks' in extended_flavor_dict_yaml
:
3974 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
3975 if vm
.get("instance_parameters") and vm
["instance_parameters"].get("devices"):
3976 for disk
in myVMDict
['disks']:
3977 if disk
.get("name") in vm
["instance_parameters"]["devices"]:
3978 disk
.update(vm
["instance_parameters"]["devices"][disk
.get("name")])
3980 vm
['vim_flavor_id'] = flavor_id
3981 myVMDict
['imageRef'] = vm
['vim_image_id']
3982 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
3983 myVMDict
['availability_zone'] = vm
.get('availability_zone')
3984 myVMDict
['networks'] = []
3985 task_depends_on
= []
3986 # TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
3987 is_management_vm
= False
3989 for iface
in vm
['interfaces']:
3991 if iface
['type'] == "data":
3992 netDict
['type'] = iface
['model']
3993 elif "model" in iface
and iface
["model"] != None:
3994 netDict
['model'] = iface
['model']
3995 # TODO in future, remove this because mac_address will not be set, and the type of PV,VF
3996 # is obtained from iterface table model
3997 # discover type of interface looking at flavor
3998 for numa
in flavor_dict
.get('extended', {}).get('numas', []):
3999 for flavor_iface
in numa
.get('interfaces', []):
4000 if flavor_iface
.get('name') == iface
['internal_name']:
4001 if flavor_iface
['dedicated'] == 'yes':
4002 netDict
['type'] = "PF" # passthrough
4003 elif flavor_iface
['dedicated'] == 'no':
4004 netDict
['type'] = "VF" # siov
4005 elif flavor_iface
['dedicated'] == 'yes:sriov':
4006 netDict
['type'] = "VFnotShared" # sriov but only one sriov on the PF
4007 netDict
["mac_address"] = flavor_iface
.get("mac_address")
4009 netDict
["use"] = iface
['type']
4010 if netDict
["use"] == "data" and not netDict
.get("type"):
4011 # print "netDict", netDict
4012 # print "iface", iface
4013 e_text
= "Cannot determine the interface type PF or VF of VNF '{}' VM '{}' iface '{}'".fromat(
4014 sce_vnf
['name'], vm
['name'], iface
['internal_name'])
4015 if flavor_dict
.get('extended') == None:
4016 raise NfvoException(e_text
+ "After database migration some information is not available. \
4017 Try to delete and create the scenarios and VNFs again", httperrors
.Conflict
)
4019 raise NfvoException(e_text
, httperrors
.Internal_Server_Error
)
4020 if netDict
["use"] == "mgmt":
4021 is_management_vm
= True
4022 netDict
["type"] = "virtual"
4023 if netDict
["use"] == "bridge":
4024 netDict
["type"] = "virtual"
4025 if iface
.get("vpci"):
4026 netDict
['vpci'] = iface
['vpci']
4027 if iface
.get("mac"):
4028 netDict
['mac_address'] = iface
['mac']
4029 if iface
.get("mac_address"):
4030 netDict
['mac_address'] = iface
['mac_address']
4031 if iface
.get("ip_address"):
4032 netDict
['ip_address'] = iface
['ip_address']
4033 if iface
.get("port-security") is not None:
4034 netDict
['port_security'] = iface
['port-security']
4035 if iface
.get("floating-ip") is not None:
4036 netDict
['floating_ip'] = iface
['floating-ip']
4037 netDict
['name'] = iface
['internal_name']
4038 if iface
['net_id'] is None:
4039 for vnf_iface
in sce_vnf
["interfaces"]:
4042 if vnf_iface
['interface_id'] == iface
['uuid']:
4043 netDict
['net_id'] = "TASK-{}".format(
4044 net2task_id
['scenario'][vnf_iface
['sce_net_id']][datacenter_id
])
4045 instance_net_id
= sce_net2instance
[vnf_iface
['sce_net_id']][datacenter_id
]
4046 instance_wim_net_id
= sce_net2wim_instance
[vnf_iface
['sce_net_id']][datacenter_id
]
4047 task_depends_on
.append(net2task_id
['scenario'][vnf_iface
['sce_net_id']][datacenter_id
])
4050 netDict
['net_id'] = "TASK-{}".format(net2task_id
[sce_vnf
['uuid']][iface
['net_id']])
4051 instance_net_id
= vnf_net2instance
[sce_vnf
['uuid']][iface
['net_id']]
4052 task_depends_on
.append(net2task_id
[sce_vnf
['uuid']][iface
['net_id']])
4053 # skip bridge ifaces not connected to any net
4054 if 'net_id' not in netDict
or netDict
['net_id'] == None:
4056 myVMDict
['networks'].append(netDict
)
4059 # 'instance_vm_id': instance_vm_uuid,
4060 "instance_net_id": instance_net_id
,
4061 "instance_wim_net_id": instance_wim_net_id
,
4062 'interface_id': iface
['uuid'],
4063 # 'vim_interface_id': ,
4064 'type': 'external' if iface
['external_name'] is not None else 'internal',
4065 'model': iface
['model'],
4066 'ip_address': iface
.get('ip_address'),
4067 'mac_address': iface
.get('mac'),
4068 'floating_ip': int(iface
.get('floating-ip', False)),
4069 'port_security': int(iface
.get('port-security', True))
4071 db_vm_ifaces
.append(db_vm_iface
)
4072 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
4073 # print myVMDict['name']
4074 # print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
4075 # print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
4076 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
4078 # We add the RO key to cloud_config if vnf will need ssh access
4079 cloud_config_vm
= cloud_config
4080 if is_management_vm
and params
["instance_parameters"].get("mgmt_keys"):
4081 cloud_config_vm
= unify_cloud_config({"key-pairs": params
["instance_parameters"]["mgmt_keys"]},
4084 if vm
.get("instance_parameters") and "mgmt_keys" in vm
["instance_parameters"]:
4085 if vm
["instance_parameters"]["mgmt_keys"]:
4086 cloud_config_vm
= unify_cloud_config({"key-pairs": vm
["instance_parameters"]["mgmt_keys"]},
4089 cloud_config_vm
= unify_cloud_config(cloud_config_vm
, {"key-pairs": [RO_pub_key
]})
4090 if vm
.get("boot_data"):
4091 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config_vm
)
4093 if myVMDict
.get('availability_zone'):
4094 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
4097 for vm_index
in range(0, vm
.get('count', 1)):
4098 vm_name
= myVMDict
['name'] + "-" + str(vm_index
+1)
4099 task_params
= (vm_name
, myVMDict
['description'], myVMDict
.get('start', None),
4100 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'], cloud_config_vm
,
4101 myVMDict
['disks'], av_index
, vnf_availability_zones
)
4102 # put interface uuid back to scenario[vnfs][vms[[interfaces]
4103 for net
in myVMDict
['networks']:
4105 for iface
in vm
['interfaces']:
4106 if net
["name"] == iface
["internal_name"]:
4107 iface
["vim_id"] = net
["vim_id"]
4109 vm_uuid
= str(uuid4())
4110 uuid_list
.append(vm_uuid
)
4114 'instance_vnf_id': vnf_uuid
,
4115 # TODO delete "vim_vm_id": vm_id,
4116 "vm_id": vm
["uuid"],
4117 "vim_name": vm_name
,
4120 db_instance_vms
.append(db_vm
)
4123 for db_vm_iface
in db_vm_ifaces
:
4124 iface_uuid
= str(uuid4())
4125 uuid_list
.append(iface_uuid
)
4126 db_vm_iface_instance
= {
4128 "instance_vm_id": vm_uuid
4130 db_vm_iface_instance
.update(db_vm_iface
)
4131 if db_vm_iface_instance
.get("ip_address"): # increment ip_address
4132 ip
= db_vm_iface_instance
.get("ip_address")
4137 ip
= ip
[i
:] + str(int(ip
[:i
]) + 1)
4138 db_vm_iface_instance
["ip_address"] = ip
4140 db_vm_iface_instance
["ip_address"] = None
4141 db_instance_interfaces
.append(db_vm_iface_instance
)
4142 myVMDict
['networks'][iface_index
]["uuid"] = iface_uuid
4146 "instance_action_id": instance_action_id
,
4147 "task_index": task_index
,
4148 "datacenter_vim_id": myvim_thread_id
,
4150 "status": "SCHEDULED",
4151 "item": "instance_vms",
4154 "extra": yaml
.safe_dump({"params": task_params
, "depends_on": task_depends_on
},
4155 default_flow_style
=True, width
=256)
4158 db_vim_actions
.append(db_vim_action
)
4159 params_out
["task_index"] = task_index
4160 params_out
["uuid_list"] = uuid_list
4163 def delete_instance(mydb
, tenant_id
, instance_id
):
4164 # print "Checking that the instance_id exists and getting the instance dictionary"
4165 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
4166 # print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
4167 tenant_id
= instanceDict
["tenant_id"]
4170 # We need to retrieve the WIM Actions now, before the instance_scenario is
4171 # deleted. The reason for that is that: ON CASCADE rules will delete the
4172 # instance_wim_nets record in the database
4173 wim_actions
= wim_engine
.delete_actions(instance_scenario_id
=instance_id
)
4176 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
4177 # 1. Delete from Database
4178 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
4180 # 2. delete from VIM
4184 vimthread_affected
= {}
4185 net2vm_dependencies
= {}
4188 instance_action_id
= get_task_id()
4190 db_instance_action
= {
4191 "uuid": instance_action_id
, # same uuid for the instance and the action on create
4192 "tenant_id": tenant_id
,
4193 "instance_id": instance_id
,
4194 "description": "DELETE",
4195 # "number_tasks": 0 # filled bellow
4198 # 2.1 deleting VNFFGs
4199 for sfp
in instanceDict
.get('sfps', ()):
4200 vimthread_affected
[sfp
["datacenter_tenant_id"]] = None
4201 datacenter_key
= (sfp
["datacenter_id"], sfp
["datacenter_tenant_id"])
4202 if datacenter_key
not in myvims
:
4204 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sfp
["datacenter_id"], sfp
["datacenter_tenant_id"])
4205 except NfvoException
as e
:
4206 logger
.error(str(e
))
4208 myvim_threads
[datacenter_key
] = myvim_thread
4209 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sfp
["datacenter_id"],
4210 datacenter_tenant_id
=sfp
["datacenter_tenant_id"])
4212 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfp
["datacenter_id"], sfp
["datacenter_tenant_id"]))
4213 myvims
[datacenter_key
] = None
4215 myvims
[datacenter_key
] = next(iter(vims
.values()))
4216 myvim
= myvims
[datacenter_key
]
4217 myvim_thread
= myvim_threads
[datacenter_key
]
4220 error_msg
+= "\n vim_sfp_id={} cannot be deleted because datacenter={} not found".format(sfp
['vim_sfp_id'], sfp
["datacenter_id"])
4222 extra
= {"params": (sfp
['vim_sfp_id'])}
4224 "instance_action_id": instance_action_id
,
4225 "task_index": task_index
,
4226 "datacenter_vim_id": sfp
["datacenter_tenant_id"],
4228 "status": "SCHEDULED",
4229 "item": "instance_sfps",
4230 "item_id": sfp
["uuid"],
4231 "related": sfp
["related"],
4232 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4235 db_vim_actions
.append(db_vim_action
)
4237 for classification
in instanceDict
['classifications']:
4238 vimthread_affected
[classification
["datacenter_tenant_id"]] = None
4239 datacenter_key
= (classification
["datacenter_id"], classification
["datacenter_tenant_id"])
4240 if datacenter_key
not in myvims
:
4242 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, classification
["datacenter_id"], classification
["datacenter_tenant_id"])
4243 except NfvoException
as e
:
4244 logger
.error(str(e
))
4246 myvim_threads
[datacenter_key
] = myvim_thread
4247 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=classification
["datacenter_id"],
4248 datacenter_tenant_id
=classification
["datacenter_tenant_id"])
4250 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(classification
["datacenter_id"],
4251 classification
["datacenter_tenant_id"]))
4252 myvims
[datacenter_key
] = None
4254 myvims
[datacenter_key
] = next(iter(vims
.values()))
4255 myvim
= myvims
[datacenter_key
]
4256 myvim_thread
= myvim_threads
[datacenter_key
]
4259 error_msg
+= "\n vim_classification_id={} cannot be deleted because datacenter={} not found".format(classification
['vim_classification_id'],
4260 classification
["datacenter_id"])
4262 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfps"]
4263 extra
= {"params": (classification
['vim_classification_id']), "depends_on": depends_on
}
4265 "instance_action_id": instance_action_id
,
4266 "task_index": task_index
,
4267 "datacenter_vim_id": classification
["datacenter_tenant_id"],
4269 "status": "SCHEDULED",
4270 "item": "instance_classifications",
4271 "item_id": classification
["uuid"],
4272 "related": classification
["related"],
4273 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4276 db_vim_actions
.append(db_vim_action
)
4278 for sf
in instanceDict
.get('sfs', ()):
4279 vimthread_affected
[sf
["datacenter_tenant_id"]] = None
4280 datacenter_key
= (sf
["datacenter_id"], sf
["datacenter_tenant_id"])
4281 if datacenter_key
not in myvims
:
4283 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sf
["datacenter_id"], sf
["datacenter_tenant_id"])
4284 except NfvoException
as e
:
4285 logger
.error(str(e
))
4287 myvim_threads
[datacenter_key
] = myvim_thread
4288 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sf
["datacenter_id"],
4289 datacenter_tenant_id
=sf
["datacenter_tenant_id"])
4291 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sf
["datacenter_id"], sf
["datacenter_tenant_id"]))
4292 myvims
[datacenter_key
] = None
4294 myvims
[datacenter_key
] = next(iter(vims
.values()))
4295 myvim
= myvims
[datacenter_key
]
4296 myvim_thread
= myvim_threads
[datacenter_key
]
4299 error_msg
+= "\n vim_sf_id={} cannot be deleted because datacenter={} not found".format(sf
['vim_sf_id'], sf
["datacenter_id"])
4301 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfps"]
4302 extra
= {"params": (sf
['vim_sf_id']), "depends_on": depends_on
}
4304 "instance_action_id": instance_action_id
,
4305 "task_index": task_index
,
4306 "datacenter_vim_id": sf
["datacenter_tenant_id"],
4308 "status": "SCHEDULED",
4309 "item": "instance_sfs",
4310 "item_id": sf
["uuid"],
4311 "related": sf
["related"],
4312 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4315 db_vim_actions
.append(db_vim_action
)
4317 for sfi
in instanceDict
.get('sfis', ()):
4318 vimthread_affected
[sfi
["datacenter_tenant_id"]] = None
4319 datacenter_key
= (sfi
["datacenter_id"], sfi
["datacenter_tenant_id"])
4320 if datacenter_key
not in myvims
:
4322 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sfi
["datacenter_id"], sfi
["datacenter_tenant_id"])
4323 except NfvoException
as e
:
4324 logger
.error(str(e
))
4326 myvim_threads
[datacenter_key
] = myvim_thread
4327 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sfi
["datacenter_id"],
4328 datacenter_tenant_id
=sfi
["datacenter_tenant_id"])
4330 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfi
["datacenter_id"], sfi
["datacenter_tenant_id"]))
4331 myvims
[datacenter_key
] = None
4333 myvims
[datacenter_key
] = next(iter(vims
.values()))
4334 myvim
= myvims
[datacenter_key
]
4335 myvim_thread
= myvim_threads
[datacenter_key
]
4338 error_msg
+= "\n vim_sfi_id={} cannot be deleted because datacenter={} not found".format(sfi
['vim_sfi_id'], sfi
["datacenter_id"])
4340 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfs"]
4341 extra
= {"params": (sfi
['vim_sfi_id']), "depends_on": depends_on
}
4343 "instance_action_id": instance_action_id
,
4344 "task_index": task_index
,
4345 "datacenter_vim_id": sfi
["datacenter_tenant_id"],
4347 "status": "SCHEDULED",
4348 "item": "instance_sfis",
4349 "item_id": sfi
["uuid"],
4350 "related": sfi
["related"],
4351 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4354 db_vim_actions
.append(db_vim_action
)
4358 for sce_vnf
in instanceDict
.get('vnfs', ()):
4359 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
4360 vimthread_affected
[sce_vnf
["datacenter_tenant_id"]] = None
4361 if datacenter_key
not in myvims
:
4363 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
4364 except NfvoException
as e
:
4365 logger
.error(str(e
))
4367 myvim_threads
[datacenter_key
] = myvim_thread
4368 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
4369 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
4371 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
4372 sce_vnf
["datacenter_tenant_id"]))
4373 myvims
[datacenter_key
] = None
4375 myvims
[datacenter_key
] = next(iter(vims
.values()))
4376 myvim
= myvims
[datacenter_key
]
4377 myvim_thread
= myvim_threads
[datacenter_key
]
4379 for vm
in sce_vnf
['vms']:
4381 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
4383 sfi_dependencies
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfis"]
4385 "instance_action_id": instance_action_id
,
4386 "task_index": task_index
,
4387 "datacenter_vim_id": sce_vnf
["datacenter_tenant_id"],
4389 "status": "SCHEDULED",
4390 "item": "instance_vms",
4391 "item_id": vm
["uuid"],
4392 "related": vm
["related"],
4393 "extra": yaml
.safe_dump({"params": vm
["interfaces"], "depends_on": sfi_dependencies
},
4394 default_flow_style
=True, width
=256)
4396 db_vim_actions
.append(db_vim_action
)
4397 for interface
in vm
["interfaces"]:
4398 if not interface
.get("instance_net_id"):
4400 if interface
["instance_net_id"] not in net2vm_dependencies
:
4401 net2vm_dependencies
[interface
["instance_net_id"]] = []
4402 net2vm_dependencies
[interface
["instance_net_id"]].append(task_index
)
4407 for net
in instanceDict
['nets']:
4408 vimthread_affected
[net
["datacenter_tenant_id"]] = None
4409 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
4410 if datacenter_key
not in myvims
:
4412 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, net
["datacenter_id"], net
["datacenter_tenant_id"])
4413 except NfvoException
as e
:
4414 logger
.error(str(e
))
4416 myvim_threads
[datacenter_key
] = myvim_thread
4417 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
4418 datacenter_tenant_id
=net
["datacenter_tenant_id"])
4420 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
4421 myvims
[datacenter_key
] = None
4423 myvims
[datacenter_key
] = next(iter(vims
.values()))
4424 myvim
= myvims
[datacenter_key
]
4425 myvim_thread
= myvim_threads
[datacenter_key
]
4428 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
4430 extra
= {"params": (net
['vim_net_id'], net
['sdn_net_id'])}
4431 if net2vm_dependencies
.get(net
["uuid"]):
4432 extra
["depends_on"] = net2vm_dependencies
[net
["uuid"]]
4433 sfi_dependencies
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfis"]
4434 if len(sfi_dependencies
) > 0:
4435 if "depends_on" in extra
:
4436 extra
["depends_on"] += sfi_dependencies
4438 extra
["depends_on"] = sfi_dependencies
4440 "instance_action_id": instance_action_id
,
4441 "task_index": task_index
,
4442 "datacenter_vim_id": net
["datacenter_tenant_id"],
4444 "status": "SCHEDULED",
4445 "item": "instance_nets",
4446 "item_id": net
["uuid"],
4447 "related": net
["related"],
4448 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4451 db_vim_actions
.append(db_vim_action
)
4452 for sdn_net
in instanceDict
['sdn_nets']:
4453 if not sdn_net
["sdn"]:
4457 "instance_action_id": instance_action_id
,
4458 "task_index": task_index
,
4459 "wim_account_id": sdn_net
["wim_account_id"],
4461 "status": "SCHEDULED",
4462 "item": "instance_wim_nets",
4463 "item_id": sdn_net
["uuid"],
4464 "related": sdn_net
["related"],
4465 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4468 db_vim_actions
.append(db_vim_action
)
4470 db_instance_action
["number_tasks"] = task_index
4473 wim_actions
, db_instance_action
= (
4474 wim_engine
.incorporate_actions(wim_actions
, db_instance_action
))
4478 {"instance_actions": db_instance_action
},
4479 {"vim_wim_actions": db_vim_actions
+ wim_actions
}
4482 logger
.debug("delete_instance done DB tables: %s",
4483 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
4484 mydb
.new_rows(db_tables
, ())
4485 for myvim_thread_id
in vimthread_affected
.keys():
4486 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
4488 wim_engine
.dispatch(wim_actions
)
4490 if len(error_msg
) > 0:
4491 return 'action_id={} instance {} deleted but some elements could not be deleted, or already deleted '\
4492 '(error: 404) from VIM: {}'.format(instance_action_id
, message
, error_msg
)
4494 return "action_id={} instance {} deleted".format(instance_action_id
, message
)
4496 def get_instance_id(mydb
, tenant_id
, instance_id
):
4498 #check valid tenant_id
4499 check_tenant(mydb
, tenant_id
)
4502 instance_dict
= mydb
.get_instance_scenario(instance_id
, tenant_id
, verbose
=True)
4504 # for net in instance_dict["nets"]:
4505 # if net.get("sdn_net_id"):
4506 # net_sdn = ovim.show_network(net["sdn_net_id"])
4507 # net["sdn_info"] = {
4508 # "admin_state_up": net_sdn.get("admin_state_up"),
4509 # "flows": net_sdn.get("flows"),
4510 # "last_error": net_sdn.get("last_error"),
4511 # "ports": net_sdn.get("ports"),
4512 # "type": net_sdn.get("type"),
4513 # "status": net_sdn.get("status"),
4514 # "vlan": net_sdn.get("vlan"),
4516 return instance_dict
4518 @deprecated("Instance is automatically refreshed by vim_threads")
4519 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
4520 '''Refreshes a scenario instance. It modifies instanceDict'''
4522 - 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
4525 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
4526 # #print "nfvo.refresh_instance begins"
4527 # #print json.dumps(instanceDict, indent=4)
4529 # #print "Getting the VIM URL and the VIM tenant_id"
4532 # # 1. Getting VIM vm and net list
4533 # vms_updated = [] #List of VM instance uuids in openmano that were updated
4536 # for sce_vnf in instanceDict['vnfs']:
4537 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
4538 # if datacenter_key not in vm_list:
4539 # vm_list[datacenter_key] = []
4540 # if datacenter_key not in myvims:
4541 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
4542 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
4543 # if len(vims) == 0:
4544 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
4545 # myvims[datacenter_key] = None
4547 # myvims[datacenter_key] = next(iter(vims.values()))
4548 # for vm in sce_vnf['vms']:
4549 # vm_list[datacenter_key].append(vm['vim_vm_id'])
4550 # vms_notupdated.append(vm["uuid"])
4552 # nets_updated = [] #List of VM instance uuids in openmano that were updated
4553 # nets_notupdated=[]
4555 # for net in instanceDict['nets']:
4556 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
4557 # if datacenter_key not in net_list:
4558 # net_list[datacenter_key] = []
4559 # if datacenter_key not in myvims:
4560 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
4561 # datacenter_tenant_id=net["datacenter_tenant_id"])
4562 # if len(vims) == 0:
4563 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
4564 # myvims[datacenter_key] = None
4566 # myvims[datacenter_key] = next(iter(vims.values()))
4568 # net_list[datacenter_key].append(net['vim_net_id'])
4569 # nets_notupdated.append(net["uuid"])
4571 # # 1. Getting the status of all VMs
4573 # for datacenter_key in myvims:
4574 # if not vm_list.get(datacenter_key):
4578 # if not myvims[datacenter_key]:
4579 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
4582 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
4584 # except vimconn.vimconnException as e:
4585 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
4586 # failed_message = str(e)
4588 # for vm in vm_list[datacenter_key]:
4589 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
4591 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
4592 # for sce_vnf in instanceDict['vnfs']:
4593 # for vm in sce_vnf['vms']:
4594 # vm_id = vm['vim_vm_id']
4595 # interfaces = vm_dict[vm_id].pop('interfaces', [])
4596 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
4597 # has_mgmt_iface = False
4598 # for iface in vm["interfaces"]:
4599 # if iface["type"]=="mgmt":
4600 # has_mgmt_iface = True
4601 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
4602 # vm_dict[vm_id]['status'] = "ACTIVE"
4603 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
4604 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
4605 # 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'):
4606 # vm['status'] = vm_dict[vm_id]['status']
4607 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
4608 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
4609 # # 2.1. Update in openmano DB the VMs whose status changed
4611 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
4612 # vms_notupdated.remove(vm["uuid"])
4614 # vms_updated.append(vm["uuid"])
4615 # except db_base_Exception as e:
4616 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
4617 # # 2.2. Update in openmano DB the interface VMs
4618 # for interface in interfaces:
4619 # #translate from vim_net_id to instance_net_id
4620 # network_id_list=[]
4621 # for net in instanceDict['nets']:
4622 # if net["vim_net_id"] == interface["vim_net_id"]:
4623 # network_id_list.append(net["uuid"])
4624 # if not network_id_list:
4626 # del interface["vim_net_id"]
4628 # for network_id in network_id_list:
4629 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
4630 # except db_base_Exception as e:
4631 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
4633 # # 3. Getting the status of all nets
4635 # for datacenter_key in myvims:
4636 # if not net_list.get(datacenter_key):
4639 # failed_message = ""
4640 # if not myvims[datacenter_key]:
4641 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
4644 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
4646 # except vimconn.vimconnException as e:
4647 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
4648 # failed_message = str(e)
4650 # for net in net_list[datacenter_key]:
4651 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
4653 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
4654 # # TODO: update nets inside a vnf
4655 # for net in instanceDict['nets']:
4656 # net_id = net['vim_net_id']
4657 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
4658 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
4659 # 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'):
4660 # net['status'] = net_dict[net_id]['status']
4661 # net['error_msg'] = net_dict[net_id].get('error_msg')
4662 # net['vim_info'] = net_dict[net_id].get('vim_info')
4663 # # 5.1. Update in openmano DB the nets whose status changed
4665 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
4666 # nets_notupdated.remove(net["uuid"])
4668 # nets_updated.append(net["uuid"])
4669 # except db_base_Exception as e:
4670 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
4672 # # Returns appropriate output
4673 # #print "nfvo.refresh_instance finishes"
4674 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
4675 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
4676 instance_id
= instanceDict
['uuid']
4677 # if len(vms_notupdated)+len(nets_notupdated)>0:
4678 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
4679 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
4681 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
4683 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
4684 #print "Checking that the instance_id exists and getting the instance dictionary"
4685 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
4686 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
4688 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
4689 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
4691 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), httperrors
.Not_Found
)
4692 myvim
= next(iter(vims
.values()))
4697 myvim_threads_id
= {}
4698 if action_dict
.get("vdu-scaling"):
4699 db_instance_vms
= []
4701 db_instance_interfaces
= []
4702 instance_action_id
= get_task_id()
4703 db_instance_action
= {
4704 "uuid": instance_action_id
, # same uuid for the instance and the action on create
4705 "tenant_id": nfvo_tenant
,
4706 "instance_id": instance_id
,
4707 "description": "SCALE",
4709 vm_result
["instance_action_id"] = instance_action_id
4710 vm_result
["created"] = []
4711 vm_result
["deleted"] = []
4713 for vdu
in action_dict
["vdu-scaling"]:
4714 vdu_id
= vdu
.get("vdu-id")
4715 osm_vdu_id
= vdu
.get("osm_vdu_id")
4716 member_vnf_index
= vdu
.get("member-vnf-index")
4717 vdu_count
= vdu
.get("count", 1)
4719 target_vms
= mydb
.get_rows(
4720 FROM
="instance_vms as vms join instance_vnfs as vnfs on vms.instance_vnf_id=vnfs.uuid",
4721 WHERE
={"vms.uuid": vdu_id
},
4722 ORDER_BY
="vms.created_at"
4725 raise NfvoException("Cannot find the vdu with id {}".format(vdu_id
), httperrors
.Not_Found
)
4727 if not osm_vdu_id
and not member_vnf_index
:
4728 raise NfvoException("Invalid input vdu parameters. Must supply either 'vdu-id' of 'osm_vdu_id','member-vnf-index'")
4729 target_vms
= mydb
.get_rows(
4730 # SELECT=("ivms.uuid", "ivnfs.datacenter_id", "ivnfs.datacenter_tenant_id"),
4731 FROM
="instance_vms as ivms join instance_vnfs as ivnfs on ivms.instance_vnf_id=ivnfs.uuid"\
4732 " join sce_vnfs as svnfs on ivnfs.sce_vnf_id=svnfs.uuid"\
4733 " join vms on ivms.vm_id=vms.uuid",
4734 WHERE
={"vms.osm_id": osm_vdu_id
, "svnfs.member_vnf_index": member_vnf_index
,
4735 "ivnfs.instance_scenario_id": instance_id
},
4736 ORDER_BY
="ivms.created_at"
4739 raise NfvoException("Cannot find the vdu with osm_vdu_id {} and member-vnf-index {}".format(osm_vdu_id
, member_vnf_index
), httperrors
.Not_Found
)
4740 vdu_id
= target_vms
[-1]["uuid"]
4741 target_vm
= target_vms
[-1]
4742 datacenter
= target_vm
["datacenter_id"]
4743 myvim_threads_id
[datacenter
], _
= get_vim_thread(mydb
, nfvo_tenant
, datacenter
)
4745 if vdu
["type"] == "delete":
4746 for index
in range(0, vdu_count
):
4747 target_vm
= target_vms
[-1-index
]
4748 vdu_id
= target_vm
["uuid"]
4750 vm_interfaces
= None
4751 for sce_vnf
in instanceDict
['vnfs']:
4752 for vm
in sce_vnf
['vms']:
4753 if vm
["uuid"] == vdu_id
:
4754 # TODO revise this should not be vm["uuid"] instance_vms["vm_id"]
4755 vm_interfaces
= vm
["interfaces"]
4759 "instance_action_id": instance_action_id
,
4760 "task_index": task_index
,
4761 "datacenter_vim_id": target_vm
["datacenter_tenant_id"],
4763 "status": "SCHEDULED",
4764 "item": "instance_vms",
4766 "related": target_vm
["related"],
4767 "extra": yaml
.safe_dump({"params": vm_interfaces
},
4768 default_flow_style
=True, width
=256)
4771 db_vim_actions
.append(db_vim_action
)
4772 vm_result
["deleted"].append(vdu_id
)
4773 # delete from database
4774 db_instance_vms
.append({"TO-DELETE": vdu_id
})
4776 else: # vdu["type"] == "create":
4778 where
= {"item": "instance_vms", "item_id": target_vm
["uuid"], "action": "CREATE"}
4780 vim_action_to_clone
= mydb
.get_rows(FROM
="vim_wim_actions", WHERE
=where
)
4781 if not vim_action_to_clone
:
4782 raise NfvoException("Cannot find the vim_action at database with {}".format(where
), httperrors
.Internal_Server_Error
)
4783 vim_action_to_clone
= vim_action_to_clone
[0]
4784 extra
= yaml
.safe_load(vim_action_to_clone
["extra"])
4786 # generate a new depends_on. Convert format TASK-Y into new format TASK-ACTION-XXXX.XXXX.Y
4787 # TODO do the same for flavor and image when available
4788 task_depends_on
= []
4789 task_params
= extra
["params"]
4790 task_params_networks
= deepcopy(task_params
[5])
4791 for iface
in task_params
[5]:
4792 if iface
["net_id"].startswith("TASK-"):
4793 if "." not in iface
["net_id"]:
4794 task_depends_on
.append("{}.{}".format(vim_action_to_clone
["instance_action_id"],
4795 iface
["net_id"][5:]))
4796 iface
["net_id"] = "TASK-{}.{}".format(vim_action_to_clone
["instance_action_id"],
4797 iface
["net_id"][5:])
4799 task_depends_on
.append(iface
["net_id"][5:])
4800 if "mac_address" in iface
:
4801 del iface
["mac_address"]
4803 vm_ifaces_to_clone
= mydb
.get_rows(FROM
="instance_interfaces", WHERE
={"instance_vm_id": target_vm
["uuid"]})
4804 for index
in range(0, vdu_count
):
4805 vm_uuid
= str(uuid4())
4806 vm_name
= target_vm
.get('vim_name')
4808 suffix
= vm_name
.rfind("-")
4809 vm_name
= vm_name
[:suffix
+1] + str(index
+ 1 + int(vm_name
[suffix
+1:]))
4815 'instance_vnf_id': target_vm
['instance_vnf_id'],
4816 'vm_id': target_vm
['vm_id'],
4817 'vim_name': vm_name
,
4819 db_instance_vms
.append(db_instance_vm
)
4821 for vm_iface
in vm_ifaces_to_clone
:
4822 iface_uuid
= str(uuid4())
4823 iface2iface
[vm_iface
["uuid"]] = iface_uuid
4826 'instance_vm_id': vm_uuid
,
4827 "instance_net_id": vm_iface
["instance_net_id"],
4828 'interface_id': vm_iface
['interface_id'],
4829 'type': vm_iface
['type'],
4830 'floating_ip': vm_iface
['floating_ip'],
4831 'port_security': vm_iface
['port_security']
4833 db_instance_interfaces
.append(db_vm_iface
)
4834 task_params_copy
= deepcopy(task_params
)
4835 for iface
in task_params_copy
[5]:
4836 iface
["uuid"] = iface2iface
[iface
["uuid"]]
4837 # increment ip_address
4838 if "ip_address" in iface
:
4839 ip
= iface
.get("ip_address")
4844 ip
= ip
[i
:] + str(int(ip
[:i
]) + 1)
4845 iface
["ip_address"] = ip
4847 iface
["ip_address"] = None
4849 task_params_copy
[0] = vm_name
4851 "instance_action_id": instance_action_id
,
4852 "task_index": task_index
,
4853 "datacenter_vim_id": vim_action_to_clone
["datacenter_vim_id"],
4855 "status": "SCHEDULED",
4856 "item": "instance_vms",
4861 # TODO examinar parametros, quitar MAC o incrementar. Incrementar IP y colocar las dependencias con ACTION-asdfasd.
4864 "extra": yaml
.safe_dump({"params": task_params_copy
, "depends_on": task_depends_on
}, default_flow_style
=True, width
=256)
4867 db_vim_actions
.append(db_vim_action
)
4868 vm_result
["created"].append(vm_uuid
)
4870 db_instance_action
["number_tasks"] = task_index
4872 {"instance_vms": db_instance_vms
},
4873 {"instance_interfaces": db_instance_interfaces
},
4874 {"instance_actions": db_instance_action
},
4876 # {"instance_sfis": db_instance_sfis},
4877 # {"instance_sfs": db_instance_sfs},
4878 # {"instance_classifications": db_instance_classifications},
4879 # {"instance_sfps": db_instance_sfps},
4880 {"vim_wim_actions": db_vim_actions
}
4882 logger
.debug("create_vdu done DB tables: %s",
4883 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
4884 mydb
.new_rows(db_tables
, [])
4885 for myvim_thread
in myvim_threads_id
.values():
4886 vim_threads
["running"][myvim_thread
].insert_task(db_vim_actions
)
4890 input_vnfs
= action_dict
.pop("vnfs", [])
4891 input_vms
= action_dict
.pop("vms", [])
4892 action_over_all
= True if not input_vnfs
and not input_vms
else False
4893 for sce_vnf
in instanceDict
['vnfs']:
4894 for vm
in sce_vnf
['vms']:
4895 if not action_over_all
and sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
4896 sce_vnf
['member_vnf_index'] not in input_vnfs
and \
4897 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
and \
4898 sce_vnf
['member_vnf_index'] + "-" + vm
['vdu_osm_id'] not in input_vms
: # TODO conside vm_count_index
4901 if "add_public_key" in action_dict
:
4902 if sce_vnf
.get('mgmt_access'):
4903 mgmt_access
= yaml
.load(sce_vnf
['mgmt_access'], Loader
=yaml
.Loader
)
4904 if not input_vms
and mgmt_access
.get("vdu-id") != vm
['vdu_osm_id']:
4906 default_user
= mgmt_access
.get("default-user")
4907 password
= mgmt_access
.get("password")
4908 if mgmt_access
.get(vm
['vdu_osm_id']):
4909 default_user
= mgmt_access
[vm
['vdu_osm_id']].get("default-user", default_user
)
4910 password
= mgmt_access
[vm
['vdu_osm_id']].get("password", password
)
4912 tenant
= mydb
.get_rows_by_id('nfvo_tenants', nfvo_tenant
)
4914 if 'ip_address' in vm
:
4915 mgmt_ip
= vm
['ip_address'].split(';')
4916 priv_RO_key
= decrypt_key(tenant
[0]['encrypted_RO_priv_key'], tenant
[0]['uuid'])
4917 data
= myvim
.inject_user_key(mgmt_ip
[0], action_dict
.get('user', default_user
),
4918 action_dict
['add_public_key'],
4919 password
=password
, ro_key
=priv_RO_key
)
4920 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4921 "description": "Public key injected",
4926 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4927 httperrors
.Internal_Server_Error
)
4929 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4930 httperrors
.Internal_Server_Error
)
4932 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
4933 if "console" in action_dict
:
4934 if not global_config
["http_console_proxy"]:
4935 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4936 "description": "{protocol}//{ip}:{port}/{suffix}".format(
4937 protocol
=data
["protocol"],
4938 ip
= data
["server"],
4939 port
= data
["port"],
4940 suffix
= data
["suffix"]),
4944 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
4945 vm_result
[ vm
['uuid'] ] = {"vim_result": -httperrors
.Unauthorized
,
4946 "description": "this console is only reachable by local interface",
4951 #print "console data", data
4953 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
4954 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4955 "description": "{protocol}//{ip}:{port}/{suffix}".format(
4956 protocol
=data
["protocol"],
4957 ip
= global_config
["http_console_host"],
4958 port
= console_thread
.port
,
4959 suffix
= data
["suffix"]),
4963 except NfvoException
as e
:
4964 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
4968 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
4970 except vimconn
.vimconnException
as e
:
4971 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
4974 if vm_ok
==0: #all goes wrong
4979 def instance_action_get(mydb
, nfvo_tenant
, instance_id
, action_id
):
4981 if nfvo_tenant
and nfvo_tenant
!= "any":
4982 filter["tenant_id"] = nfvo_tenant
4983 if instance_id
and instance_id
!= "any":
4984 filter["instance_id"] = instance_id
4986 filter["uuid"] = action_id
4987 rows
= mydb
.get_rows(FROM
="instance_actions", WHERE
=filter)
4990 raise NfvoException("Not found any action with this criteria", httperrors
.Not_Found
)
4991 vim_wim_actions
= mydb
.get_rows(FROM
="vim_wim_actions", WHERE
={"instance_action_id": action_id
})
4992 rows
[0]["vim_wim_actions"] = vim_wim_actions
4993 # for backward compatibility set vim_actions = vim_wim_actions
4994 rows
[0]["vim_actions"] = vim_wim_actions
4995 return {"actions": rows
}
4998 def create_or_use_console_proxy_thread(console_server
, console_port
):
4999 #look for a non-used port
5000 console_thread_key
= console_server
+ ":" + str(console_port
)
5001 if console_thread_key
in global_config
["console_thread"]:
5002 #global_config["console_thread"][console_thread_key].start_timeout()
5003 return global_config
["console_thread"][console_thread_key
]
5005 for port
in global_config
["console_port_iterator"]():
5006 #print "create_or_use_console_proxy_thread() port:", port
5007 if port
in global_config
["console_ports"]:
5010 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
5012 global_config
["console_thread"][console_thread_key
] = clithread
5013 global_config
["console_ports"][port
] = console_thread_key
5015 except cli
.ConsoleProxyExceptionPortUsed
as e
:
5016 #port used, try with onoher
5018 except cli
.ConsoleProxyException
as e
:
5019 raise NfvoException(str(e
), httperrors
.Bad_Request
)
5020 raise NfvoException("Not found any free 'http_console_ports'", httperrors
.Conflict
)
5023 def check_tenant(mydb
, tenant_id
):
5024 '''check that tenant exists at database'''
5025 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
5027 raise NfvoException("tenant '{}' not found".format(tenant_id
), httperrors
.Not_Found
)
5030 def new_tenant(mydb
, tenant_dict
):
5032 tenant_uuid
= str(uuid4())
5033 tenant_dict
['uuid'] = tenant_uuid
5035 pub_key
, priv_key
= create_RO_keypair(tenant_uuid
)
5036 tenant_dict
['RO_pub_key'] = pub_key
5037 tenant_dict
['encrypted_RO_priv_key'] = priv_key
5038 mydb
.new_row("nfvo_tenants", tenant_dict
, confidential_data
=True)
5039 except db_base_Exception
as e
:
5040 raise NfvoException("Error creating the new tenant: {} ".format(tenant_dict
['name']) + str(e
), e
.http_code
)
5043 def delete_tenant(mydb
, tenant
):
5044 #get nfvo_tenant info
5046 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
5047 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
5048 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
5051 def new_datacenter(mydb
, datacenter_descriptor
):
5052 sdn_port_mapping
= None
5053 if "config" in datacenter_descriptor
:
5054 sdn_port_mapping
= datacenter_descriptor
["config"].pop("sdn-port-mapping", None)
5055 datacenter_descriptor
["config"] = yaml
.safe_dump(datacenter_descriptor
["config"], default_flow_style
=True,
5057 # Check that datacenter-type is correct
5058 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
5059 # module_info = None
5062 plugin_name
= "rovim_" + datacenter_type
5063 if plugin_name
not in plugins
:
5064 _load_plugin(plugin_name
, type="vim")
5066 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True, confidential_data
=True)
5067 if sdn_port_mapping
:
5069 datacenter_sdn_port_mapping_set(mydb
, None, datacenter_id
, sdn_port_mapping
)
5070 except Exception as e
:
5071 mydb
.delete_row_by_id("datacenters", datacenter_id
) # Rollback
5073 return datacenter_id
5076 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
5077 # obtain data, check that only one exist
5078 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
5081 datacenter_id
= datacenter
['uuid']
5082 where
= {'uuid': datacenter
['uuid']}
5083 remove_port_mapping
= False
5084 new_sdn_port_mapping
= None
5085 if "config" in datacenter_descriptor
:
5086 if datacenter_descriptor
['config'] != None:
5088 new_config_dict
= datacenter_descriptor
["config"]
5089 if "sdn-port-mapping" in new_config_dict
:
5090 remove_port_mapping
= True
5091 new_sdn_port_mapping
= new_config_dict
.pop("sdn-port-mapping")
5092 # delete null fields
5094 for k
in new_config_dict
:
5095 if new_config_dict
[k
] is None:
5097 if k
== 'sdn-controller':
5098 remove_port_mapping
= True
5100 config_text
= datacenter
.get("config")
5103 config_dict
= yaml
.load(config_text
, Loader
=yaml
.Loader
)
5104 config_dict
.update(new_config_dict
)
5105 # delete null fields
5108 except Exception as e
:
5109 raise NfvoException("Bad format at datacenter:config " + str(e
), httperrors
.Bad_Request
)
5111 datacenter_descriptor
["config"] = yaml
.safe_dump(config_dict
, default_flow_style
=True, width
=256)
5113 datacenter_descriptor
["config"] = None
5114 if remove_port_mapping
:
5116 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_id
)
5117 except ovimException
as e
:
5118 raise NfvoException("Error deleting datacenter-port-mapping " + str(e
), httperrors
.Conflict
)
5120 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
5121 if new_sdn_port_mapping
:
5123 datacenter_sdn_port_mapping_set(mydb
, None, datacenter_id
, new_sdn_port_mapping
)
5124 except ovimException
as e
:
5126 mydb
.update_rows('datacenters', datacenter
, where
)
5127 raise NfvoException("Error adding datacenter-port-mapping " + str(e
), httperrors
.Conflict
)
5128 return datacenter_id
5131 def delete_datacenter(mydb
, datacenter
):
5132 #get nfvo_tenant info
5133 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
5134 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
5136 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_dict
['uuid'])
5137 except ovimException
as e
:
5138 raise NfvoException("Error deleting datacenter-port-mapping " + str(e
))
5139 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
5142 def create_vim_account(mydb
, nfvo_tenant
, datacenter_id
, name
=None, vim_id
=None, vim_tenant
=None, vim_tenant_name
=None,
5143 vim_username
=None, vim_password
=None, config
=None):
5144 # get datacenter info
5146 if not datacenter_id
:
5148 raise NfvoException("You must provide 'vim_id", http_code
=httperrors
.Bad_Request
)
5149 datacenter_id
= vim_id
5150 datacenter_id
, datacenter_name
= get_datacenter_uuid(mydb
, None, datacenter_id
)
5152 create_vim_tenant
= True if not vim_tenant
and not vim_tenant_name
else False
5154 # get nfvo_tenant info
5155 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
5156 if vim_tenant_name
==None:
5157 vim_tenant_name
=tenant_dict
['name']
5159 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
5160 # #check that this association does not exist before
5161 # tenants_datacenters = mydb.get_rows(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict)
5162 # if len(tenants_datacenters)>0:
5163 # raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id, tenant_dict['uuid']), httperrors.Conflict)
5165 vim_tenant_id_exist_atdb
=False
5166 if not create_vim_tenant
:
5167 where_
={"datacenter_id": datacenter_id
}
5168 if vim_tenant
!=None:
5169 where_
["vim_tenant_id"] = vim_tenant
5170 if vim_tenant_name
!=None:
5171 where_
["vim_tenant_name"] = vim_tenant_name
5172 #check if vim_tenant_id is already at database
5173 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
5174 if len(datacenter_tenants_dict
)>=1:
5175 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
5176 vim_tenant_id_exist_atdb
=True
5177 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
5179 datacenter_tenants_dict
= {}
5180 #insert at table datacenter_tenants
5181 else: #if vim_tenant==None:
5182 #create tenant at VIM if not provided
5184 _
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
, vim_user
=vim_username
,
5185 vim_passwd
=vim_password
)
5186 datacenter_name
= myvim
["name"]
5187 vim_tenant
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
5188 except vimconn
.vimconnException
as e
:
5189 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), httperrors
.Internal_Server_Error
)
5190 datacenter_tenants_dict
= {}
5191 datacenter_tenants_dict
["created"]="true"
5193 #fill datacenter_tenants table
5194 if not vim_tenant_id_exist_atdb
:
5195 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant
5196 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
5197 datacenter_tenants_dict
["user"] = vim_username
5198 datacenter_tenants_dict
["passwd"] = vim_password
5199 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
5201 datacenter_tenants_dict
["name"] = name
5203 datacenter_tenants_dict
["name"] = datacenter_name
5205 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
5206 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True, confidential_data
=True)
5207 datacenter_tenants_dict
["uuid"] = id_
5209 #fill tenants_datacenters table
5210 datacenter_tenant_id
= datacenter_tenants_dict
["uuid"]
5211 tenants_datacenter_dict
["datacenter_tenant_id"] = datacenter_tenant_id
5212 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
5215 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
5216 new_thread
= vim_thread(task_lock
, plugins
, thread_name
, None, datacenter_tenant_id
, db
=db
)
5218 thread_id
= datacenter_tenants_dict
["uuid"]
5219 vim_threads
["running"][thread_id
] = new_thread
5221 except vimconn
.vimconnException
as e
:
5222 raise NfvoException(str(e
), httperrors
.Bad_Request
)
5225 def edit_vim_account(mydb
, nfvo_tenant
, datacenter_tenant_id
, datacenter_id
=None, name
=None, vim_tenant
=None,
5226 vim_tenant_name
=None, vim_username
=None, vim_password
=None, config
=None):
5228 # get vim_account; check is valid for this tenant
5229 from_
= "datacenter_tenants as dt JOIN tenants_datacenters as td ON dt.uuid=td.datacenter_tenant_id"
5230 where_
= {"td.nfvo_tenant_id": nfvo_tenant
}
5231 if datacenter_tenant_id
:
5232 where_
["dt.uuid"] = datacenter_tenant_id
5234 where_
["dt.datacenter_id"] = datacenter_id
5235 vim_accounts
= mydb
.get_rows(SELECT
="dt.uuid as uuid, config", FROM
=from_
, WHERE
=where_
)
5236 if not vim_accounts
:
5237 raise NfvoException("vim_account not found for this tenant", http_code
=httperrors
.Not_Found
)
5238 elif len(vim_accounts
) > 1:
5239 raise NfvoException("found more than one vim_account for this tenant", http_code
=httperrors
.Conflict
)
5240 datacenter_tenant_id
= vim_accounts
[0]["uuid"]
5241 original_config
= vim_accounts
[0]["config"]
5245 original_config_dict
= yaml
.load(original_config
, Loader
=yaml
.Loader
)
5246 original_config_dict
.update(config
)
5247 update
["config"] = yaml
.safe_dump(original_config_dict
, default_flow_style
=True, width
=256)
5249 update_
['name'] = name
5251 update_
['vim_tenant_id'] = vim_tenant
5253 update_
['vim_tenant_name'] = vim_tenant_name
5255 update_
['user'] = vim_username
5257 update_
['passwd'] = vim_password
5259 mydb
.update_rows("datacenter_tenants", UPDATE
=update_
, WHERE
={"uuid": datacenter_tenant_id
})
5261 vim_threads
["running"][datacenter_tenant_id
].insert_task("reload")
5262 return datacenter_tenant_id
5264 def delete_vim_account(mydb
, tenant_id
, vim_account_id
, datacenter
=None):
5265 #get nfvo_tenant info
5266 if not tenant_id
or tenant_id
=="any":
5269 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
5270 tenant_uuid
= tenant_dict
['uuid']
5272 #check that this association exist before
5273 tenants_datacenter_dict
= {}
5275 datacenter_id
, _
= get_datacenter_uuid(mydb
, tenant_uuid
, datacenter
)
5276 tenants_datacenter_dict
["datacenter_id"] = datacenter_id
5277 elif vim_account_id
:
5278 tenants_datacenter_dict
["datacenter_tenant_id"] = vim_account_id
5280 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
5281 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
5282 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
5283 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), httperrors
.Not_Found
)
5285 #delete this association
5286 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
5288 #get vim_tenant info and deletes
5290 for tenant_datacenter_item
in tenant_datacenter_list
:
5291 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
5292 #try to delete vim:tenant
5294 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
5295 if vim_tenant_dict
['created']=='true':
5296 #delete tenant at VIM if created by NFVO
5298 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5299 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
5300 except vimconn
.vimconnException
as e
:
5301 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
5302 logger
.warn(warning
)
5303 except db_base_Exception
as e
:
5304 logger
.error("Cannot delete datacenter_tenants " + str(e
))
5305 pass # the error will be caused because dependencies, vim_tenant can not be deleted
5306 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
5307 thread
= vim_threads
["running"].get(thread_id
)
5309 thread
.insert_task("exit")
5310 vim_threads
["deleting"][thread_id
] = thread
5311 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
5314 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
5316 #get datacenter info
5317 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5319 if 'check-connectivity' in action_dict
:
5321 myvim
.check_vim_connectivity()
5322 except vimconn
.vimconnException
as e
:
5323 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
5324 raise NfvoException(str(e
), e
.http_code
)
5325 elif 'net-update' in action_dict
:
5327 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
5329 except vimconn
.vimconnException
as e
:
5330 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
5331 raise NfvoException(str(e
), httperrors
.Internal_Server_Error
)
5332 #update nets Change from VIM format to NFVO format
5335 net_nfvo
={'datacenter_id': datacenter_id
}
5336 net_nfvo
['name'] = net
['name']
5337 #net_nfvo['description']= net['name']
5338 net_nfvo
['vim_net_id'] = net
['id']
5339 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
5340 net_nfvo
['shared'] = net
['shared']
5341 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
5342 net_list
.append(net_nfvo
)
5343 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
5344 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
5346 elif 'net-edit' in action_dict
:
5347 net
= action_dict
['net-edit'].pop('net')
5348 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
5349 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
5350 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
5352 elif 'net-delete' in action_dict
:
5353 net
= action_dict
['net-deelte'].get('net')
5354 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
5355 result
= mydb
.delete_row(FROM
='datacenter_nets',
5356 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
5360 raise NfvoException("Unknown action " + str(action_dict
), httperrors
.Bad_Request
)
5363 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
5364 #get datacenter info
5365 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5367 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
5368 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
5369 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
5373 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
5374 #get datacenter info
5375 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5378 action_dict
= action_dict
["netmap"]
5379 if 'vim_id' in action_dict
:
5380 filter_dict
["id"] = action_dict
['vim_id']
5381 if 'vim_name' in action_dict
:
5382 filter_dict
["name"] = action_dict
['vim_name']
5384 filter_dict
["shared"] = True
5387 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
5388 except vimconn
.vimconnException
as e
:
5389 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
5390 raise NfvoException(str(e
), httperrors
.Internal_Server_Error
)
5391 if len(vim_nets
)>1 and action_dict
:
5392 raise NfvoException("more than two networks found, specify with vim_id", httperrors
.Conflict
)
5393 elif len(vim_nets
)==0: # and action_dict:
5394 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), httperrors
.Not_Found
)
5396 for net
in vim_nets
:
5397 net_nfvo
={'datacenter_id': datacenter_id
}
5398 if action_dict
and "name" in action_dict
:
5399 net_nfvo
['name'] = action_dict
['name']
5401 net_nfvo
['name'] = net
['name']
5402 #net_nfvo['description']= net['name']
5403 net_nfvo
['vim_net_id'] = net
['id']
5404 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
5405 net_nfvo
['shared'] = net
['shared']
5406 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
5408 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
5409 net_nfvo
["status"] = "OK"
5410 net_nfvo
["uuid"] = net_id
5411 except db_base_Exception
as e
:
5415 net_nfvo
["status"] = "FAIL: " + str(e
)
5416 net_list
.append(net_nfvo
)
5419 def get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
):
5420 # obtain all network data
5422 if utils
.check_valid_uuid(network_id
):
5423 filter_dict
= {"id": network_id
}
5425 filter_dict
= {"name": network_id
}
5427 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5428 network
= myvim
.get_network_list(filter_dict
=filter_dict
)
5429 except vimconn
.vimconnException
as e
:
5430 raise NfvoException("Not possible to get_sdn_net_id from VIM: {}".format(str(e
)), e
.http_code
)
5432 # ensure the network is defined
5433 if len(network
) == 0:
5434 raise NfvoException("Network {} is not present in the system".format(network_id
),
5435 httperrors
.Bad_Request
)
5437 # ensure there is only one network with the provided name
5438 if len(network
) > 1:
5439 raise NfvoException("Multiple networks present in vim identified by {}".format(network_id
), httperrors
.Bad_Request
)
5441 # ensure it is a dataplane network
5442 if network
[0]['type'] != 'data':
5445 # ensure we use the id
5446 network_id
= network
[0]['id']
5448 # search in dabase mano_db in table instance nets for the sdn_net_id that corresponds to the vim_net_id==network_id
5449 # and with instance_scenario_id==NULL
5450 #search_dict = {'vim_net_id': network_id, 'instance_scenario_id': None}
5451 search_dict
= {'vim_net_id': network_id
}
5454 #sdn_network_id = mydb.get_rows(SELECT=('sdn_net_id',), FROM='instance_nets', WHERE=search_dict)[0]['sdn_net_id']
5455 result
= mydb
.get_rows(SELECT
=('sdn_net_id',), FROM
='instance_nets', WHERE
=search_dict
)
5456 except db_base_Exception
as e
:
5457 raise NfvoException("db_base_Exception obtaining SDN network to associated to vim network {}".format(
5458 network_id
) + str(e
), e
.http_code
)
5462 if net
['sdn_net_id'] != None:
5464 sdn_net_id
= net
['sdn_net_id']
5466 if sdn_net_counter
== 0:
5468 elif sdn_net_counter
== 1:
5471 raise NfvoException("More than one SDN network is associated to vim network {}".format(
5472 network_id
), httperrors
.Internal_Server_Error
)
5474 def get_sdn_controller_id(mydb
, datacenter
):
5475 # Obtain sdn controller id
5476 config
= mydb
.get_rows(SELECT
=('config',), FROM
='datacenters', WHERE
={'uuid': datacenter
})[0].get('config', '{}')
5480 return yaml
.load(config
, Loader
=yaml
.Loader
).get('sdn-controller')
5482 def vim_net_sdn_attach(mydb
, tenant_id
, datacenter
, network_id
, descriptor
):
5484 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
5485 if not sdn_network_id
:
5486 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
), httperrors
.Internal_Server_Error
)
5488 #Obtain sdn controller id
5489 controller_id
= get_sdn_controller_id(mydb
, datacenter
)
5490 if not controller_id
:
5491 raise NfvoException("No SDN controller is set for datacenter {}".format(datacenter
), httperrors
.Internal_Server_Error
)
5493 #Obtain sdn controller info
5494 sdn_controller
= ovim
.show_of_controller(controller_id
)
5497 'name': 'external_port',
5498 'net_id': sdn_network_id
,
5499 'ofc_id': controller_id
,
5500 'switch_dpid': sdn_controller
['dpid'],
5501 'switch_port': descriptor
['port']
5504 if 'vlan' in descriptor
:
5505 port_data
['vlan'] = descriptor
['vlan']
5506 if 'mac' in descriptor
:
5507 port_data
['mac'] = descriptor
['mac']
5509 result
= ovim
.new_port(port_data
)
5510 except ovimException
as e
:
5511 raise NfvoException("ovimException attaching SDN network {} to vim network {}".format(
5512 sdn_network_id
, network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5513 except db_base_Exception
as e
:
5514 raise NfvoException("db_base_Exception attaching SDN network to vim network {}".format(
5515 network_id
) + str(e
), e
.http_code
)
5517 return 'Port uuid: '+ result
5519 def vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, network_id
, port_id
=None):
5521 filter = {'uuid': port_id
}
5523 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
5524 if not sdn_network_id
:
5525 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
),
5526 httperrors
.Internal_Server_Error
)
5527 #in case no port_id is specified only ports marked as 'external_port' will be detached
5528 filter = {'name': 'external_port', 'net_id': sdn_network_id
}
5531 port_list
= ovim
.get_ports(columns
={'uuid'}, filter=filter)
5532 except ovimException
as e
:
5533 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
5534 httperrors
.Internal_Server_Error
)
5536 if len(port_list
) == 0:
5537 raise NfvoException("No ports attached to the network {} were found with the requested criteria".format(network_id
),
5538 httperrors
.Bad_Request
)
5541 for port
in port_list
:
5543 port_uuid_list
.append(port
['uuid'])
5544 ovim
.delete_port(port
['uuid'])
5545 except ovimException
as e
:
5546 raise NfvoException("ovimException deleting port {} for net {}. ".format(port
['uuid'], network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5548 return 'Detached ports uuid: {}'.format(','.join(port_uuid_list
))
5550 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
5551 #get datacenter info
5552 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5555 if utils
.check_valid_uuid(name
):
5556 filter_dict
["id"] = name
5558 filter_dict
["name"] = name
5560 if item
=="networks":
5561 #filter_dict['tenant_id'] = myvim['tenant_id']
5562 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
5564 if len(content
) == 0:
5565 raise NfvoException("Network {} is not present in the system. ".format(name
),
5566 httperrors
.Bad_Request
)
5568 #Update the networks with the attached ports
5570 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, net
['id'])
5571 if sdn_network_id
!= None:
5573 #port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan'}, filter={'name': 'external_port', 'net_id': sdn_network_id})
5574 port_list
= ovim
.get_ports(columns
={'uuid', 'switch_port', 'vlan','name'}, filter={'net_id': sdn_network_id
})
5575 except ovimException
as e
:
5576 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5577 #Remove field name and if port name is external_port save it as 'type'
5578 for port
in port_list
:
5579 if port
['name'] == 'external_port':
5580 port
['type'] = "External"
5582 net
['sdn_network_id'] = sdn_network_id
5583 net
['sdn_attached_ports'] = port_list
5585 elif item
=="tenants":
5586 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
5587 elif item
== "images":
5589 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
5591 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5592 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
5593 if name
and len(content
)==1:
5594 return {item
[:-1]: content
[0]}
5595 elif name
and len(content
)==0:
5596 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.items())),
5599 return {item
: content
}
5600 except vimconn
.vimconnException
as e
:
5601 print("vim_action Not possible to get_{}_list from VIM: {} ".format(item
, str(e
)))
5602 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
5605 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
5606 #get datacenter info
5607 if tenant_id
== "any":
5610 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5612 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
5613 logger
.debug("vim_action_delete vim response: " + str(content
))
5614 items
= next(iter(content
.values()))
5615 if type(items
)==list and len(items
)==0:
5616 raise NfvoException("Not found " + item
, httperrors
.Not_Found
)
5617 elif type(items
)==list and len(items
)>1:
5618 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), httperrors
.Not_Found
)
5619 else: # it is a dict
5620 item_id
= items
["id"]
5621 item_name
= str(items
.get("name"))
5624 if item
=="networks":
5625 # If there is a SDN network associated to the vim-network, proceed to clear the relationship and delete it
5626 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, item_id
)
5627 if sdn_network_id
!= None:
5628 #Delete any port attachment to this network
5630 port_list
= ovim
.get_ports(columns
={'uuid'}, filter={'net_id': sdn_network_id
})
5631 except ovimException
as e
:
5632 raise NfvoException(
5633 "ovimException obtaining external ports for net {}. ".format(sdn_network_id
) + str(e
),
5634 httperrors
.Internal_Server_Error
)
5636 # By calling one by one all ports to be detached we ensure that not only the external_ports get detached
5637 for port
in port_list
:
5638 vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, item_id
, port
['uuid'])
5640 #Delete from 'instance_nets' the correspondence between the vim-net-id and the sdn-net-id
5642 mydb
.delete_row(FROM
='instance_nets', WHERE
={'instance_scenario_id': None,
5643 'sdn_net_id': sdn_network_id
,
5644 'vim_net_id': item_id
})
5645 except db_base_Exception
as e
:
5646 raise NfvoException("Error deleting correspondence for VIM/SDN dataplane networks{}: {}".format(
5647 item_id
, e
), e
.http_code
)
5649 #Delete the SDN network
5651 ovim
.delete_network(sdn_network_id
)
5652 except ovimException
as e
:
5653 logger
.error("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
), exc_info
=True)
5654 raise NfvoException("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
),
5655 httperrors
.Internal_Server_Error
)
5657 content
= myvim
.delete_network(item_id
)
5658 elif item
=="tenants":
5659 content
= myvim
.delete_tenant(item_id
)
5660 elif item
== "images":
5661 content
= myvim
.delete_image(item_id
)
5663 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5664 except vimconn
.vimconnException
as e
:
5665 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
5666 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
5668 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
5671 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
5672 #get datacenter info
5673 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
5674 if tenant_id
== "any":
5676 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5678 if item
=="networks":
5679 net
= descriptor
["network"]
5680 net_name
= net
.pop("name")
5681 net_type
= net
.pop("type", "bridge")
5682 net_public
= net
.pop("shared", False)
5683 net_ipprofile
= net
.pop("ip_profile", None)
5684 net_vlan
= net
.pop("vlan", None)
5685 content
, _
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
5687 #If the datacenter has a SDN controller defined and the network is of dataplane type, then create the sdn network
5688 if get_sdn_controller_id(mydb
, datacenter
) != None and (net_type
== 'data' or net_type
== 'ptp'):
5689 #obtain datacenter_tenant_id
5690 datacenter_tenant_id
= mydb
.get_rows(SELECT
=('uuid',),
5691 FROM
='datacenter_tenants',
5692 WHERE
={'datacenter_id': datacenter
})[0]['uuid']
5695 sdn_network
['vlan'] = net_vlan
5696 sdn_network
['type'] = net_type
5697 sdn_network
['name'] = net_name
5698 sdn_network
['region'] = datacenter_tenant_id
5699 ovim_content
= ovim
.new_network(sdn_network
)
5700 except ovimException
as e
:
5701 logger
.error("ovimException creating SDN network={} ".format(
5702 sdn_network
) + str(e
), exc_info
=True)
5703 raise NfvoException("ovimException creating SDN network={} ".format(sdn_network
) + str(e
),
5704 httperrors
.Internal_Server_Error
)
5706 # Save entry in in dabase mano_db in table instance_nets to stablish a dictionary vim_net_id <->sdn_net_id
5707 # use instance_scenario_id=None to distinguish from real instaces of nets
5708 correspondence
= {'instance_scenario_id': None,
5709 'sdn_net_id': ovim_content
,
5710 'vim_net_id': content
,
5711 'datacenter_tenant_id': datacenter_tenant_id
5714 mydb
.new_row('instance_nets', correspondence
, add_uuid
=True)
5715 except db_base_Exception
as e
:
5716 raise NfvoException("Error saving correspondence for VIM/SDN dataplane networks{}: {}".format(
5717 correspondence
, e
), e
.http_code
)
5718 elif item
=="tenants":
5719 tenant
= descriptor
["tenant"]
5720 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
5722 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5723 except vimconn
.vimconnException
as e
:
5724 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
5726 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
5728 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
5729 wim_id
= ovim
.new_of_controller(sdn_controller
)
5731 thread_name
= get_non_used_vim_name(sdn_controller
['name'], wim_id
, wim_id
, None)
5732 new_thread
= vim_thread(task_lock
, plugins
, thread_name
, wim_id
, None, db
=db
)
5735 vim_threads
["running"][thread_id
] = new_thread
5736 logger
.debug('New SDN controller created with uuid {}'.format(wim_id
))
5739 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
5740 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
5741 msg
= 'SDN controller {} updated'.format(data
)
5742 vim_threads
["running"][controller_id
].insert_task("reload")
5746 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
5747 if controller_id
== None:
5748 data
= ovim
.get_of_controllers()
5750 data
= ovim
.show_of_controller(controller_id
)
5752 msg
= 'SDN controller list:\n {}'.format(data
)
5756 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
5757 select_
= ('uuid', 'config')
5758 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
5759 for datacenter
in datacenters
:
5760 if datacenter
['config']:
5761 config
= yaml
.load(datacenter
['config'], Loader
=yaml
.Loader
)
5762 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
5763 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), httperrors
.Conflict
)
5765 data
= ovim
.delete_of_controller(controller_id
)
5766 msg
= 'SDN controller {} deleted'.format(data
)
5770 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
5771 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
5772 if len(controller
) < 1:
5773 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), httperrors
.Not_Found
)
5776 sdn_controller_id
= yaml
.load(controller
[0]["config"], Loader
=yaml
.Loader
)["sdn-controller"]
5778 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), httperrors
.Bad_Request
)
5780 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
5781 switch_dpid
= sdn_controller
["dpid"]
5784 for compute_node
in sdn_port_mapping
:
5785 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
5787 element
["compute_node"] = compute_node
["compute_node"]
5788 if compute_node
["ports"]:
5789 for port
in compute_node
["ports"]:
5790 pci
= port
.get("pci")
5791 element
["switch_port"] = port
.get("switch_port")
5792 element
["switch_mac"] = port
.get("switch_mac")
5793 if not element
["switch_port"] and not element
["switch_mac"]:
5794 raise NfvoException ("The mapping must contain 'switch_port' or 'switch_mac'", httperrors
.Bad_Request
)
5795 for pci_expanded
in utils
.expand_brackets(pci
):
5796 element
["pci"] = pci_expanded
5797 maps
.append(dict(element
))
5799 out
= ovim
.set_of_port_mapping(maps
, sdn_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, vim_id
=datacenter_id
)
5800 vim_threads
["running"][sdn_controller_id
].insert_task("reload")
5803 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
5804 maps
= ovim
.get_of_port_mappings(db_filter
={"datacenter_id": datacenter_id
})
5807 "sdn-controller": None,
5808 "datacenter-id": datacenter_id
,
5810 "ports_mapping": list()
5813 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
5814 if datacenter
['config']:
5815 config
= yaml
.load(datacenter
['config'], Loader
=yaml
.Loader
)
5816 if 'sdn-controller' in config
:
5817 controller_id
= config
['sdn-controller']
5818 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
5819 result
["sdn-controller"] = controller_id
5820 result
["dpid"] = sdn_controller
["dpid"]
5822 if result
["sdn-controller"] == None:
5823 raise NfvoException("SDN controller is not defined for datacenter {}".format(datacenter_id
), httperrors
.Bad_Request
)
5824 if result
["dpid"] == None:
5825 raise NfvoException("It was not possible to determine DPID for SDN controller {}".format(result
["sdn-controller"]),
5826 httperrors
.Internal_Server_Error
)
5831 ports_correspondence_dict
= dict()
5833 if result
["sdn-controller"] != link
["wim_id"]:
5834 raise NfvoException("The sdn-controller specified for different port mappings differ", httperrors
.Internal_Server_Error
)
5835 if result
["dpid"] != link
["switch_dpid"]:
5836 raise NfvoException("The dpid specified for different port mappings differ", httperrors
.Internal_Server_Error
)
5837 link_config
= link
["service_mapping_info"]
5839 element
["pci"] = link
.get("device_interface_id")
5840 if link
["switch_port"]:
5841 element
["switch_port"] = link
["switch_port"]
5842 if link_config
["switch_mac"]:
5843 element
["switch_mac"] = link_config
.get("switch_mac")
5845 if not link
.get("interface_id") in ports_correspondence_dict
:
5847 content
["compute_node"] = link
.get("interface_id")
5848 content
["ports"] = list()
5849 ports_correspondence_dict
[link
.get("interface_id")] = content
5851 ports_correspondence_dict
[link
["interface_id"]]["ports"].append(element
)
5853 for key
in sorted(ports_correspondence_dict
):
5854 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
5858 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
5859 return ovim
.clear_of_port_mapping(db_filter
={"datacenter_id":datacenter_id
})
5861 def create_RO_keypair(tenant_id
):
5863 Creates a public / private keys for a RO tenant and returns their values
5865 tenant_id: ID of the tenant
5867 public_key: Public key for the RO tenant
5868 private_key: Encrypted private key for RO tenant
5872 key
= RSA
.generate(bits
)
5874 public_key
= key
.publickey().exportKey('OpenSSH')
5875 if isinstance(public_key
, ValueError):
5876 raise NfvoException("Unable to create public key: {}".format(public_key
), httperrors
.Internal_Server_Error
)
5877 private_key
= key
.exportKey(passphrase
=tenant_id
, pkcs
=8)
5878 except (ValueError, NameError) as e
:
5879 raise NfvoException("Unable to create private key: {}".format(e
), httperrors
.Internal_Server_Error
)
5880 return public_key
, private_key
5882 def decrypt_key (key
, tenant_id
):
5884 Decrypts an encrypted RSA key
5886 key: Private key to be decrypted
5887 tenant_id: ID of the tenant
5889 unencrypted_key: Unencrypted private key for RO tenant
5892 key
= RSA
.importKey(key
,tenant_id
)
5893 unencrypted_key
= key
.exportKey('PEM')
5894 if isinstance(unencrypted_key
, ValueError):
5895 raise NfvoException("Unable to decrypt the private key: {}".format(unencrypted_key
), httperrors
.Internal_Server_Error
)
5896 except ValueError as e
:
5897 raise NfvoException("Unable to decrypt the private key: {}".format(e
), httperrors
.Internal_Server_Error
)
5898 return unencrypted_key