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") and vnfd
.get("vdu"):
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)
2437 # table sce_interfaces (vld:vnfd-connection-point-ref)
2438 for iface
in vld
.get("vnfd-connection-point-ref").values():
2439 # Check if there are VDUs in the descriptor
2440 vnf_index
= str(iface
['member-vnf-index-ref'])
2441 existing_vdus
= mydb
.get_rows(SELECT
=('vms.uuid'), FROM
="vms", WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
]})
2443 # check correct parameters
2444 if vnf_index
not in vnf_index2vnf_uuid
:
2445 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2446 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2447 "'nsd':'constituent-vnfd'".format(
2448 str(nsd
["id"]), str(vld
["id"]), str(iface
["member-vnf-index-ref"])),
2449 httperrors
.Bad_Request
)
2451 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid', 'i.type as iface_type'),
2452 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2453 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2454 'external_name': get_str(iface
, "vnfd-connection-point-ref",
2456 if not existing_ifaces
:
2457 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2458 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2459 "connection-point name at VNFD '{}'".format(
2460 str(nsd
["id"]), str(vld
["id"]), str(iface
["vnfd-connection-point-ref"]),
2461 str(iface
.get("vnfd-id-ref"))[:255]),
2462 httperrors
.Bad_Request
)
2463 interface_uuid
= existing_ifaces
[0]["uuid"]
2464 if existing_ifaces
[0]["iface_type"] == "data":
2465 db_sce_net
["type"] = "data"
2466 sce_interface_uuid
= str(uuid4())
2467 uuid_list
.append(sce_net_uuid
)
2468 iface_ip_address
= None
2469 if iface
.get("ip-address"):
2470 iface_ip_address
= str(iface
.get("ip-address"))
2471 db_sce_interface
= {
2472 "uuid": sce_interface_uuid
,
2473 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2474 "sce_net_id": sce_net_uuid
,
2475 "interface_id": interface_uuid
,
2476 "ip_address": iface_ip_address
,
2478 db_sce_interfaces
.append(db_sce_interface
)
2479 if not db_sce_net
["type"]:
2480 db_sce_net
["type"] = "bridge"
2482 # table sce_vnffgs (vnffgd)
2483 for vnffg
in nsd
.get("vnffgd").values():
2484 sce_vnffg_uuid
= str(uuid4())
2485 uuid_list
.append(sce_vnffg_uuid
)
2487 "uuid": sce_vnffg_uuid
,
2488 "name": get_str(vnffg
, "name", 255),
2489 "scenario_id": scenario_uuid
,
2490 "vendor": get_str(vnffg
, "vendor", 255),
2491 "description": get_str(vld
, "description", 255),
2493 db_sce_vnffgs
.append(db_sce_vnffg
)
2496 for rsp
in vnffg
.get("rsp").values():
2497 sce_rsp_uuid
= str(uuid4())
2498 uuid_list
.append(sce_rsp_uuid
)
2500 "uuid": sce_rsp_uuid
,
2501 "name": get_str(rsp
, "name", 255),
2502 "sce_vnffg_id": sce_vnffg_uuid
,
2503 "id": get_str(rsp
, "id", 255), # only useful to link with classifiers; will be removed later in the code
2505 db_sce_rsps
.append(db_sce_rsp
)
2506 for iface
in rsp
.get("vnfd-connection-point-ref").values():
2507 vnf_index
= str(iface
['member-vnf-index-ref'])
2508 if_order
= int(iface
['order'])
2509 # check correct parameters
2510 if vnf_index
not in vnf_index2vnf_uuid
:
2511 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2512 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2513 "'nsd':'constituent-vnfd'".format(
2514 str(nsd
["id"]), str(rsp
["id"]), str(iface
["member-vnf-index-ref"])),
2515 httperrors
.Bad_Request
)
2517 ingress_existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2518 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2520 'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2521 'external_name': get_str(iface
, "vnfd-ingress-connection-point-ref",
2523 if not ingress_existing_ifaces
:
2524 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2525 "-ref':'vnfd-ingress-connection-point-ref':'{}'. Reference to a non-existing "
2526 "connection-point name at VNFD '{}'".format(
2527 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-ingress-connection-point-ref"]),
2528 str(iface
.get("vnfd-id-ref"))[:255]), httperrors
.Bad_Request
)
2530 egress_existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2531 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2533 'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2534 'external_name': get_str(iface
, "vnfd-egress-connection-point-ref",
2536 if not egress_existing_ifaces
:
2537 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2538 "-ref':'vnfd-egress-connection-point-ref':'{}'. Reference to a non-existing "
2539 "connection-point name at VNFD '{}'".format(
2540 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-egress-connection-point-ref"]),
2541 str(iface
.get("vnfd-id-ref"))[:255]), HTTP_Bad_Request
)
2543 ingress_interface_uuid
= ingress_existing_ifaces
[0]["uuid"]
2544 egress_interface_uuid
= egress_existing_ifaces
[0]["uuid"]
2545 sce_rsp_hop_uuid
= str(uuid4())
2546 uuid_list
.append(sce_rsp_hop_uuid
)
2548 "uuid": sce_rsp_hop_uuid
,
2549 "if_order": if_order
,
2550 "ingress_interface_id": ingress_interface_uuid
,
2551 "egress_interface_id": egress_interface_uuid
,
2552 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2553 "sce_rsp_id": sce_rsp_uuid
,
2555 db_sce_rsp_hops
.append(db_sce_rsp_hop
)
2557 # deal with classifiers
2558 for classifier
in vnffg
.get("classifier").values():
2559 sce_classifier_uuid
= str(uuid4())
2560 uuid_list
.append(sce_classifier_uuid
)
2563 vnf_index
= str(classifier
['member-vnf-index-ref'])
2564 if vnf_index
not in vnf_index2vnf_uuid
:
2565 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'classifier[{}]':'vnfd-connection-point"
2566 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2567 "'nsd':'constituent-vnfd'".format(
2568 str(nsd
["id"]), str(classifier
["id"]), str(classifier
["member-vnf-index-ref"])),
2569 httperrors
.Bad_Request
)
2570 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2571 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2572 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2573 'external_name': get_str(classifier
, "vnfd-connection-point-ref",
2575 if not existing_ifaces
:
2576 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2577 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2578 "connection-point name at VNFD '{}'".format(
2579 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-connection-point-ref"]),
2580 str(iface
.get("vnfd-id-ref"))[:255]),
2581 httperrors
.Bad_Request
)
2582 interface_uuid
= existing_ifaces
[0]["uuid"]
2584 db_sce_classifier
= {
2585 "uuid": sce_classifier_uuid
,
2586 "name": get_str(classifier
, "name", 255),
2587 "sce_vnffg_id": sce_vnffg_uuid
,
2588 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2589 "interface_id": interface_uuid
,
2591 rsp_id
= get_str(classifier
, "rsp-id-ref", 255)
2592 rsp
= next((item
for item
in db_sce_rsps
if item
["id"] == rsp_id
), None)
2593 db_sce_classifier
["sce_rsp_id"] = rsp
["uuid"]
2594 db_sce_classifiers
.append(db_sce_classifier
)
2596 for match
in classifier
.get("match-attributes").values():
2597 sce_classifier_match_uuid
= str(uuid4())
2598 uuid_list
.append(sce_classifier_match_uuid
)
2599 db_sce_classifier_match
= {
2600 "uuid": sce_classifier_match_uuid
,
2601 "ip_proto": get_str(match
, "ip-proto", 2),
2602 "source_ip": get_str(match
, "source-ip-address", 16),
2603 "destination_ip": get_str(match
, "destination-ip-address", 16),
2604 "source_port": get_str(match
, "source-port", 5),
2605 "destination_port": get_str(match
, "destination-port", 5),
2606 "sce_classifier_id": sce_classifier_uuid
,
2608 db_sce_classifier_matches
.append(db_sce_classifier_match
)
2611 # remove unneeded id's in sce_rsps
2612 for rsp
in db_sce_rsps
:
2616 {"scenarios": db_scenarios
},
2617 {"sce_nets": db_sce_nets
},
2618 {"ip_profiles": db_ip_profiles
},
2619 {"sce_vnfs": db_sce_vnfs
},
2620 {"sce_interfaces": db_sce_interfaces
},
2621 {"sce_vnffgs": db_sce_vnffgs
},
2622 {"sce_rsps": db_sce_rsps
},
2623 {"sce_rsp_hops": db_sce_rsp_hops
},
2624 {"sce_classifiers": db_sce_classifiers
},
2625 {"sce_classifier_matches": db_sce_classifier_matches
},
2628 logger
.debug("new_nsd_v3 done: %s",
2629 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
2630 mydb
.new_rows(db_tables
, uuid_list
)
2631 return nsd_uuid_list
2632 except NfvoException
:
2634 except Exception as e
:
2635 logger
.error("Exception {}".format(e
))
2636 raise # NfvoException("Exception {}".format(e), httperrors.Bad_Request)
2639 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
2640 data
["uuid"] = scenario_id
2641 data
["tenant_id"] = tenant_id
2642 c
= mydb
.edit_scenario( data
)
2646 @deprecated("Use create_instance")
2647 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
2648 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2649 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
2650 vims
= {datacenter_id
: myvim
}
2651 myvim_tenant
= myvim
['tenant_id']
2652 datacenter_name
= myvim
['name']
2656 #print "Checking that the scenario_id exists and getting the scenario dictionary"
2657 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
=datacenter_id
)
2658 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
2659 scenarioDict
['datacenter_id'] = datacenter_id
2660 #print '================scenarioDict======================='
2661 #print json.dumps(scenarioDict, indent=4)
2662 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
2664 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
2665 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2667 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
2668 auxNetDict
['scenario'] = {}
2670 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
2671 for sce_net
in scenarioDict
['nets']:
2672 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
2674 myNetName
= "{}.{}".format(instance_scenario_name
, sce_net
['name'])
2675 myNetName
= myNetName
[0:255] #limit length
2676 myNetType
= sce_net
['type']
2678 myNetDict
["name"] = myNetName
2679 myNetDict
["type"] = myNetType
2680 myNetDict
["tenant_id"] = myvim_tenant
2681 myNetIPProfile
= sce_net
.get('ip_profile', None)
2682 myProviderNetwork
= sce_net
.get('provider_network', None)
2684 #We should use the dictionary as input parameter for new_network
2686 if not sce_net
["external"]:
2687 network_id
, _
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
, provider_network_profile
=myProviderNetwork
)
2688 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
2689 sce_net
['vim_id'] = network_id
2690 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
2691 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2692 sce_net
["created"] = True
2694 if sce_net
['vim_id'] == None:
2695 error_text
= "Error, datacenter '{}' does not have external network '{}'.".format(
2696 datacenter_name
, sce_net
['name'])
2697 _
, message
= rollback(mydb
, vims
, rollbackList
)
2698 logger
.error("nfvo.start_scenario: %s", error_text
)
2699 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2700 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
2701 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
2703 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
2704 #For each vnf net, we create it and we add it to instanceNetlist.
2706 for sce_vnf
in scenarioDict
['vnfs']:
2707 for net
in sce_vnf
['nets']:
2708 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
2710 myNetName
= "{}.{}".format(instance_scenario_name
,net
['name'])
2711 myNetName
= myNetName
[0:255] #limit length
2712 myNetType
= net
['type']
2714 myNetDict
["name"] = myNetName
2715 myNetDict
["type"] = myNetType
2716 myNetDict
["tenant_id"] = myvim_tenant
2717 myNetIPProfile
= net
.get('ip_profile', None)
2718 myProviderNetwork
= sce_net
.get('provider_network', None)
2721 #We should use the dictionary as input parameter for new_network
2722 network_id
, _
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
, provider_network_profile
=myProviderNetwork
)
2723 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
2724 net
['vim_id'] = network_id
2725 if sce_vnf
['uuid'] not in auxNetDict
:
2726 auxNetDict
[sce_vnf
['uuid']] = {}
2727 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
2728 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2729 net
["created"] = True
2731 #print "auxNetDict:"
2732 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2734 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
2735 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2737 for sce_vnf
in scenarioDict
['vnfs']:
2738 vnf_availability_zones
= []
2739 for vm
in sce_vnf
['vms']:
2740 vm_av
= vm
.get('availability_zone')
2741 if vm_av
and vm_av
not in vnf_availability_zones
:
2742 vnf_availability_zones
.append(vm_av
)
2744 # check if there is enough availability zones available at vim level.
2745 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
2746 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
2747 raise NfvoException('No enough availability zones at VIM for this deployment', httperrors
.Bad_Request
)
2749 for vm
in sce_vnf
['vms']:
2752 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
2753 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
2754 #myVMDict['description'] = vm['description']
2755 myVMDict
['description'] = myVMDict
['name'][0:99]
2757 myVMDict
['start'] = "no"
2758 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2759 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
2761 #create image at vim in case it not exist
2762 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2763 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
2764 vm
['vim_image_id'] = image_id
2766 #create flavor at vim in case it not exist
2767 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2768 if flavor_dict
['extended']!=None:
2769 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'], Loader
=yaml
.Loader
)
2770 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
2771 vm
['vim_flavor_id'] = flavor_id
2774 myVMDict
['imageRef'] = vm
['vim_image_id']
2775 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2776 myVMDict
['networks'] = []
2777 for iface
in vm
['interfaces']:
2779 if iface
['type']=="data":
2780 netDict
['type'] = iface
['model']
2781 elif "model" in iface
and iface
["model"]!=None:
2782 netDict
['model']=iface
['model']
2783 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2784 #discover type of interface looking at flavor
2785 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2786 for flavor_iface
in numa
.get('interfaces',[]):
2787 if flavor_iface
.get('name') == iface
['internal_name']:
2788 if flavor_iface
['dedicated'] == 'yes':
2789 netDict
['type']="PF" #passthrough
2790 elif flavor_iface
['dedicated'] == 'no':
2791 netDict
['type']="VF" #siov
2792 elif flavor_iface
['dedicated'] == 'yes:sriov':
2793 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2794 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2796 netDict
["use"]=iface
['type']
2797 if netDict
["use"]=="data" and not netDict
.get("type"):
2798 #print "netDict", netDict
2799 #print "iface", iface
2800 e_text
= "Cannot determine the interface type PF or VF of VNF '{}' VM '{}' iface '{}'".format(
2801 sce_vnf
['name'], vm
['name'], iface
['internal_name'])
2802 if flavor_dict
.get('extended')==None:
2803 raise NfvoException(e_text
+ "After database migration some information is not available. \
2804 Try to delete and create the scenarios and VNFs again", httperrors
.Conflict
)
2806 raise NfvoException(e_text
, httperrors
.Internal_Server_Error
)
2807 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2808 netDict
["type"]="virtual"
2809 if "vpci" in iface
and iface
["vpci"] is not None:
2810 netDict
['vpci'] = iface
['vpci']
2811 if "mac" in iface
and iface
["mac"] is not None:
2812 netDict
['mac_address'] = iface
['mac']
2813 if "port-security" in iface
and iface
["port-security"] is not None:
2814 netDict
['port_security'] = iface
['port-security']
2815 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2816 netDict
['floating_ip'] = iface
['floating-ip']
2817 netDict
['name'] = iface
['internal_name']
2818 if iface
['net_id'] is None:
2819 for vnf_iface
in sce_vnf
["interfaces"]:
2822 if vnf_iface
['interface_id']==iface
['uuid']:
2823 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
2826 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2827 #skip bridge ifaces not connected to any net
2828 #if 'net_id' not in netDict or netDict['net_id']==None:
2830 myVMDict
['networks'].append(netDict
)
2831 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2832 #print myVMDict['name']
2833 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2834 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2835 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2837 if 'availability_zone' in myVMDict
:
2838 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
2842 vm_id
, _
= myvim
.new_vminstance(myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2843 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2844 availability_zone_index
=av_index
,
2845 availability_zone_list
=vnf_availability_zones
)
2846 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
2847 vm
['vim_id'] = vm_id
2848 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2849 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2850 for net
in myVMDict
['networks']:
2852 for iface
in vm
['interfaces']:
2853 if net
["name"]==iface
["internal_name"]:
2854 iface
["vim_id"]=net
["vim_id"]
2857 logger
.debug("start scenario Deployment done")
2858 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2859 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
2860 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
2861 return mydb
.get_instance_scenario(instance_id
)
2863 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
2864 _
, message
= rollback(mydb
, vims
, rollbackList
)
2865 if isinstance(e
, db_base_Exception
):
2866 error_text
= "Exception at database"
2868 error_text
= "Exception at VIM"
2869 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2870 #logger.error("start_scenario %s", error_text)
2871 raise NfvoException(error_text
, e
.http_code
)
2873 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
2874 """ join the cloud config information into cloud_config_preserve.
2875 In case of conflict cloud_config_preserve preserves
2878 if not cloud_config_preserve
and not cloud_config
:
2881 new_cloud_config
= {"key-pairs":[], "users":[]}
2883 if cloud_config_preserve
:
2884 for key
in cloud_config_preserve
.get("key-pairs", () ):
2885 if key
not in new_cloud_config
["key-pairs"]:
2886 new_cloud_config
["key-pairs"].append(key
)
2888 for key
in cloud_config
.get("key-pairs", () ):
2889 if key
not in new_cloud_config
["key-pairs"]:
2890 new_cloud_config
["key-pairs"].append(key
)
2891 if not new_cloud_config
["key-pairs"]:
2892 del new_cloud_config
["key-pairs"]
2896 new_cloud_config
["users"] += cloud_config
.get("users", () )
2897 if cloud_config_preserve
:
2898 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
2899 index_to_delete
= []
2900 users
= new_cloud_config
.get("users", [])
2901 for index0
in range(0,len(users
)):
2902 if index0
in index_to_delete
:
2904 for index1
in range(index0
+1,len(users
)):
2905 if index1
in index_to_delete
:
2907 if users
[index0
]["name"] == users
[index1
]["name"]:
2908 index_to_delete
.append(index1
)
2909 for key
in users
[index1
].get("key-pairs",()):
2910 if "key-pairs" not in users
[index0
]:
2911 users
[index0
]["key-pairs"] = [key
]
2912 elif key
not in users
[index0
]["key-pairs"]:
2913 users
[index0
]["key-pairs"].append(key
)
2914 index_to_delete
.sort(reverse
=True)
2915 for index
in index_to_delete
:
2917 if not new_cloud_config
["users"]:
2918 del new_cloud_config
["users"]
2921 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
2922 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
2923 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
2924 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
2927 new_cloud_config
["user-data"] = []
2928 if cloud_config
and cloud_config
.get("user-data"):
2929 if isinstance(cloud_config
["user-data"], list):
2930 new_cloud_config
["user-data"] += cloud_config
["user-data"]
2932 new_cloud_config
["user-data"].append(cloud_config
["user-data"])
2933 if cloud_config_preserve
and cloud_config_preserve
.get("user-data"):
2934 if isinstance(cloud_config_preserve
["user-data"], list):
2935 new_cloud_config
["user-data"] += cloud_config_preserve
["user-data"]
2937 new_cloud_config
["user-data"].append(cloud_config_preserve
["user-data"])
2938 if not new_cloud_config
["user-data"]:
2939 del new_cloud_config
["user-data"]
2942 new_cloud_config
["config-files"] = []
2943 if cloud_config
and cloud_config
.get("config-files") != None:
2944 new_cloud_config
["config-files"] += cloud_config
["config-files"]
2945 if cloud_config_preserve
:
2946 for file in cloud_config_preserve
.get("config-files", ()):
2947 for index
in range(0, len(new_cloud_config
["config-files"])):
2948 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
2949 new_cloud_config
["config-files"][index
] = file
2952 new_cloud_config
["config-files"].append(file)
2953 if not new_cloud_config
["config-files"]:
2954 del new_cloud_config
["config-files"]
2955 return new_cloud_config
2958 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
2959 datacenter_id
= None
2960 datacenter_name
= None
2963 if datacenter_tenant_id
:
2964 thread_id
= datacenter_tenant_id
2965 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
2967 where_
={"td.nfvo_tenant_id": tenant_id
}
2968 if datacenter_id_name
:
2969 if utils
.check_valid_uuid(datacenter_id_name
):
2970 datacenter_id
= datacenter_id_name
2971 where_
["dt.datacenter_id"] = datacenter_id
2973 datacenter_name
= datacenter_id_name
2974 where_
["d.name"] = datacenter_name
2975 if datacenter_tenant_id
:
2976 where_
["dt.uuid"] = datacenter_tenant_id
2977 datacenters
= mydb
.get_rows(
2978 SELECT
=("dt.uuid as datacenter_tenant_id",),
2979 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
2980 "join datacenters as d on d.uuid=dt.datacenter_id",
2982 if len(datacenters
) > 1:
2983 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
2985 thread_id
= datacenters
[0]["datacenter_tenant_id"]
2986 thread
= vim_threads
["running"].get(thread_id
)
2988 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
2989 return thread_id
, thread
2990 except db_base_Exception
as e
:
2991 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
2994 def get_datacenter_uuid(mydb
, tenant_id
, datacenter_id_name
):
2996 if utils
.check_valid_uuid(datacenter_id_name
):
2997 WHERE_dict
['d.uuid'] = datacenter_id_name
2999 WHERE_dict
['d.name'] = datacenter_id_name
3002 WHERE_dict
['nfvo_tenant_id'] = tenant_id
3003 from_
= "tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join datacenter_tenants as" \
3004 " dt on td.datacenter_tenant_id=dt.uuid"
3006 from_
= 'datacenters as d'
3007 vimaccounts
= mydb
.get_rows(FROM
=from_
, SELECT
=("d.uuid as uuid, d.name as name",), WHERE
=WHERE_dict
)
3008 if len(vimaccounts
) == 0:
3009 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
3010 elif len(vimaccounts
)>1:
3011 #print "nfvo.datacenter_action() error. Several datacenters found"
3012 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
3013 return vimaccounts
[0]["uuid"], vimaccounts
[0]["name"]
3016 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
3017 datacenter_id
= None
3018 datacenter_name
= None
3019 if datacenter_id_name
:
3020 if utils
.check_valid_uuid(datacenter_id_name
):
3021 datacenter_id
= datacenter_id_name
3023 datacenter_name
= datacenter_id_name
3024 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
3026 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
3028 #print "nfvo.datacenter_action() error. Several datacenters found"
3029 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
3030 for vim_id
, vim_content
in vims
.items():
3031 return vim_id
, vim_content
3035 """Takes dict d and updates it with the values in dict u.
3036 It merges all depth levels"""
3037 for k
, v
in u
.items():
3038 if isinstance(v
, collections
.Mapping
):
3039 r
= update(d
.get(k
, {}), v
)
3046 def _get_wim(db
, wim_account_id
):
3047 # get wim from wim_account
3048 wim_accounts
= db
.get_rows(FROM
='wim_accounts', WHERE
={"uuid": wim_account_id
})
3049 if not wim_accounts
:
3050 raise NfvoException("Not found sdn id={}".format(wim_account_id
), http_code
=httperrors
.Not_Found
)
3051 return wim_accounts
[0]["wim_id"]
3054 def create_instance(mydb
, tenant_id
, instance_dict
):
3055 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
3056 # logger.debug("Creating instance...")
3058 scenario
= instance_dict
["scenario"]
3060 # find main datacenter
3062 myvim_threads_id
= {}
3063 datacenter
= instance_dict
.get("datacenter")
3064 default_wim_account
= instance_dict
.get("wim_account")
3065 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3066 myvims
[default_datacenter_id
] = vim
3067 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
3068 tenant
= mydb
.get_rows_by_id('nfvo_tenants', tenant_id
)
3069 # myvim_tenant = myvim['tenant_id']
3072 # print "Checking that the scenario exists and getting the scenario dictionary"
3073 if isinstance(scenario
, str):
3074 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, datacenter_vim_id
=myvim_threads_id
[default_datacenter_id
],
3075 datacenter_id
=default_datacenter_id
)
3077 scenarioDict
= scenario
3078 scenarioDict
["uuid"] = None
3080 # logger.debug(">>>>>> Dictionaries before merging")
3081 # logger.debug(">>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
3082 # logger.debug(">>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
3084 db_instance_vnfs
= []
3085 db_instance_vms
= []
3086 db_instance_interfaces
= []
3087 db_instance_sfis
= []
3088 db_instance_sfs
= []
3089 db_instance_classifications
= []
3090 db_instance_sfps
= []
3095 instance_name
= instance_dict
["name"]
3096 instance_uuid
= str(uuid4())
3097 uuid_list
.append(instance_uuid
)
3098 db_instance_scenario
= {
3099 "uuid": instance_uuid
,
3100 "name": instance_name
,
3101 "tenant_id": tenant_id
,
3102 "scenario_id": scenarioDict
['uuid'],
3103 "datacenter_id": default_datacenter_id
,
3104 # filled bellow 'datacenter_tenant_id'
3105 "description": instance_dict
.get("description"),
3107 if scenarioDict
.get("cloud-config"):
3108 db_instance_scenario
["cloud_config"] = yaml
.safe_dump(scenarioDict
["cloud-config"],
3109 default_flow_style
=True, width
=256)
3110 instance_action_id
= get_task_id()
3111 db_instance_action
= {
3112 "uuid": instance_action_id
, # same uuid for the instance and the action on create
3113 "tenant_id": tenant_id
,
3114 "instance_id": instance_uuid
,
3115 "description": "CREATE",
3118 # Auxiliary dictionaries from x to y
3119 sce_net2wim_instance
= {}
3120 sce_net2instance
= {}
3121 net2task_id
= {'scenario': {}}
3122 # Mapping between local networks and WIMs
3125 def ip_profile_IM2RO(ip_profile_im
):
3126 # translate from input format to database format
3128 if 'subnet-address' in ip_profile_im
:
3129 ip_profile_ro
['subnet_address'] = ip_profile_im
['subnet-address']
3130 if 'ip-version' in ip_profile_im
:
3131 ip_profile_ro
['ip_version'] = ip_profile_im
['ip-version']
3132 if 'gateway-address' in ip_profile_im
:
3133 ip_profile_ro
['gateway_address'] = ip_profile_im
['gateway-address']
3134 if 'dns-address' in ip_profile_im
:
3135 ip_profile_ro
['dns_address'] = ip_profile_im
['dns-address']
3136 if isinstance(ip_profile_ro
['dns_address'], (list, tuple)):
3137 ip_profile_ro
['dns_address'] = ";".join(ip_profile_ro
['dns_address'])
3138 if 'dhcp' in ip_profile_im
:
3139 ip_profile_ro
['dhcp_start_address'] = ip_profile_im
['dhcp'].get('start-address')
3140 ip_profile_ro
['dhcp_enabled'] = ip_profile_im
['dhcp'].get('enabled', True)
3141 ip_profile_ro
['dhcp_count'] = ip_profile_im
['dhcp'].get('count')
3142 return ip_profile_ro
3144 # logger.debug("Creating instance from scenario-dict:\n%s",
3145 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
3147 # 0 check correct parameters
3148 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).items():
3149 for scenario_net
in scenarioDict
['nets']:
3150 if net_name
== scenario_net
.get("name") or net_name
== scenario_net
.get("osm_id") or net_name
== scenario_net
.get("uuid"):
3153 raise NfvoException("Invalid scenario network name or id '{}' at instance:networks".format(net_name
),
3154 httperrors
.Bad_Request
)
3155 if "sites" not in net_instance_desc
:
3156 net_instance_desc
["sites"] = [ {} ]
3157 site_without_datacenter_field
= False
3158 for site
in net_instance_desc
["sites"]:
3159 if site
.get("datacenter"):
3160 site
["datacenter"], _
= get_datacenter_uuid(mydb
, tenant_id
, site
["datacenter"])
3161 if site
["datacenter"] not in myvims
:
3162 # Add this datacenter to myvims
3163 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
3165 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
3166 site
["datacenter"] = d
# change name to id
3168 if site_without_datacenter_field
:
3169 raise NfvoException("Found more than one entries without datacenter field at "
3170 "instance:networks:{}:sites".format(net_name
), httperrors
.Bad_Request
)
3171 site_without_datacenter_field
= True
3172 site
["datacenter"] = default_datacenter_id
# change name to id
3174 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).items():
3175 for scenario_vnf
in scenarioDict
['vnfs']:
3176 if vnf_name
== scenario_vnf
['member_vnf_index'] or vnf_name
== scenario_vnf
['uuid'] or vnf_name
== scenario_vnf
['name']:
3179 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_name
), httperrors
.Bad_Request
)
3180 if "datacenter" in vnf_instance_desc
:
3181 # Add this datacenter to myvims
3182 vnf_instance_desc
["datacenter"], _
= get_datacenter_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3183 if vnf_instance_desc
["datacenter"] not in myvims
:
3184 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3186 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3187 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
3189 for net_id
, net_instance_desc
in vnf_instance_desc
.get("networks", {}).items():
3190 for scenario_net
in scenario_vnf
['nets']:
3191 if net_id
== scenario_net
['osm_id'] or net_id
== scenario_net
['uuid'] or net_id
== scenario_net
["name"]:
3194 raise NfvoException("Invalid net id or name '{}' at instance:vnfs:networks".format(net_id
), httperrors
.Bad_Request
)
3195 if net_instance_desc
.get("vim-network-name"):
3196 scenario_net
["vim-network-name"] = net_instance_desc
["vim-network-name"]
3197 if net_instance_desc
.get("vim-network-id"):
3198 scenario_net
["vim-network-id"] = net_instance_desc
["vim-network-id"]
3199 if net_instance_desc
.get("name"):
3200 scenario_net
["name"] = net_instance_desc
["name"]
3201 if 'ip-profile' in net_instance_desc
:
3202 ipprofile_db
= ip_profile_IM2RO(net_instance_desc
['ip-profile'])
3203 if 'ip_profile' not in scenario_net
:
3204 scenario_net
['ip_profile'] = ipprofile_db
3206 update(scenario_net
['ip_profile'], ipprofile_db
)
3208 if 'provider-network' in net_instance_desc
:
3209 provider_network_db
= net_instance_desc
['provider-network']
3210 if 'provider-network' not in scenario_net
:
3211 scenario_net
['provider-network'] = provider_network_db
3213 update(scenario_net
['provider-network'], provider_network_db
)
3215 for vdu_id
, vdu_instance_desc
in vnf_instance_desc
.get("vdus", {}).items():
3216 for scenario_vm
in scenario_vnf
['vms']:
3217 if vdu_id
== scenario_vm
['osm_id'] or vdu_id
== scenario_vm
["name"]:
3220 raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id
), httperrors
.Bad_Request
)
3221 scenario_vm
["instance_parameters"] = vdu_instance_desc
3222 for iface_id
, iface_instance_desc
in vdu_instance_desc
.get("interfaces", {}).items():
3223 for scenario_interface
in scenario_vm
['interfaces']:
3224 if iface_id
== scenario_interface
['internal_name'] or iface_id
== scenario_interface
["external_name"]:
3225 scenario_interface
.update(iface_instance_desc
)
3228 raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id
), httperrors
.Bad_Request
)
3230 # 0.1 parse cloud-config parameters
3231 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
3233 # 0.2 merge instance information into scenario
3234 # Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
3235 # However, this is not possible yet.
3236 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).items():
3237 for scenario_net
in scenarioDict
['nets']:
3238 if net_name
== scenario_net
.get("name") or net_name
== scenario_net
.get("osm_id") or net_name
== scenario_net
.get("uuid"):
3239 if "wim_account" in net_instance_desc
and net_instance_desc
["wim_account"] is not None:
3240 scenario_net
["wim_account"] = net_instance_desc
["wim_account"]
3241 if 'ip-profile' in net_instance_desc
:
3242 ipprofile_db
= ip_profile_IM2RO(net_instance_desc
['ip-profile'])
3243 if 'ip_profile' not in scenario_net
:
3244 scenario_net
['ip_profile'] = ipprofile_db
3246 update(scenario_net
['ip_profile'], ipprofile_db
)
3247 if 'provider-network' in net_instance_desc
:
3248 provider_network_db
= net_instance_desc
['provider-network']
3250 if 'provider-network' not in scenario_net
:
3251 scenario_net
['provider_network'] = provider_network_db
3253 update(scenario_net
['provider-network'], provider_network_db
)
3255 for interface
in net_instance_desc
.get('interfaces', ()):
3256 if 'ip_address' in interface
:
3257 for vnf
in scenarioDict
['vnfs']:
3258 if interface
['vnf'] == vnf
['name']:
3259 for vnf_interface
in vnf
['interfaces']:
3260 if interface
['vnf_interface'] == vnf_interface
['external_name']:
3261 vnf_interface
['ip_address'] = interface
['ip_address']
3263 # logger.debug(">>>>>>>> Merged dictionary")
3264 # logger.debug("Creating instance scenario-dict MERGED:\n%s",
3265 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
3268 # 1. Creating new nets (sce_nets) in the VIM"
3269 number_mgmt_networks
= 0
3270 db_instance_nets
= []
3271 db_instance_wim_nets
= []
3272 for sce_net
in scenarioDict
['nets']:
3274 sce_net_uuid
= sce_net
.get('uuid', sce_net
["name"])
3275 # get involved datacenters where this network need to be created
3276 involved_datacenters
= []
3277 for sce_vnf
in scenarioDict
.get("vnfs", ()):
3278 vnf_datacenter
= sce_vnf
.get("datacenter", default_datacenter_id
)
3279 if vnf_datacenter
in involved_datacenters
:
3281 if sce_vnf
.get("interfaces"):
3282 for sce_vnf_ifaces
in sce_vnf
["interfaces"]:
3283 if sce_vnf_ifaces
.get("sce_net_id") == sce_net
["uuid"]:
3284 involved_datacenters
.append(vnf_datacenter
)
3286 if not involved_datacenters
:
3287 involved_datacenters
.append(default_datacenter_id
)
3288 target_wim_account
= sce_net
.get("wim_account", default_wim_account
)
3291 # TODO: use this information during network creation
3292 wim_account_id
= wim_account_name
= None
3293 if len(involved_datacenters
) > 1 and 'uuid' in sce_net
:
3294 if target_wim_account
is None or target_wim_account
is True: # automatic selection of WIM
3295 # OBS: sce_net without uuid are used internally to VNFs
3296 # and the assumption is that VNFs will not be split among
3297 # different datacenters
3298 wim_account
= wim_engine
.find_suitable_wim_account(
3299 involved_datacenters
, tenant_id
)
3300 wim_account_id
= wim_account
['uuid']
3301 wim_account_name
= wim_account
['name']
3302 wim_usage
[sce_net
['uuid']] = wim_account_id
3303 elif isinstance(target_wim_account
, str): # manual selection of WIM
3304 wim_account
.persist
.get_wim_account_by(target_wim_account
, tenant_id
)
3305 wim_account_id
= wim_account
['uuid']
3306 wim_account_name
= wim_account
['name']
3307 wim_usage
[sce_net
['uuid']] = wim_account_id
3308 else: # not WIM usage
3309 wim_usage
[sce_net
['uuid']] = False
3313 if instance_dict
.get("networks"):
3314 if sce_net
.get("uuid") in instance_dict
["networks"]:
3315 descriptor_net
= instance_dict
["networks"][sce_net
["uuid"]]
3316 descriptor_net_name
= sce_net
["uuid"]
3317 elif sce_net
.get("osm_id") in instance_dict
["networks"]:
3318 descriptor_net
= instance_dict
["networks"][sce_net
["osm_id"]]
3319 descriptor_net_name
= sce_net
["osm_id"]
3320 elif sce_net
["name"] in instance_dict
["networks"]:
3321 descriptor_net
= instance_dict
["networks"][sce_net
["name"]]
3322 descriptor_net_name
= sce_net
["name"]
3323 net_name
= descriptor_net
.get("vim-network-name")
3324 # add datacenters from instantiation parameters
3325 if descriptor_net
.get("sites"):
3326 for site
in descriptor_net
["sites"]:
3327 if site
.get("datacenter") and site
["datacenter"] not in involved_datacenters
:
3328 involved_datacenters
.append(site
["datacenter"])
3329 sce_net2instance
[sce_net_uuid
] = {}
3330 sce_net2wim_instance
[sce_net_uuid
] = {}
3331 net2task_id
['scenario'][sce_net_uuid
] = {}
3334 related_network
= None
3335 if descriptor_net
.get("use-network"):
3336 target_instance_nets
= mydb
.get_rows(
3338 FROM
="instance_nets",
3339 WHERE
={"instance_scenario_id": descriptor_net
["use-network"]["instance_scenario_id"],
3340 "osm_id": descriptor_net
["use-network"]["osm_id"]},
3342 if not target_instance_nets
:
3343 raise NfvoException(
3344 "Cannot find the target network at instance:networks[{}]:use-network".format(descriptor_net_name
),
3345 httperrors
.Bad_Request
)
3347 use_network
= target_instance_nets
[0]["related"]
3349 if sce_net
["external"]:
3350 number_mgmt_networks
+= 1
3352 for datacenter_id
in involved_datacenters
:
3354 netmap_create
= None
3355 if descriptor_net
.get("sites"):
3356 for site
in descriptor_net
["sites"]:
3357 if site
.get("datacenter") == datacenter_id
:
3358 netmap_use
= site
.get("netmap-use")
3359 netmap_create
= site
.get("netmap-create")
3362 vim
= myvims
[datacenter_id
]
3363 myvim_thread_id
= myvim_threads_id
[datacenter_id
]
3365 net_type
= sce_net
['type']
3367 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} # 'shared': True
3370 if sce_net
["external"]:
3371 net_name
= sce_net
["name"]
3373 net_name
= "{}-{}".format(instance_name
, sce_net
["name"])
3374 net_name
= net_name
[:255] # limit length
3376 if netmap_use
or netmap_create
:
3377 create_network
= False
3378 lookfor_network
= False
3380 lookfor_network
= True
3381 if utils
.check_valid_uuid(netmap_use
):
3382 lookfor_filter
["id"] = netmap_use
3384 lookfor_filter
["name"] = netmap_use
3386 create_network
= True
3387 net_vim_name
= net_name
3388 if isinstance(netmap_create
, str):
3389 net_vim_name
= netmap_create
3390 elif sce_net
.get("vim_network_name"):
3391 create_network
= False
3392 lookfor_network
= True
3393 lookfor_filter
["name"] = sce_net
.get("vim_network_name")
3394 elif sce_net
["external"]:
3395 if sce_net
.get('vim_id'):
3396 # there is a netmap at datacenter_nets database # TODO REVISE!!!!
3397 create_network
= False
3398 lookfor_network
= True
3399 lookfor_filter
["id"] = sce_net
['vim_id']
3400 elif vim
["config"].get("management_network_id") or vim
["config"].get("management_network_name"):
3401 if number_mgmt_networks
> 1:
3402 raise NfvoException("Found several VLD of type mgmt. "
3403 "You must concrete what vim-network must be use for each one",
3404 httperrors
.Bad_Request
)
3405 create_network
= False
3406 lookfor_network
= True
3407 if vim
["config"].get("management_network_id"):
3408 lookfor_filter
["id"] = vim
["config"]["management_network_id"]
3410 lookfor_filter
["name"] = vim
["config"]["management_network_name"]
3412 # There is not a netmap, look at datacenter for a net with this name and create if not found
3413 create_network
= True
3414 lookfor_network
= True
3415 lookfor_filter
["name"] = sce_net
["name"]
3416 net_vim_name
= sce_net
["name"]
3418 net_vim_name
= net_name
3419 create_network
= True
3420 lookfor_network
= False
3424 task_action
= "CREATE"
3425 task_extra
["params"] = (net_vim_name
, net_type
, sce_net
.get('ip_profile', None), False,
3426 sce_net
.get('provider_network', None), wim_account_name
)
3429 task_extra
["find"] = (lookfor_filter
,)
3430 elif lookfor_network
:
3431 task_action
= "FIND"
3432 task_extra
["params"] = (lookfor_filter
,)
3434 # fill database content
3435 net_uuid
= str(uuid4())
3436 uuid_list
.append(net_uuid
)
3437 sce_net2instance
[sce_net_uuid
][datacenter_id
] = net_uuid
3438 if not related_network
: # all db_instance_nets will have same related
3439 related_network
= use_network
or net_uuid
3441 sdn_controller
= vim
.config
.get('sdn-controller')
3442 sce_net2wim_instance
[sce_net_uuid
][datacenter_id
] = None
3443 if sdn_controller
and net_type
in ("data", "ptp"):
3444 wim_id
= _get_wim(mydb
, sdn_controller
)
3445 sdn_net_id
= str(uuid4())
3446 sce_net2wim_instance
[sce_net_uuid
][datacenter_id
] = sdn_net_id
3447 task_extra
["sdn_net_id"] = sdn_net_id
3448 db_instance_wim_nets
.append({
3450 "instance_scenario_id": instance_uuid
,
3451 "sce_net_id": sce_net
.get("uuid"),
3453 "wim_account_id": sdn_controller
,
3454 'status': 'BUILD', # if create_network else "ACTIVE"
3455 "related": related_network
,
3456 'multipoint': True if net_type
=="data" else False,
3457 "created": create_network
, # TODO py3
3460 task_wim_extra
= {"params": [net_type
, wim_account_name
]}
3462 "instance_action_id": instance_action_id
,
3463 "status": "SCHEDULED",
3464 "task_index": task_index
,
3465 # "datacenter_vim_id": myvim_thread_id,
3466 "wim_account_id": sdn_controller
,
3467 "action": task_action
,
3468 "item": "instance_wim_nets",
3469 "item_id": sdn_net_id
,
3470 "related": related_network
,
3471 "extra": yaml
.safe_dump(task_wim_extra
, default_flow_style
=True, width
=256)
3474 db_vim_actions
.append(db_vim_action
)
3477 "osm_id": sce_net
.get("osm_id") or sce_net
["name"],
3478 "related": related_network
,
3480 "vim_name": net_vim_name
,
3481 "instance_scenario_id": instance_uuid
,
3482 "sce_net_id": sce_net
.get("uuid"),
3483 "created": create_network
,
3484 'datacenter_id': datacenter_id
,
3485 'datacenter_tenant_id': myvim_thread_id
,
3486 'status': 'BUILD', # if create_network else "ACTIVE"
3487 'sdn_net_id': sdn_net_id
,
3489 db_instance_nets
.append(db_net
)
3491 "instance_action_id": instance_action_id
,
3492 "status": "SCHEDULED",
3493 "task_index": task_index
,
3494 "datacenter_vim_id": myvim_thread_id
,
3495 "action": task_action
,
3496 "item": "instance_nets",
3497 "item_id": net_uuid
,
3498 "related": related_network
,
3499 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
3501 net2task_id
['scenario'][sce_net_uuid
][datacenter_id
] = task_index
3503 db_vim_actions
.append(db_vim_action
)
3505 if 'ip_profile' in sce_net
:
3507 'instance_net_id': net_uuid
,
3508 'ip_version': sce_net
['ip_profile']['ip_version'],
3509 'subnet_address': sce_net
['ip_profile']['subnet_address'],
3510 'gateway_address': sce_net
['ip_profile']['gateway_address'],
3511 'dns_address': sce_net
['ip_profile']['dns_address'],
3512 'dhcp_enabled': sce_net
['ip_profile']['dhcp_enabled'],
3513 'dhcp_start_address': sce_net
['ip_profile']['dhcp_start_address'],
3514 'dhcp_count': sce_net
['ip_profile']['dhcp_count'],
3516 db_ip_profiles
.append(db_ip_profile
)
3520 "default_datacenter_id": default_datacenter_id
,
3521 "myvim_threads_id": myvim_threads_id
,
3522 "instance_uuid": instance_uuid
,
3523 "instance_name": instance_name
,
3524 "instance_action_id": instance_action_id
,
3526 "cloud_config": cloud_config
,
3527 "RO_pub_key": tenant
[0].get('RO_pub_key'),
3528 "instance_parameters": instance_dict
,
3531 "task_index": task_index
,
3532 "uuid_list": uuid_list
,
3533 "db_instance_nets": db_instance_nets
,
3534 "db_instance_wim_nets": db_instance_wim_nets
,
3535 "db_vim_actions": db_vim_actions
,
3536 "db_ip_profiles": db_ip_profiles
,
3537 "db_instance_vnfs": db_instance_vnfs
,
3538 "db_instance_vms": db_instance_vms
,
3539 "db_instance_interfaces": db_instance_interfaces
,
3540 "net2task_id": net2task_id
,
3541 "sce_net2instance": sce_net2instance
,
3542 "sce_net2wim_instance": sce_net2wim_instance
,
3544 # sce_vnf_list = sorted(scenarioDict['vnfs'], key=lambda k: k['name'])
3545 for sce_vnf
in scenarioDict
.get('vnfs', ()): # sce_vnf_list:
3546 instantiate_vnf(mydb
, sce_vnf
, vnf_params
, vnf_params_out
, rollbackList
)
3547 task_index
= vnf_params_out
["task_index"]
3548 uuid_list
= vnf_params_out
["uuid_list"]
3551 # task_depends_on = []
3552 for vnffg
in scenarioDict
.get('vnffgs', ()):
3553 for rsp
in vnffg
['rsps']:
3555 for cp
in rsp
['connection_points']:
3556 count
= mydb
.get_rows(
3558 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_rsp_hops as h "
3559 "on interfaces.uuid=h.ingress_interface_id",
3560 WHERE
={'h.uuid': cp
['uuid']})[0]['count']
3561 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == cp
['sce_vnf_id']), None)
3562 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3564 for instance_vm
in instance_vms
:
3565 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3567 dependencies
.append(action
['task_index'])
3568 # TODO: throw exception if count != len(instance_vms)
3569 # TODO: and action shouldn't ever be None
3571 for i
in range(count
):
3573 sfi_uuid
= str(uuid4())
3575 "ingress_interface_id": cp
["ingress_interface_id"],
3576 "egress_interface_id": cp
["egress_interface_id"]
3578 uuid_list
.append(sfi_uuid
)
3581 "related": sfi_uuid
,
3582 "instance_scenario_id": instance_uuid
,
3583 'sce_rsp_hop_id': cp
['uuid'],
3584 'datacenter_id': datacenter_id
,
3585 'datacenter_tenant_id': myvim_thread_id
,
3586 "vim_sfi_id": None, # vim thread will populate
3588 db_instance_sfis
.append(db_sfi
)
3590 "instance_action_id": instance_action_id
,
3591 "task_index": task_index
,
3592 "datacenter_vim_id": myvim_thread_id
,
3594 "status": "SCHEDULED",
3595 "item": "instance_sfis",
3596 "item_id": sfi_uuid
,
3597 "related": sfi_uuid
,
3598 "extra": yaml
.safe_dump({"params": extra_params
, "depends_on": [dependencies
[i
]]},
3599 default_flow_style
=True, width
=256)
3601 sfis_created
.append(task_index
)
3603 db_vim_actions
.append(db_vim_action
)
3605 sf_uuid
= str(uuid4())
3606 uuid_list
.append(sf_uuid
)
3610 "instance_scenario_id": instance_uuid
,
3611 'sce_rsp_hop_id': cp
['uuid'],
3612 'datacenter_id': datacenter_id
,
3613 'datacenter_tenant_id': myvim_thread_id
,
3614 "vim_sf_id": None, # vim thread will populate
3616 db_instance_sfs
.append(db_sf
)
3618 "instance_action_id": instance_action_id
,
3619 "task_index": task_index
,
3620 "datacenter_vim_id": myvim_thread_id
,
3622 "status": "SCHEDULED",
3623 "item": "instance_sfs",
3626 "extra": yaml
.safe_dump({"params": "", "depends_on": sfis_created
},
3627 default_flow_style
=True, width
=256)
3629 sfs_created
.append(task_index
)
3631 db_vim_actions
.append(db_vim_action
)
3632 classifier
= rsp
['classifier']
3634 # TODO the following ~13 lines can be reused for the sfi case
3635 count
= mydb
.get_rows(
3636 SELECT
=('vms.count'),
3637 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_classifiers as c on interfaces.uuid=c.interface_id",
3638 WHERE
={'c.uuid': classifier
['uuid']})[0]['count']
3639 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == classifier
['sce_vnf_id']), None)
3640 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3642 for instance_vm
in instance_vms
:
3643 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3645 dependencies
.append(action
['task_index'])
3646 # TODO: throw exception if count != len(instance_vms)
3647 # TODO: and action shouldn't ever be None
3648 classifications_created
= []
3649 for i
in range(count
):
3650 for match
in classifier
['matches']:
3651 # create classifications
3652 classification_uuid
= str(uuid4())
3653 uuid_list
.append(classification_uuid
)
3654 db_classification
= {
3655 "uuid": classification_uuid
,
3656 "related": classification_uuid
,
3657 "instance_scenario_id": instance_uuid
,
3658 'sce_classifier_match_id': match
['uuid'],
3659 'datacenter_id': datacenter_id
,
3660 'datacenter_tenant_id': myvim_thread_id
,
3661 "vim_classification_id": None, # vim thread will populate
3663 db_instance_classifications
.append(db_classification
)
3664 classification_params
= {
3665 "ip_proto": match
["ip_proto"],
3666 "source_ip": match
["source_ip"],
3667 "destination_ip": match
["destination_ip"],
3668 "source_port": match
["source_port"],
3669 "destination_port": match
["destination_port"]
3672 "instance_action_id": instance_action_id
,
3673 "task_index": task_index
,
3674 "datacenter_vim_id": myvim_thread_id
,
3676 "status": "SCHEDULED",
3677 "item": "instance_classifications",
3678 "item_id": classification_uuid
,
3679 "related": classification_uuid
,
3680 "extra": yaml
.safe_dump({"params": classification_params
, "depends_on": [dependencies
[i
]]},
3681 default_flow_style
=True, width
=256)
3683 classifications_created
.append(task_index
)
3685 db_vim_actions
.append(db_vim_action
)
3688 sfp_uuid
= str(uuid4())
3689 uuid_list
.append(sfp_uuid
)
3692 "related": sfp_uuid
,
3693 "instance_scenario_id": instance_uuid
,
3694 'sce_rsp_id': rsp
['uuid'],
3695 'datacenter_id': datacenter_id
,
3696 'datacenter_tenant_id': myvim_thread_id
,
3697 "vim_sfp_id": None, # vim thread will populate
3699 db_instance_sfps
.append(db_sfp
)
3701 "instance_action_id": instance_action_id
,
3702 "task_index": task_index
,
3703 "datacenter_vim_id": myvim_thread_id
,
3705 "status": "SCHEDULED",
3706 "item": "instance_sfps",
3707 "item_id": sfp_uuid
,
3708 "related": sfp_uuid
,
3709 "extra": yaml
.safe_dump({"params": "", "depends_on": sfs_created
+ classifications_created
},
3710 default_flow_style
=True, width
=256)
3713 db_vim_actions
.append(db_vim_action
)
3714 db_instance_action
["number_tasks"] = task_index
3717 logger
.debug('wim_usage:\n%s\n\n', pformat(wim_usage
))
3718 wan_links
= wim_engine
.derive_wan_links(wim_usage
, db_instance_nets
, tenant_id
)
3719 wim_actions
= wim_engine
.create_actions(wan_links
)
3720 wim_actions
, db_instance_action
= (
3721 wim_engine
.incorporate_actions(wim_actions
, db_instance_action
))
3724 scenarioDict
["datacenter2tenant"] = myvim_threads_id
3726 db_instance_scenario
['datacenter_tenant_id'] = myvim_threads_id
[default_datacenter_id
]
3727 db_instance_scenario
['datacenter_id'] = default_datacenter_id
3729 {"instance_scenarios": db_instance_scenario
},
3730 {"instance_vnfs": db_instance_vnfs
},
3731 {"instance_nets": db_instance_nets
},
3732 {"ip_profiles": db_ip_profiles
},
3733 {"instance_vms": db_instance_vms
},
3734 {"instance_interfaces": db_instance_interfaces
},
3735 {"instance_actions": db_instance_action
},
3736 {"instance_sfis": db_instance_sfis
},
3737 {"instance_sfs": db_instance_sfs
},
3738 {"instance_classifications": db_instance_classifications
},
3739 {"instance_sfps": db_instance_sfps
},
3740 {"instance_wim_nets": db_instance_wim_nets
+ wan_links
},
3741 {"vim_wim_actions": db_vim_actions
+ wim_actions
}
3744 logger
.debug("create_instance done DB tables: %s",
3745 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
3746 mydb
.new_rows(db_tables
, uuid_list
)
3747 for myvim_thread_id
in myvim_threads_id
.values():
3748 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
3750 wim_engine
.dispatch(wim_actions
)
3752 returned_instance
= mydb
.get_instance_scenario(instance_uuid
)
3753 returned_instance
["action_id"] = instance_action_id
3754 return returned_instance
3755 except (NfvoException
, vimconn
.vimconnException
, sdnconn
.SdnConnectorError
, db_base_Exception
) as e
:
3756 message
= rollback(mydb
, myvims
, rollbackList
)
3757 if isinstance(e
, db_base_Exception
):
3758 error_text
= "database Exception"
3759 elif isinstance(e
, vimconn
.vimconnException
):
3760 error_text
= "VIM Exception"
3761 elif isinstance(e
, sdnconn
.SdnConnectorError
):
3762 error_text
= "WIM Exception"
3764 error_text
= "Exception"
3765 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
3766 # logger.error("create_instance: %s", error_text)
3768 raise NfvoException(error_text
, e
.http_code
)
3771 def instantiate_vnf(mydb
, sce_vnf
, params
, params_out
, rollbackList
):
3772 default_datacenter_id
= params
["default_datacenter_id"]
3773 myvim_threads_id
= params
["myvim_threads_id"]
3774 instance_uuid
= params
["instance_uuid"]
3775 instance_name
= params
["instance_name"]
3776 instance_action_id
= params
["instance_action_id"]
3777 myvims
= params
["myvims"]
3778 cloud_config
= params
["cloud_config"]
3779 RO_pub_key
= params
["RO_pub_key"]
3781 task_index
= params_out
["task_index"]
3782 uuid_list
= params_out
["uuid_list"]
3783 db_instance_nets
= params_out
["db_instance_nets"]
3784 db_instance_wim_nets
= params_out
["db_instance_wim_nets"]
3785 db_vim_actions
= params_out
["db_vim_actions"]
3786 db_ip_profiles
= params_out
["db_ip_profiles"]
3787 db_instance_vnfs
= params_out
["db_instance_vnfs"]
3788 db_instance_vms
= params_out
["db_instance_vms"]
3789 db_instance_interfaces
= params_out
["db_instance_interfaces"]
3790 net2task_id
= params_out
["net2task_id"]
3791 sce_net2instance
= params_out
["sce_net2instance"]
3792 sce_net2wim_instance
= params_out
["sce_net2wim_instance"]
3794 vnf_net2instance
= {}
3796 # 2. Creating new nets (vnf internal nets) in the VIM"
3797 # For each vnf net, we create it and we add it to instanceNetlist.
3798 if sce_vnf
.get("datacenter"):
3799 vim
= myvims
[sce_vnf
["datacenter"]]
3800 datacenter_id
= sce_vnf
["datacenter"]
3801 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
3803 vim
= myvims
[default_datacenter_id
]
3804 datacenter_id
= default_datacenter_id
3805 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
3806 for net
in sce_vnf
['nets']:
3808 # descriptor_net = instance_dict.get("vnfs", {}).get(sce_vnf["name"], {})
3809 # net_name = descriptor_net.get("name")
3812 net_name
= "{}-{}".format(instance_name
, net
["name"])
3813 net_name
= net_name
[:255] # limit length
3814 net_type
= net
['type']
3816 if sce_vnf
['uuid'] not in vnf_net2instance
:
3817 vnf_net2instance
[sce_vnf
['uuid']] = {}
3818 if sce_vnf
['uuid'] not in net2task_id
:
3819 net2task_id
[sce_vnf
['uuid']] = {}
3821 # fill database content
3822 net_uuid
= str(uuid4())
3823 uuid_list
.append(net_uuid
)
3824 vnf_net2instance
[sce_vnf
['uuid']][net
['uuid']] = net_uuid
3826 sdn_controller
= vim
.config
.get('sdn-controller')
3828 if sdn_controller
and net_type
in ("data", "ptp"):
3829 wim_id
= _get_wim(mydb
, sdn_controller
)
3830 sdn_net_id
= str(uuid4())
3831 db_instance_wim_nets
.append({
3833 "instance_scenario_id": instance_uuid
,
3835 "wim_account_id": sdn_controller
,
3836 'status': 'BUILD', # if create_network else "ACTIVE"
3837 "related": net_uuid
,
3838 'multipoint': True if net_type
== "data" else False,
3839 "created": True, # TODO py3
3845 "related": net_uuid
,
3847 "vim_name": net_name
,
3848 "instance_scenario_id": instance_uuid
,
3849 "net_id": net
["uuid"],
3851 'datacenter_id': datacenter_id
,
3852 'datacenter_tenant_id': myvim_thread_id
,
3853 'sdn_net_id': sdn_net_id
,
3855 db_instance_nets
.append(db_net
)
3858 if net
.get("vim-network-name"):
3859 lookfor_filter
["name"] = net
["vim-network-name"]
3860 if net
.get("vim-network-id"):
3861 lookfor_filter
["id"] = net
["vim-network-id"]
3863 task_action
= "FIND"
3864 task_extra
= {"params": (lookfor_filter
,)}
3866 task_action
= "CREATE"
3867 task_extra
= {"params": (net_name
, net_type
, net
.get('ip_profile', None))}
3869 task_extra
["sdn_net_id"] = sdn_net_id
3872 task_wim_extra
= {"params": [net_type
, None]}
3874 "instance_action_id": instance_action_id
,
3875 "status": "SCHEDULED",
3876 "task_index": task_index
,
3877 # "datacenter_vim_id": myvim_thread_id,
3878 "wim_account_id": sdn_controller
,
3879 "action": task_action
,
3880 "item": "instance_wim_nets",
3881 "item_id": sdn_net_id
,
3882 "related": net_uuid
,
3883 "extra": yaml
.safe_dump(task_wim_extra
, default_flow_style
=True, width
=256)
3886 db_vim_actions
.append(db_vim_action
)
3888 "instance_action_id": instance_action_id
,
3889 "task_index": task_index
,
3890 "datacenter_vim_id": myvim_thread_id
,
3891 "status": "SCHEDULED",
3892 "action": task_action
,
3893 "item": "instance_nets",
3894 "item_id": net_uuid
,
3895 "related": net_uuid
,
3896 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
3898 net2task_id
[sce_vnf
['uuid']][net
['uuid']] = task_index
3900 db_vim_actions
.append(db_vim_action
)
3902 if 'ip_profile' in net
:
3904 'instance_net_id': net_uuid
,
3905 'ip_version': net
['ip_profile']['ip_version'],
3906 'subnet_address': net
['ip_profile']['subnet_address'],
3907 'gateway_address': net
['ip_profile']['gateway_address'],
3908 'dns_address': net
['ip_profile']['dns_address'],
3909 'dhcp_enabled': net
['ip_profile']['dhcp_enabled'],
3910 'dhcp_start_address': net
['ip_profile']['dhcp_start_address'],
3911 'dhcp_count': net
['ip_profile']['dhcp_count'],
3913 db_ip_profiles
.append(db_ip_profile
)
3915 # print "vnf_net2instance:"
3916 # print yaml.safe_dump(vnf_net2instance, indent=4, default_flow_style=False)
3918 # 3. Creating new vm instances in the VIM
3919 # myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
3921 if sce_vnf
.get('mgmt_access'):
3922 ssh_access
= sce_vnf
['mgmt_access'].get('config-access', {}).get('ssh-access')
3923 vnf_availability_zones
= []
3924 for vm
in sce_vnf
.get('vms'):
3925 vm_av
= vm
.get('availability_zone')
3926 if vm_av
and vm_av
not in vnf_availability_zones
:
3927 vnf_availability_zones
.append(vm_av
)
3929 # check if there is enough availability zones available at vim level.
3930 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
3931 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
3932 raise NfvoException('No enough availability zones at VIM for this deployment', httperrors
.Bad_Request
)
3934 if sce_vnf
.get("datacenter"):
3935 vim
= myvims
[sce_vnf
["datacenter"]]
3936 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
3937 datacenter_id
= sce_vnf
["datacenter"]
3939 vim
= myvims
[default_datacenter_id
]
3940 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
3941 datacenter_id
= default_datacenter_id
3942 sce_vnf
["datacenter_id"] = datacenter_id
3945 vnf_uuid
= str(uuid4())
3946 uuid_list
.append(vnf_uuid
)
3949 'instance_scenario_id': instance_uuid
,
3950 'vnf_id': sce_vnf
['vnf_id'],
3951 'sce_vnf_id': sce_vnf
['uuid'],
3952 'datacenter_id': datacenter_id
,
3953 'datacenter_tenant_id': myvim_thread_id
,
3955 db_instance_vnfs
.append(db_instance_vnf
)
3957 for vm
in sce_vnf
['vms']:
3959 if vm
.get("pdu_type"):
3963 sce_vnf_name
= sce_vnf
['member_vnf_index'] if sce_vnf
['member_vnf_index'] else sce_vnf
['name']
3964 myVMDict
['name'] = "{}-{}-{}".format(instance_name
[:64], sce_vnf_name
[:64], vm
["name"][:64])
3965 myVMDict
['description'] = myVMDict
['name'][0:99]
3967 # myVMDict['start'] = "no"
3968 if vm
.get("instance_parameters") and vm
["instance_parameters"].get("name"):
3969 myVMDict
['name'] = vm
["instance_parameters"].get("name")
3970 myVMDict
['name'] = myVMDict
['name'][0:255] # limit name length
3971 # create image at vim in case it not exist
3972 image_uuid
= vm
['image_id']
3973 if vm
.get("image_list"):
3974 for alternative_image
in vm
["image_list"]:
3975 if alternative_image
["vim_type"] == vim
["config"]["_vim_type_internal"]:
3976 image_uuid
= alternative_image
['image_id']
3978 image_dict
= mydb
.get_table_by_uuid_name("images", image_uuid
)
3979 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
3980 vm
['vim_image_id'] = image_id
3982 # create flavor at vim in case it not exist
3983 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
3984 if flavor_dict
['extended'] != None:
3985 flavor_dict
['extended'] = yaml
.load(flavor_dict
['extended'], Loader
=yaml
.Loader
)
3986 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
3988 # Obtain information for additional disks
3989 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',),
3990 WHERE
={'vim_id': flavor_id
})
3991 if not extended_flavor_dict
:
3992 raise NfvoException("flavor '{}' not found".format(flavor_id
), httperrors
.Not_Found
)
3994 # extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0], Loader=yaml.Loader)
3995 myVMDict
['disks'] = None
3996 extended_info
= extended_flavor_dict
[0]['extended']
3997 if extended_info
!= None:
3998 extended_flavor_dict_yaml
= yaml
.load(extended_info
, Loader
=yaml
.Loader
)
3999 if 'disks' in extended_flavor_dict_yaml
:
4000 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
4001 if vm
.get("instance_parameters") and vm
["instance_parameters"].get("devices"):
4002 for disk
in myVMDict
['disks']:
4003 if disk
.get("name") in vm
["instance_parameters"]["devices"]:
4004 disk
.update(vm
["instance_parameters"]["devices"][disk
.get("name")])
4006 vm
['vim_flavor_id'] = flavor_id
4007 myVMDict
['imageRef'] = vm
['vim_image_id']
4008 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
4009 myVMDict
['availability_zone'] = vm
.get('availability_zone')
4010 myVMDict
['networks'] = []
4011 task_depends_on
= []
4012 # TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
4013 is_management_vm
= False
4015 for iface
in vm
['interfaces']:
4017 if iface
['type'] == "data":
4018 netDict
['type'] = iface
['model']
4019 elif "model" in iface
and iface
["model"] != None:
4020 netDict
['model'] = iface
['model']
4021 # TODO in future, remove this because mac_address will not be set, and the type of PV,VF
4022 # is obtained from iterface table model
4023 # discover type of interface looking at flavor
4024 for numa
in flavor_dict
.get('extended', {}).get('numas', []):
4025 for flavor_iface
in numa
.get('interfaces', []):
4026 if flavor_iface
.get('name') == iface
['internal_name']:
4027 if flavor_iface
['dedicated'] == 'yes':
4028 netDict
['type'] = "PF" # passthrough
4029 elif flavor_iface
['dedicated'] == 'no':
4030 netDict
['type'] = "VF" # siov
4031 elif flavor_iface
['dedicated'] == 'yes:sriov':
4032 netDict
['type'] = "VFnotShared" # sriov but only one sriov on the PF
4033 netDict
["mac_address"] = flavor_iface
.get("mac_address")
4035 netDict
["use"] = iface
['type']
4036 if netDict
["use"] == "data" and not netDict
.get("type"):
4037 # print "netDict", netDict
4038 # print "iface", iface
4039 e_text
= "Cannot determine the interface type PF or VF of VNF '{}' VM '{}' iface '{}'".fromat(
4040 sce_vnf
['name'], vm
['name'], iface
['internal_name'])
4041 if flavor_dict
.get('extended') == None:
4042 raise NfvoException(e_text
+ "After database migration some information is not available. \
4043 Try to delete and create the scenarios and VNFs again", httperrors
.Conflict
)
4045 raise NfvoException(e_text
, httperrors
.Internal_Server_Error
)
4046 if netDict
["use"] == "mgmt":
4047 is_management_vm
= True
4048 netDict
["type"] = "virtual"
4049 if netDict
["use"] == "bridge":
4050 netDict
["type"] = "virtual"
4051 if iface
.get("vpci"):
4052 netDict
['vpci'] = iface
['vpci']
4053 if iface
.get("mac"):
4054 netDict
['mac_address'] = iface
['mac']
4055 if iface
.get("mac_address"):
4056 netDict
['mac_address'] = iface
['mac_address']
4057 if iface
.get("ip_address"):
4058 netDict
['ip_address'] = iface
['ip_address']
4059 if iface
.get("port-security") is not None:
4060 netDict
['port_security'] = iface
['port-security']
4061 if iface
.get("floating-ip") is not None:
4062 netDict
['floating_ip'] = iface
['floating-ip']
4063 netDict
['name'] = iface
['internal_name']
4064 if iface
['net_id'] is None:
4065 for vnf_iface
in sce_vnf
["interfaces"]:
4068 if vnf_iface
['interface_id'] == iface
['uuid']:
4069 netDict
['net_id'] = "TASK-{}".format(
4070 net2task_id
['scenario'][vnf_iface
['sce_net_id']][datacenter_id
])
4071 instance_net_id
= sce_net2instance
[vnf_iface
['sce_net_id']][datacenter_id
]
4072 instance_wim_net_id
= sce_net2wim_instance
[vnf_iface
['sce_net_id']][datacenter_id
]
4073 task_depends_on
.append(net2task_id
['scenario'][vnf_iface
['sce_net_id']][datacenter_id
])
4076 netDict
['net_id'] = "TASK-{}".format(net2task_id
[sce_vnf
['uuid']][iface
['net_id']])
4077 instance_net_id
= vnf_net2instance
[sce_vnf
['uuid']][iface
['net_id']]
4078 task_depends_on
.append(net2task_id
[sce_vnf
['uuid']][iface
['net_id']])
4079 # skip bridge ifaces not connected to any net
4080 if 'net_id' not in netDict
or netDict
['net_id'] == None:
4082 myVMDict
['networks'].append(netDict
)
4085 # 'instance_vm_id': instance_vm_uuid,
4086 "instance_net_id": instance_net_id
,
4087 "instance_wim_net_id": instance_wim_net_id
,
4088 'interface_id': iface
['uuid'],
4089 # 'vim_interface_id': ,
4090 'type': 'external' if iface
['external_name'] is not None else 'internal',
4091 'model': iface
['model'],
4092 'ip_address': iface
.get('ip_address'),
4093 'mac_address': iface
.get('mac'),
4094 'floating_ip': int(iface
.get('floating-ip', False)),
4095 'port_security': int(iface
.get('port-security', True))
4097 db_vm_ifaces
.append(db_vm_iface
)
4098 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
4099 # print myVMDict['name']
4100 # print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
4101 # print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
4102 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
4104 # We add the RO key to cloud_config if vnf will need ssh access
4105 cloud_config_vm
= cloud_config
4106 if is_management_vm
and params
["instance_parameters"].get("mgmt_keys"):
4107 cloud_config_vm
= unify_cloud_config({"key-pairs": params
["instance_parameters"]["mgmt_keys"]},
4110 if vm
.get("instance_parameters") and "mgmt_keys" in vm
["instance_parameters"]:
4111 if vm
["instance_parameters"]["mgmt_keys"]:
4112 cloud_config_vm
= unify_cloud_config({"key-pairs": vm
["instance_parameters"]["mgmt_keys"]},
4115 cloud_config_vm
= unify_cloud_config(cloud_config_vm
, {"key-pairs": [RO_pub_key
]})
4116 if vm
.get("boot_data"):
4117 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config_vm
)
4119 if myVMDict
.get('availability_zone'):
4120 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
4123 for vm_index
in range(0, vm
.get('count', 1)):
4124 vm_name
= myVMDict
['name'] + "-" + str(vm_index
+1)
4125 task_params
= (vm_name
, myVMDict
['description'], myVMDict
.get('start', None),
4126 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'], cloud_config_vm
,
4127 myVMDict
['disks'], av_index
, vnf_availability_zones
)
4128 # put interface uuid back to scenario[vnfs][vms[[interfaces]
4129 for net
in myVMDict
['networks']:
4131 for iface
in vm
['interfaces']:
4132 if net
["name"] == iface
["internal_name"]:
4133 iface
["vim_id"] = net
["vim_id"]
4135 vm_uuid
= str(uuid4())
4136 uuid_list
.append(vm_uuid
)
4140 'instance_vnf_id': vnf_uuid
,
4141 # TODO delete "vim_vm_id": vm_id,
4142 "vm_id": vm
["uuid"],
4143 "vim_name": vm_name
,
4146 db_instance_vms
.append(db_vm
)
4149 for db_vm_iface
in db_vm_ifaces
:
4150 iface_uuid
= str(uuid4())
4151 uuid_list
.append(iface_uuid
)
4152 db_vm_iface_instance
= {
4154 "instance_vm_id": vm_uuid
4156 db_vm_iface_instance
.update(db_vm_iface
)
4157 if db_vm_iface_instance
.get("ip_address"): # increment ip_address
4158 ip
= db_vm_iface_instance
.get("ip_address")
4163 ip
= ip
[i
:] + str(int(ip
[:i
]) + 1)
4164 db_vm_iface_instance
["ip_address"] = ip
4166 db_vm_iface_instance
["ip_address"] = None
4167 db_instance_interfaces
.append(db_vm_iface_instance
)
4168 myVMDict
['networks'][iface_index
]["uuid"] = iface_uuid
4172 "instance_action_id": instance_action_id
,
4173 "task_index": task_index
,
4174 "datacenter_vim_id": myvim_thread_id
,
4176 "status": "SCHEDULED",
4177 "item": "instance_vms",
4180 "extra": yaml
.safe_dump({"params": task_params
, "depends_on": task_depends_on
},
4181 default_flow_style
=True, width
=256)
4184 db_vim_actions
.append(db_vim_action
)
4185 params_out
["task_index"] = task_index
4186 params_out
["uuid_list"] = uuid_list
4189 def delete_instance(mydb
, tenant_id
, instance_id
):
4190 # print "Checking that the instance_id exists and getting the instance dictionary"
4191 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
4192 # print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
4193 tenant_id
= instanceDict
["tenant_id"]
4196 # We need to retrieve the WIM Actions now, before the instance_scenario is
4197 # deleted. The reason for that is that: ON CASCADE rules will delete the
4198 # instance_wim_nets record in the database
4199 wim_actions
= wim_engine
.delete_actions(instance_scenario_id
=instance_id
)
4202 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
4203 # 1. Delete from Database
4204 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
4206 # 2. delete from VIM
4210 vimthread_affected
= {}
4211 net2vm_dependencies
= {}
4214 instance_action_id
= get_task_id()
4216 db_instance_action
= {
4217 "uuid": instance_action_id
, # same uuid for the instance and the action on create
4218 "tenant_id": tenant_id
,
4219 "instance_id": instance_id
,
4220 "description": "DELETE",
4221 # "number_tasks": 0 # filled bellow
4224 # 2.1 deleting VNFFGs
4225 for sfp
in instanceDict
.get('sfps', ()):
4226 vimthread_affected
[sfp
["datacenter_tenant_id"]] = None
4227 datacenter_key
= (sfp
["datacenter_id"], sfp
["datacenter_tenant_id"])
4228 if datacenter_key
not in myvims
:
4230 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sfp
["datacenter_id"], sfp
["datacenter_tenant_id"])
4231 except NfvoException
as e
:
4232 logger
.error(str(e
))
4234 myvim_threads
[datacenter_key
] = myvim_thread
4235 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sfp
["datacenter_id"],
4236 datacenter_tenant_id
=sfp
["datacenter_tenant_id"])
4238 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfp
["datacenter_id"], sfp
["datacenter_tenant_id"]))
4239 myvims
[datacenter_key
] = None
4241 myvims
[datacenter_key
] = next(iter(vims
.values()))
4242 myvim
= myvims
[datacenter_key
]
4243 myvim_thread
= myvim_threads
[datacenter_key
]
4246 error_msg
+= "\n vim_sfp_id={} cannot be deleted because datacenter={} not found".format(sfp
['vim_sfp_id'], sfp
["datacenter_id"])
4248 extra
= {"params": (sfp
['vim_sfp_id'])}
4250 "instance_action_id": instance_action_id
,
4251 "task_index": task_index
,
4252 "datacenter_vim_id": sfp
["datacenter_tenant_id"],
4254 "status": "SCHEDULED",
4255 "item": "instance_sfps",
4256 "item_id": sfp
["uuid"],
4257 "related": sfp
["related"],
4258 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4261 db_vim_actions
.append(db_vim_action
)
4263 for classification
in instanceDict
['classifications']:
4264 vimthread_affected
[classification
["datacenter_tenant_id"]] = None
4265 datacenter_key
= (classification
["datacenter_id"], classification
["datacenter_tenant_id"])
4266 if datacenter_key
not in myvims
:
4268 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, classification
["datacenter_id"], classification
["datacenter_tenant_id"])
4269 except NfvoException
as e
:
4270 logger
.error(str(e
))
4272 myvim_threads
[datacenter_key
] = myvim_thread
4273 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=classification
["datacenter_id"],
4274 datacenter_tenant_id
=classification
["datacenter_tenant_id"])
4276 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(classification
["datacenter_id"],
4277 classification
["datacenter_tenant_id"]))
4278 myvims
[datacenter_key
] = None
4280 myvims
[datacenter_key
] = next(iter(vims
.values()))
4281 myvim
= myvims
[datacenter_key
]
4282 myvim_thread
= myvim_threads
[datacenter_key
]
4285 error_msg
+= "\n vim_classification_id={} cannot be deleted because datacenter={} not found".format(classification
['vim_classification_id'],
4286 classification
["datacenter_id"])
4288 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfps"]
4289 extra
= {"params": (classification
['vim_classification_id']), "depends_on": depends_on
}
4291 "instance_action_id": instance_action_id
,
4292 "task_index": task_index
,
4293 "datacenter_vim_id": classification
["datacenter_tenant_id"],
4295 "status": "SCHEDULED",
4296 "item": "instance_classifications",
4297 "item_id": classification
["uuid"],
4298 "related": classification
["related"],
4299 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4302 db_vim_actions
.append(db_vim_action
)
4304 for sf
in instanceDict
.get('sfs', ()):
4305 vimthread_affected
[sf
["datacenter_tenant_id"]] = None
4306 datacenter_key
= (sf
["datacenter_id"], sf
["datacenter_tenant_id"])
4307 if datacenter_key
not in myvims
:
4309 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sf
["datacenter_id"], sf
["datacenter_tenant_id"])
4310 except NfvoException
as e
:
4311 logger
.error(str(e
))
4313 myvim_threads
[datacenter_key
] = myvim_thread
4314 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sf
["datacenter_id"],
4315 datacenter_tenant_id
=sf
["datacenter_tenant_id"])
4317 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sf
["datacenter_id"], sf
["datacenter_tenant_id"]))
4318 myvims
[datacenter_key
] = None
4320 myvims
[datacenter_key
] = next(iter(vims
.values()))
4321 myvim
= myvims
[datacenter_key
]
4322 myvim_thread
= myvim_threads
[datacenter_key
]
4325 error_msg
+= "\n vim_sf_id={} cannot be deleted because datacenter={} not found".format(sf
['vim_sf_id'], sf
["datacenter_id"])
4327 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfps"]
4328 extra
= {"params": (sf
['vim_sf_id']), "depends_on": depends_on
}
4330 "instance_action_id": instance_action_id
,
4331 "task_index": task_index
,
4332 "datacenter_vim_id": sf
["datacenter_tenant_id"],
4334 "status": "SCHEDULED",
4335 "item": "instance_sfs",
4336 "item_id": sf
["uuid"],
4337 "related": sf
["related"],
4338 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4341 db_vim_actions
.append(db_vim_action
)
4343 for sfi
in instanceDict
.get('sfis', ()):
4344 vimthread_affected
[sfi
["datacenter_tenant_id"]] = None
4345 datacenter_key
= (sfi
["datacenter_id"], sfi
["datacenter_tenant_id"])
4346 if datacenter_key
not in myvims
:
4348 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sfi
["datacenter_id"], sfi
["datacenter_tenant_id"])
4349 except NfvoException
as e
:
4350 logger
.error(str(e
))
4352 myvim_threads
[datacenter_key
] = myvim_thread
4353 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sfi
["datacenter_id"],
4354 datacenter_tenant_id
=sfi
["datacenter_tenant_id"])
4356 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfi
["datacenter_id"], sfi
["datacenter_tenant_id"]))
4357 myvims
[datacenter_key
] = None
4359 myvims
[datacenter_key
] = next(iter(vims
.values()))
4360 myvim
= myvims
[datacenter_key
]
4361 myvim_thread
= myvim_threads
[datacenter_key
]
4364 error_msg
+= "\n vim_sfi_id={} cannot be deleted because datacenter={} not found".format(sfi
['vim_sfi_id'], sfi
["datacenter_id"])
4366 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfs"]
4367 extra
= {"params": (sfi
['vim_sfi_id']), "depends_on": depends_on
}
4369 "instance_action_id": instance_action_id
,
4370 "task_index": task_index
,
4371 "datacenter_vim_id": sfi
["datacenter_tenant_id"],
4373 "status": "SCHEDULED",
4374 "item": "instance_sfis",
4375 "item_id": sfi
["uuid"],
4376 "related": sfi
["related"],
4377 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4380 db_vim_actions
.append(db_vim_action
)
4384 for sce_vnf
in instanceDict
.get('vnfs', ()):
4385 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
4386 vimthread_affected
[sce_vnf
["datacenter_tenant_id"]] = None
4387 if datacenter_key
not in myvims
:
4389 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
4390 except NfvoException
as e
:
4391 logger
.error(str(e
))
4393 myvim_threads
[datacenter_key
] = myvim_thread
4394 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
4395 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
4397 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
4398 sce_vnf
["datacenter_tenant_id"]))
4399 myvims
[datacenter_key
] = None
4401 myvims
[datacenter_key
] = next(iter(vims
.values()))
4402 myvim
= myvims
[datacenter_key
]
4403 myvim_thread
= myvim_threads
[datacenter_key
]
4405 for vm
in sce_vnf
['vms']:
4407 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
4409 sfi_dependencies
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfis"]
4411 "instance_action_id": instance_action_id
,
4412 "task_index": task_index
,
4413 "datacenter_vim_id": sce_vnf
["datacenter_tenant_id"],
4415 "status": "SCHEDULED",
4416 "item": "instance_vms",
4417 "item_id": vm
["uuid"],
4418 "related": vm
["related"],
4419 "extra": yaml
.safe_dump({"params": vm
["interfaces"], "depends_on": sfi_dependencies
},
4420 default_flow_style
=True, width
=256)
4422 db_vim_actions
.append(db_vim_action
)
4423 for interface
in vm
["interfaces"]:
4424 if not interface
.get("instance_net_id"):
4426 if interface
["instance_net_id"] not in net2vm_dependencies
:
4427 net2vm_dependencies
[interface
["instance_net_id"]] = []
4428 net2vm_dependencies
[interface
["instance_net_id"]].append(task_index
)
4433 for net
in instanceDict
['nets']:
4434 vimthread_affected
[net
["datacenter_tenant_id"]] = None
4435 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
4436 if datacenter_key
not in myvims
:
4438 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, net
["datacenter_id"], net
["datacenter_tenant_id"])
4439 except NfvoException
as e
:
4440 logger
.error(str(e
))
4442 myvim_threads
[datacenter_key
] = myvim_thread
4443 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
4444 datacenter_tenant_id
=net
["datacenter_tenant_id"])
4446 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
4447 myvims
[datacenter_key
] = None
4449 myvims
[datacenter_key
] = next(iter(vims
.values()))
4450 myvim
= myvims
[datacenter_key
]
4451 myvim_thread
= myvim_threads
[datacenter_key
]
4454 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
4456 extra
= {"params": (net
['vim_net_id'], net
['sdn_net_id'])}
4457 if net2vm_dependencies
.get(net
["uuid"]):
4458 extra
["depends_on"] = net2vm_dependencies
[net
["uuid"]]
4459 sfi_dependencies
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfis"]
4460 if len(sfi_dependencies
) > 0:
4461 if "depends_on" in extra
:
4462 extra
["depends_on"] += sfi_dependencies
4464 extra
["depends_on"] = sfi_dependencies
4466 "instance_action_id": instance_action_id
,
4467 "task_index": task_index
,
4468 "datacenter_vim_id": net
["datacenter_tenant_id"],
4470 "status": "SCHEDULED",
4471 "item": "instance_nets",
4472 "item_id": net
["uuid"],
4473 "related": net
["related"],
4474 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4477 db_vim_actions
.append(db_vim_action
)
4478 for sdn_net
in instanceDict
['sdn_nets']:
4479 if not sdn_net
["sdn"]:
4483 "instance_action_id": instance_action_id
,
4484 "task_index": task_index
,
4485 "wim_account_id": sdn_net
["wim_account_id"],
4487 "status": "SCHEDULED",
4488 "item": "instance_wim_nets",
4489 "item_id": sdn_net
["uuid"],
4490 "related": sdn_net
["related"],
4491 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4494 db_vim_actions
.append(db_vim_action
)
4496 db_instance_action
["number_tasks"] = task_index
4499 wim_actions
, db_instance_action
= (
4500 wim_engine
.incorporate_actions(wim_actions
, db_instance_action
))
4504 {"instance_actions": db_instance_action
},
4505 {"vim_wim_actions": db_vim_actions
+ wim_actions
}
4508 logger
.debug("delete_instance done DB tables: %s",
4509 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
4510 mydb
.new_rows(db_tables
, ())
4511 for myvim_thread_id
in vimthread_affected
.keys():
4512 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
4514 wim_engine
.dispatch(wim_actions
)
4516 if len(error_msg
) > 0:
4517 return 'action_id={} instance {} deleted but some elements could not be deleted, or already deleted '\
4518 '(error: 404) from VIM: {}'.format(instance_action_id
, message
, error_msg
)
4520 return "action_id={} instance {} deleted".format(instance_action_id
, message
)
4522 def get_instance_id(mydb
, tenant_id
, instance_id
):
4524 #check valid tenant_id
4525 check_tenant(mydb
, tenant_id
)
4528 instance_dict
= mydb
.get_instance_scenario(instance_id
, tenant_id
, verbose
=True)
4530 # for net in instance_dict["nets"]:
4531 # if net.get("sdn_net_id"):
4532 # net_sdn = ovim.show_network(net["sdn_net_id"])
4533 # net["sdn_info"] = {
4534 # "admin_state_up": net_sdn.get("admin_state_up"),
4535 # "flows": net_sdn.get("flows"),
4536 # "last_error": net_sdn.get("last_error"),
4537 # "ports": net_sdn.get("ports"),
4538 # "type": net_sdn.get("type"),
4539 # "status": net_sdn.get("status"),
4540 # "vlan": net_sdn.get("vlan"),
4542 return instance_dict
4544 @deprecated("Instance is automatically refreshed by vim_threads")
4545 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
4546 '''Refreshes a scenario instance. It modifies instanceDict'''
4548 - 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
4551 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
4552 # #print "nfvo.refresh_instance begins"
4553 # #print json.dumps(instanceDict, indent=4)
4555 # #print "Getting the VIM URL and the VIM tenant_id"
4558 # # 1. Getting VIM vm and net list
4559 # vms_updated = [] #List of VM instance uuids in openmano that were updated
4562 # for sce_vnf in instanceDict['vnfs']:
4563 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
4564 # if datacenter_key not in vm_list:
4565 # vm_list[datacenter_key] = []
4566 # if datacenter_key not in myvims:
4567 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
4568 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
4569 # if len(vims) == 0:
4570 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
4571 # myvims[datacenter_key] = None
4573 # myvims[datacenter_key] = next(iter(vims.values()))
4574 # for vm in sce_vnf['vms']:
4575 # vm_list[datacenter_key].append(vm['vim_vm_id'])
4576 # vms_notupdated.append(vm["uuid"])
4578 # nets_updated = [] #List of VM instance uuids in openmano that were updated
4579 # nets_notupdated=[]
4581 # for net in instanceDict['nets']:
4582 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
4583 # if datacenter_key not in net_list:
4584 # net_list[datacenter_key] = []
4585 # if datacenter_key not in myvims:
4586 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
4587 # datacenter_tenant_id=net["datacenter_tenant_id"])
4588 # if len(vims) == 0:
4589 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
4590 # myvims[datacenter_key] = None
4592 # myvims[datacenter_key] = next(iter(vims.values()))
4594 # net_list[datacenter_key].append(net['vim_net_id'])
4595 # nets_notupdated.append(net["uuid"])
4597 # # 1. Getting the status of all VMs
4599 # for datacenter_key in myvims:
4600 # if not vm_list.get(datacenter_key):
4604 # if not myvims[datacenter_key]:
4605 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
4608 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
4610 # except vimconn.vimconnException as e:
4611 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
4612 # failed_message = str(e)
4614 # for vm in vm_list[datacenter_key]:
4615 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
4617 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
4618 # for sce_vnf in instanceDict['vnfs']:
4619 # for vm in sce_vnf['vms']:
4620 # vm_id = vm['vim_vm_id']
4621 # interfaces = vm_dict[vm_id].pop('interfaces', [])
4622 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
4623 # has_mgmt_iface = False
4624 # for iface in vm["interfaces"]:
4625 # if iface["type"]=="mgmt":
4626 # has_mgmt_iface = True
4627 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
4628 # vm_dict[vm_id]['status'] = "ACTIVE"
4629 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
4630 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
4631 # 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'):
4632 # vm['status'] = vm_dict[vm_id]['status']
4633 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
4634 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
4635 # # 2.1. Update in openmano DB the VMs whose status changed
4637 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
4638 # vms_notupdated.remove(vm["uuid"])
4640 # vms_updated.append(vm["uuid"])
4641 # except db_base_Exception as e:
4642 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
4643 # # 2.2. Update in openmano DB the interface VMs
4644 # for interface in interfaces:
4645 # #translate from vim_net_id to instance_net_id
4646 # network_id_list=[]
4647 # for net in instanceDict['nets']:
4648 # if net["vim_net_id"] == interface["vim_net_id"]:
4649 # network_id_list.append(net["uuid"])
4650 # if not network_id_list:
4652 # del interface["vim_net_id"]
4654 # for network_id in network_id_list:
4655 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
4656 # except db_base_Exception as e:
4657 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
4659 # # 3. Getting the status of all nets
4661 # for datacenter_key in myvims:
4662 # if not net_list.get(datacenter_key):
4665 # failed_message = ""
4666 # if not myvims[datacenter_key]:
4667 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
4670 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
4672 # except vimconn.vimconnException as e:
4673 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
4674 # failed_message = str(e)
4676 # for net in net_list[datacenter_key]:
4677 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
4679 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
4680 # # TODO: update nets inside a vnf
4681 # for net in instanceDict['nets']:
4682 # net_id = net['vim_net_id']
4683 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
4684 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
4685 # 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'):
4686 # net['status'] = net_dict[net_id]['status']
4687 # net['error_msg'] = net_dict[net_id].get('error_msg')
4688 # net['vim_info'] = net_dict[net_id].get('vim_info')
4689 # # 5.1. Update in openmano DB the nets whose status changed
4691 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
4692 # nets_notupdated.remove(net["uuid"])
4694 # nets_updated.append(net["uuid"])
4695 # except db_base_Exception as e:
4696 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
4698 # # Returns appropriate output
4699 # #print "nfvo.refresh_instance finishes"
4700 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
4701 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
4702 instance_id
= instanceDict
['uuid']
4703 # if len(vms_notupdated)+len(nets_notupdated)>0:
4704 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
4705 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
4707 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
4709 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
4710 #print "Checking that the instance_id exists and getting the instance dictionary"
4711 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
4712 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
4714 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
4715 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
4717 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), httperrors
.Not_Found
)
4718 myvim
= next(iter(vims
.values()))
4723 myvim_threads_id
= {}
4724 if action_dict
.get("vdu-scaling"):
4725 db_instance_vms
= []
4727 db_instance_interfaces
= []
4728 instance_action_id
= get_task_id()
4729 db_instance_action
= {
4730 "uuid": instance_action_id
, # same uuid for the instance and the action on create
4731 "tenant_id": nfvo_tenant
,
4732 "instance_id": instance_id
,
4733 "description": "SCALE",
4735 vm_result
["instance_action_id"] = instance_action_id
4736 vm_result
["created"] = []
4737 vm_result
["deleted"] = []
4739 for vdu
in action_dict
["vdu-scaling"]:
4740 vdu_id
= vdu
.get("vdu-id")
4741 osm_vdu_id
= vdu
.get("osm_vdu_id")
4742 member_vnf_index
= vdu
.get("member-vnf-index")
4743 vdu_count
= vdu
.get("count", 1)
4745 target_vms
= mydb
.get_rows(
4746 FROM
="instance_vms as vms join instance_vnfs as vnfs on vms.instance_vnf_id=vnfs.uuid",
4747 WHERE
={"vms.uuid": vdu_id
},
4748 ORDER_BY
="vms.created_at"
4751 raise NfvoException("Cannot find the vdu with id {}".format(vdu_id
), httperrors
.Not_Found
)
4753 if not osm_vdu_id
and not member_vnf_index
:
4754 raise NfvoException("Invalid input vdu parameters. Must supply either 'vdu-id' of 'osm_vdu_id','member-vnf-index'")
4755 target_vms
= mydb
.get_rows(
4756 # SELECT=("ivms.uuid", "ivnfs.datacenter_id", "ivnfs.datacenter_tenant_id"),
4757 FROM
="instance_vms as ivms join instance_vnfs as ivnfs on ivms.instance_vnf_id=ivnfs.uuid"\
4758 " join sce_vnfs as svnfs on ivnfs.sce_vnf_id=svnfs.uuid"\
4759 " join vms on ivms.vm_id=vms.uuid",
4760 WHERE
={"vms.osm_id": osm_vdu_id
, "svnfs.member_vnf_index": member_vnf_index
,
4761 "ivnfs.instance_scenario_id": instance_id
},
4762 ORDER_BY
="ivms.created_at"
4765 raise NfvoException("Cannot find the vdu with osm_vdu_id {} and member-vnf-index {}".format(osm_vdu_id
, member_vnf_index
), httperrors
.Not_Found
)
4766 vdu_id
= target_vms
[-1]["uuid"]
4767 target_vm
= target_vms
[-1]
4768 datacenter
= target_vm
["datacenter_id"]
4769 myvim_threads_id
[datacenter
], _
= get_vim_thread(mydb
, nfvo_tenant
, datacenter
)
4771 if vdu
["type"] == "delete":
4772 for index
in range(0, vdu_count
):
4773 target_vm
= target_vms
[-1-index
]
4774 vdu_id
= target_vm
["uuid"]
4776 vm_interfaces
= None
4777 for sce_vnf
in instanceDict
['vnfs']:
4778 for vm
in sce_vnf
['vms']:
4779 if vm
["uuid"] == vdu_id
:
4780 # TODO revise this should not be vm["uuid"] instance_vms["vm_id"]
4781 vm_interfaces
= vm
["interfaces"]
4785 "instance_action_id": instance_action_id
,
4786 "task_index": task_index
,
4787 "datacenter_vim_id": target_vm
["datacenter_tenant_id"],
4789 "status": "SCHEDULED",
4790 "item": "instance_vms",
4792 "related": target_vm
["related"],
4793 "extra": yaml
.safe_dump({"params": vm_interfaces
},
4794 default_flow_style
=True, width
=256)
4797 db_vim_actions
.append(db_vim_action
)
4798 vm_result
["deleted"].append(vdu_id
)
4799 # delete from database
4800 db_instance_vms
.append({"TO-DELETE": vdu_id
})
4802 else: # vdu["type"] == "create":
4804 where
= {"item": "instance_vms", "item_id": target_vm
["uuid"], "action": "CREATE"}
4806 vim_action_to_clone
= mydb
.get_rows(FROM
="vim_wim_actions", WHERE
=where
)
4807 if not vim_action_to_clone
:
4808 raise NfvoException("Cannot find the vim_action at database with {}".format(where
), httperrors
.Internal_Server_Error
)
4809 vim_action_to_clone
= vim_action_to_clone
[0]
4810 extra
= yaml
.safe_load(vim_action_to_clone
["extra"])
4812 # generate a new depends_on. Convert format TASK-Y into new format TASK-ACTION-XXXX.XXXX.Y
4813 # TODO do the same for flavor and image when available
4814 task_depends_on
= []
4815 task_params
= extra
["params"]
4816 task_params_networks
= deepcopy(task_params
[5])
4817 for iface
in task_params
[5]:
4818 if iface
["net_id"].startswith("TASK-"):
4819 if "." not in iface
["net_id"]:
4820 task_depends_on
.append("{}.{}".format(vim_action_to_clone
["instance_action_id"],
4821 iface
["net_id"][5:]))
4822 iface
["net_id"] = "TASK-{}.{}".format(vim_action_to_clone
["instance_action_id"],
4823 iface
["net_id"][5:])
4825 task_depends_on
.append(iface
["net_id"][5:])
4826 if "mac_address" in iface
:
4827 del iface
["mac_address"]
4829 vm_ifaces_to_clone
= mydb
.get_rows(FROM
="instance_interfaces", WHERE
={"instance_vm_id": target_vm
["uuid"]})
4830 for index
in range(0, vdu_count
):
4831 vm_uuid
= str(uuid4())
4832 vm_name
= target_vm
.get('vim_name')
4834 suffix
= vm_name
.rfind("-")
4835 vm_name
= vm_name
[:suffix
+1] + str(index
+ 1 + int(vm_name
[suffix
+1:]))
4841 'instance_vnf_id': target_vm
['instance_vnf_id'],
4842 'vm_id': target_vm
['vm_id'],
4843 'vim_name': vm_name
,
4845 db_instance_vms
.append(db_instance_vm
)
4847 for vm_iface
in vm_ifaces_to_clone
:
4848 iface_uuid
= str(uuid4())
4849 iface2iface
[vm_iface
["uuid"]] = iface_uuid
4852 'instance_vm_id': vm_uuid
,
4853 "instance_net_id": vm_iface
["instance_net_id"],
4854 'interface_id': vm_iface
['interface_id'],
4855 'type': vm_iface
['type'],
4856 'floating_ip': vm_iface
['floating_ip'],
4857 'port_security': vm_iface
['port_security']
4859 db_instance_interfaces
.append(db_vm_iface
)
4860 task_params_copy
= deepcopy(task_params
)
4861 for iface
in task_params_copy
[5]:
4862 iface
["uuid"] = iface2iface
[iface
["uuid"]]
4863 # increment ip_address
4864 if "ip_address" in iface
:
4865 ip
= iface
.get("ip_address")
4870 ip
= ip
[i
:] + str(int(ip
[:i
]) + 1)
4871 iface
["ip_address"] = ip
4873 iface
["ip_address"] = None
4875 task_params_copy
[0] = vm_name
4877 "instance_action_id": instance_action_id
,
4878 "task_index": task_index
,
4879 "datacenter_vim_id": vim_action_to_clone
["datacenter_vim_id"],
4881 "status": "SCHEDULED",
4882 "item": "instance_vms",
4887 # TODO examinar parametros, quitar MAC o incrementar. Incrementar IP y colocar las dependencias con ACTION-asdfasd.
4890 "extra": yaml
.safe_dump({"params": task_params_copy
, "depends_on": task_depends_on
}, default_flow_style
=True, width
=256)
4893 db_vim_actions
.append(db_vim_action
)
4894 vm_result
["created"].append(vm_uuid
)
4896 db_instance_action
["number_tasks"] = task_index
4898 {"instance_vms": db_instance_vms
},
4899 {"instance_interfaces": db_instance_interfaces
},
4900 {"instance_actions": db_instance_action
},
4902 # {"instance_sfis": db_instance_sfis},
4903 # {"instance_sfs": db_instance_sfs},
4904 # {"instance_classifications": db_instance_classifications},
4905 # {"instance_sfps": db_instance_sfps},
4906 {"vim_wim_actions": db_vim_actions
}
4908 logger
.debug("create_vdu done DB tables: %s",
4909 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
4910 mydb
.new_rows(db_tables
, [])
4911 for myvim_thread
in myvim_threads_id
.values():
4912 vim_threads
["running"][myvim_thread
].insert_task(db_vim_actions
)
4916 input_vnfs
= action_dict
.pop("vnfs", [])
4917 input_vms
= action_dict
.pop("vms", [])
4918 action_over_all
= True if not input_vnfs
and not input_vms
else False
4919 for sce_vnf
in instanceDict
['vnfs']:
4920 for vm
in sce_vnf
['vms']:
4921 if not action_over_all
and sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
4922 sce_vnf
['member_vnf_index'] not in input_vnfs
and \
4923 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
and \
4924 sce_vnf
['member_vnf_index'] + "-" + vm
['vdu_osm_id'] not in input_vms
: # TODO conside vm_count_index
4927 if "add_public_key" in action_dict
:
4928 if sce_vnf
.get('mgmt_access'):
4929 mgmt_access
= yaml
.load(sce_vnf
['mgmt_access'], Loader
=yaml
.Loader
)
4930 if not input_vms
and mgmt_access
.get("vdu-id") != vm
['vdu_osm_id']:
4932 default_user
= mgmt_access
.get("default-user")
4933 password
= mgmt_access
.get("password")
4934 if mgmt_access
.get(vm
['vdu_osm_id']):
4935 default_user
= mgmt_access
[vm
['vdu_osm_id']].get("default-user", default_user
)
4936 password
= mgmt_access
[vm
['vdu_osm_id']].get("password", password
)
4938 tenant
= mydb
.get_rows_by_id('nfvo_tenants', nfvo_tenant
)
4940 if 'ip_address' in vm
:
4941 mgmt_ip
= vm
['ip_address'].split(';')
4942 priv_RO_key
= decrypt_key(tenant
[0]['encrypted_RO_priv_key'], tenant
[0]['uuid'])
4943 data
= myvim
.inject_user_key(mgmt_ip
[0], action_dict
.get('user', default_user
),
4944 action_dict
['add_public_key'],
4945 password
=password
, ro_key
=priv_RO_key
)
4946 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4947 "description": "Public key injected",
4951 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4952 httperrors
.Internal_Server_Error
)
4954 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4955 httperrors
.Internal_Server_Error
)
4957 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
4958 if "console" in action_dict
:
4959 if not global_config
["http_console_proxy"]:
4960 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4961 "description": "{protocol}//{ip}:{port}/{suffix}".format(
4962 protocol
=data
["protocol"],
4963 ip
= data
["server"],
4964 port
= data
["port"],
4965 suffix
= data
["suffix"]),
4969 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
4970 vm_result
[ vm
['uuid'] ] = {"vim_result": -httperrors
.Unauthorized
,
4971 "description": "this console is only reachable by local interface",
4976 #print "console data", data
4978 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
4979 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4980 "description": "{protocol}//{ip}:{port}/{suffix}".format(
4981 protocol
=data
["protocol"],
4982 ip
= global_config
["http_console_host"],
4983 port
= console_thread
.port
,
4984 suffix
= data
["suffix"]),
4988 except NfvoException
as e
:
4989 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
4993 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
4995 except vimconn
.vimconnException
as e
:
4996 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
4999 if vm_ok
==0: #all goes wrong
5004 def instance_action_get(mydb
, nfvo_tenant
, instance_id
, action_id
):
5006 if nfvo_tenant
and nfvo_tenant
!= "any":
5007 filter["tenant_id"] = nfvo_tenant
5008 if instance_id
and instance_id
!= "any":
5009 filter["instance_id"] = instance_id
5011 filter["uuid"] = action_id
5012 rows
= mydb
.get_rows(FROM
="instance_actions", WHERE
=filter)
5015 raise NfvoException("Not found any action with this criteria", httperrors
.Not_Found
)
5016 vim_wim_actions
= mydb
.get_rows(FROM
="vim_wim_actions", WHERE
={"instance_action_id": action_id
})
5017 rows
[0]["vim_wim_actions"] = vim_wim_actions
5018 # for backward compatibility set vim_actions = vim_wim_actions
5019 rows
[0]["vim_actions"] = vim_wim_actions
5020 return {"actions": rows
}
5023 def create_or_use_console_proxy_thread(console_server
, console_port
):
5024 #look for a non-used port
5025 console_thread_key
= console_server
+ ":" + str(console_port
)
5026 if console_thread_key
in global_config
["console_thread"]:
5027 #global_config["console_thread"][console_thread_key].start_timeout()
5028 return global_config
["console_thread"][console_thread_key
]
5030 for port
in global_config
["console_port_iterator"]():
5031 #print "create_or_use_console_proxy_thread() port:", port
5032 if port
in global_config
["console_ports"]:
5035 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
5037 global_config
["console_thread"][console_thread_key
] = clithread
5038 global_config
["console_ports"][port
] = console_thread_key
5040 except cli
.ConsoleProxyExceptionPortUsed
as e
:
5041 #port used, try with onoher
5043 except cli
.ConsoleProxyException
as e
:
5044 raise NfvoException(str(e
), httperrors
.Bad_Request
)
5045 raise NfvoException("Not found any free 'http_console_ports'", httperrors
.Conflict
)
5048 def check_tenant(mydb
, tenant_id
):
5049 '''check that tenant exists at database'''
5050 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
5052 raise NfvoException("tenant '{}' not found".format(tenant_id
), httperrors
.Not_Found
)
5055 def new_tenant(mydb
, tenant_dict
):
5057 tenant_uuid
= str(uuid4())
5058 tenant_dict
['uuid'] = tenant_uuid
5060 pub_key
, priv_key
= create_RO_keypair(tenant_uuid
)
5061 tenant_dict
['RO_pub_key'] = pub_key
5062 tenant_dict
['encrypted_RO_priv_key'] = priv_key
5063 mydb
.new_row("nfvo_tenants", tenant_dict
, confidential_data
=True)
5064 except db_base_Exception
as e
:
5065 raise NfvoException("Error creating the new tenant: {} ".format(tenant_dict
['name']) + str(e
), e
.http_code
)
5068 def delete_tenant(mydb
, tenant
):
5069 #get nfvo_tenant info
5071 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
5072 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
5073 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
5076 def new_datacenter(mydb
, datacenter_descriptor
):
5077 sdn_port_mapping
= None
5078 if "config" in datacenter_descriptor
:
5079 sdn_port_mapping
= datacenter_descriptor
["config"].pop("sdn-port-mapping", None)
5080 datacenter_descriptor
["config"] = yaml
.safe_dump(datacenter_descriptor
["config"], default_flow_style
=True,
5082 # Check that datacenter-type is correct
5083 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
5084 # module_info = None
5087 plugin_name
= "rovim_" + datacenter_type
5088 if plugin_name
not in plugins
:
5089 _load_plugin(plugin_name
, type="vim")
5091 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True, confidential_data
=True)
5092 if sdn_port_mapping
:
5094 datacenter_sdn_port_mapping_set(mydb
, None, datacenter_id
, sdn_port_mapping
)
5095 except Exception as e
:
5096 mydb
.delete_row_by_id("datacenters", datacenter_id
) # Rollback
5098 return datacenter_id
5101 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
5102 # obtain data, check that only one exist
5103 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
5106 datacenter_id
= datacenter
['uuid']
5107 where
= {'uuid': datacenter
['uuid']}
5108 remove_port_mapping
= False
5109 new_sdn_port_mapping
= None
5110 if "config" in datacenter_descriptor
:
5111 if datacenter_descriptor
['config'] != None:
5113 new_config_dict
= datacenter_descriptor
["config"]
5114 if "sdn-port-mapping" in new_config_dict
:
5115 remove_port_mapping
= True
5116 new_sdn_port_mapping
= new_config_dict
.pop("sdn-port-mapping")
5117 # delete null fields
5119 for k
in new_config_dict
:
5120 if new_config_dict
[k
] is None:
5122 if k
== 'sdn-controller':
5123 remove_port_mapping
= True
5125 config_text
= datacenter
.get("config")
5128 config_dict
= yaml
.load(config_text
, Loader
=yaml
.Loader
)
5129 config_dict
.update(new_config_dict
)
5130 # delete null fields
5133 except Exception as e
:
5134 raise NfvoException("Bad format at datacenter:config " + str(e
), httperrors
.Bad_Request
)
5136 datacenter_descriptor
["config"] = yaml
.safe_dump(config_dict
, default_flow_style
=True, width
=256)
5138 datacenter_descriptor
["config"] = None
5139 if remove_port_mapping
:
5141 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_id
)
5142 except ovimException
as e
:
5143 raise NfvoException("Error deleting datacenter-port-mapping " + str(e
), httperrors
.Conflict
)
5145 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
5146 if new_sdn_port_mapping
:
5148 datacenter_sdn_port_mapping_set(mydb
, None, datacenter_id
, new_sdn_port_mapping
)
5149 except ovimException
as e
:
5151 mydb
.update_rows('datacenters', datacenter
, where
)
5152 raise NfvoException("Error adding datacenter-port-mapping " + str(e
), httperrors
.Conflict
)
5153 return datacenter_id
5156 def delete_datacenter(mydb
, datacenter
):
5157 #get nfvo_tenant info
5158 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
5159 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
5161 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_dict
['uuid'])
5162 except ovimException
as e
:
5163 raise NfvoException("Error deleting datacenter-port-mapping " + str(e
))
5164 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
5167 def create_vim_account(mydb
, nfvo_tenant
, datacenter_id
, name
=None, vim_id
=None, vim_tenant
=None, vim_tenant_name
=None,
5168 vim_username
=None, vim_password
=None, config
=None):
5169 # get datacenter info
5171 if not datacenter_id
:
5173 raise NfvoException("You must provide 'vim_id", http_code
=httperrors
.Bad_Request
)
5174 datacenter_id
= vim_id
5175 datacenter_id
, datacenter_name
= get_datacenter_uuid(mydb
, None, datacenter_id
)
5177 create_vim_tenant
= True if not vim_tenant
and not vim_tenant_name
else False
5179 # get nfvo_tenant info
5180 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
5181 if vim_tenant_name
==None:
5182 vim_tenant_name
=tenant_dict
['name']
5184 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
5185 # #check that this association does not exist before
5186 # tenants_datacenters = mydb.get_rows(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict)
5187 # if len(tenants_datacenters)>0:
5188 # raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id, tenant_dict['uuid']), httperrors.Conflict)
5190 vim_tenant_id_exist_atdb
=False
5191 if not create_vim_tenant
:
5192 where_
={"datacenter_id": datacenter_id
}
5193 if vim_tenant
!=None:
5194 where_
["vim_tenant_id"] = vim_tenant
5195 if vim_tenant_name
!=None:
5196 where_
["vim_tenant_name"] = vim_tenant_name
5197 #check if vim_tenant_id is already at database
5198 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
5199 if len(datacenter_tenants_dict
)>=1:
5200 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
5201 vim_tenant_id_exist_atdb
=True
5202 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
5204 datacenter_tenants_dict
= {}
5205 #insert at table datacenter_tenants
5206 else: #if vim_tenant==None:
5207 #create tenant at VIM if not provided
5209 _
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
, vim_user
=vim_username
,
5210 vim_passwd
=vim_password
)
5211 datacenter_name
= myvim
["name"]
5212 vim_tenant
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
5213 except vimconn
.vimconnException
as e
:
5214 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), httperrors
.Internal_Server_Error
)
5215 datacenter_tenants_dict
= {}
5216 datacenter_tenants_dict
["created"]="true"
5218 #fill datacenter_tenants table
5219 if not vim_tenant_id_exist_atdb
:
5220 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant
5221 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
5222 datacenter_tenants_dict
["user"] = vim_username
5223 datacenter_tenants_dict
["passwd"] = vim_password
5224 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
5226 datacenter_tenants_dict
["name"] = name
5228 datacenter_tenants_dict
["name"] = datacenter_name
5230 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
5231 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True, confidential_data
=True)
5232 datacenter_tenants_dict
["uuid"] = id_
5234 #fill tenants_datacenters table
5235 datacenter_tenant_id
= datacenter_tenants_dict
["uuid"]
5236 tenants_datacenter_dict
["datacenter_tenant_id"] = datacenter_tenant_id
5237 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
5240 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
5241 new_thread
= vim_thread(task_lock
, plugins
, thread_name
, None, datacenter_tenant_id
, db
=db
)
5243 thread_id
= datacenter_tenants_dict
["uuid"]
5244 vim_threads
["running"][thread_id
] = new_thread
5246 except vimconn
.vimconnException
as e
:
5247 raise NfvoException(str(e
), httperrors
.Bad_Request
)
5250 def edit_vim_account(mydb
, nfvo_tenant
, datacenter_tenant_id
, datacenter_id
=None, name
=None, vim_tenant
=None,
5251 vim_tenant_name
=None, vim_username
=None, vim_password
=None, config
=None):
5253 # get vim_account; check is valid for this tenant
5254 from_
= "datacenter_tenants as dt JOIN tenants_datacenters as td ON dt.uuid=td.datacenter_tenant_id"
5255 where_
= {"td.nfvo_tenant_id": nfvo_tenant
}
5256 if datacenter_tenant_id
:
5257 where_
["dt.uuid"] = datacenter_tenant_id
5259 where_
["dt.datacenter_id"] = datacenter_id
5260 vim_accounts
= mydb
.get_rows(SELECT
="dt.uuid as uuid, config", FROM
=from_
, WHERE
=where_
)
5261 if not vim_accounts
:
5262 raise NfvoException("vim_account not found for this tenant", http_code
=httperrors
.Not_Found
)
5263 elif len(vim_accounts
) > 1:
5264 raise NfvoException("found more than one vim_account for this tenant", http_code
=httperrors
.Conflict
)
5265 datacenter_tenant_id
= vim_accounts
[0]["uuid"]
5266 original_config
= vim_accounts
[0]["config"]
5270 original_config_dict
= yaml
.load(original_config
, Loader
=yaml
.Loader
)
5271 original_config_dict
.update(config
)
5272 update
["config"] = yaml
.safe_dump(original_config_dict
, default_flow_style
=True, width
=256)
5274 update_
['name'] = name
5276 update_
['vim_tenant_id'] = vim_tenant
5278 update_
['vim_tenant_name'] = vim_tenant_name
5280 update_
['user'] = vim_username
5282 update_
['passwd'] = vim_password
5284 mydb
.update_rows("datacenter_tenants", UPDATE
=update_
, WHERE
={"uuid": datacenter_tenant_id
})
5286 vim_threads
["running"][datacenter_tenant_id
].insert_task("reload")
5287 return datacenter_tenant_id
5289 def delete_vim_account(mydb
, tenant_id
, vim_account_id
, datacenter
=None):
5290 #get nfvo_tenant info
5291 if not tenant_id
or tenant_id
=="any":
5294 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
5295 tenant_uuid
= tenant_dict
['uuid']
5297 #check that this association exist before
5298 tenants_datacenter_dict
= {}
5300 datacenter_id
, _
= get_datacenter_uuid(mydb
, tenant_uuid
, datacenter
)
5301 tenants_datacenter_dict
["datacenter_id"] = datacenter_id
5302 elif vim_account_id
:
5303 tenants_datacenter_dict
["datacenter_tenant_id"] = vim_account_id
5305 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
5306 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
5307 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
5308 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), httperrors
.Not_Found
)
5310 #delete this association
5311 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
5313 #get vim_tenant info and deletes
5315 for tenant_datacenter_item
in tenant_datacenter_list
:
5316 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
5317 #try to delete vim:tenant
5319 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
5320 if vim_tenant_dict
['created']=='true':
5321 #delete tenant at VIM if created by NFVO
5323 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5324 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
5325 except vimconn
.vimconnException
as e
:
5326 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
5327 logger
.warn(warning
)
5328 except db_base_Exception
as e
:
5329 logger
.error("Cannot delete datacenter_tenants " + str(e
))
5330 pass # the error will be caused because dependencies, vim_tenant can not be deleted
5331 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
5332 thread
= vim_threads
["running"].get(thread_id
)
5334 thread
.insert_task("exit")
5335 vim_threads
["deleting"][thread_id
] = thread
5336 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
5339 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
5341 #get datacenter info
5342 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5344 if 'check-connectivity' in action_dict
:
5346 myvim
.check_vim_connectivity()
5347 except vimconn
.vimconnException
as e
:
5348 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
5349 raise NfvoException(str(e
), e
.http_code
)
5350 elif 'net-update' in action_dict
:
5352 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
5354 except vimconn
.vimconnException
as e
:
5355 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
5356 raise NfvoException(str(e
), httperrors
.Internal_Server_Error
)
5357 #update nets Change from VIM format to NFVO format
5360 net_nfvo
={'datacenter_id': datacenter_id
}
5361 net_nfvo
['name'] = net
['name']
5362 #net_nfvo['description']= net['name']
5363 net_nfvo
['vim_net_id'] = net
['id']
5364 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
5365 net_nfvo
['shared'] = net
['shared']
5366 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
5367 net_list
.append(net_nfvo
)
5368 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
5369 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
5371 elif 'net-edit' in action_dict
:
5372 net
= action_dict
['net-edit'].pop('net')
5373 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
5374 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
5375 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
5377 elif 'net-delete' in action_dict
:
5378 net
= action_dict
['net-deelte'].get('net')
5379 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
5380 result
= mydb
.delete_row(FROM
='datacenter_nets',
5381 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
5385 raise NfvoException("Unknown action " + str(action_dict
), httperrors
.Bad_Request
)
5388 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
5389 #get datacenter info
5390 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5392 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
5393 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
5394 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
5398 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
5399 #get datacenter info
5400 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5403 action_dict
= action_dict
["netmap"]
5404 if 'vim_id' in action_dict
:
5405 filter_dict
["id"] = action_dict
['vim_id']
5406 if 'vim_name' in action_dict
:
5407 filter_dict
["name"] = action_dict
['vim_name']
5409 filter_dict
["shared"] = True
5412 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
5413 except vimconn
.vimconnException
as e
:
5414 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
5415 raise NfvoException(str(e
), httperrors
.Internal_Server_Error
)
5416 if len(vim_nets
)>1 and action_dict
:
5417 raise NfvoException("more than two networks found, specify with vim_id", httperrors
.Conflict
)
5418 elif len(vim_nets
)==0: # and action_dict:
5419 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), httperrors
.Not_Found
)
5421 for net
in vim_nets
:
5422 net_nfvo
={'datacenter_id': datacenter_id
}
5423 if action_dict
and "name" in action_dict
:
5424 net_nfvo
['name'] = action_dict
['name']
5426 net_nfvo
['name'] = net
['name']
5427 #net_nfvo['description']= net['name']
5428 net_nfvo
['vim_net_id'] = net
['id']
5429 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
5430 net_nfvo
['shared'] = net
['shared']
5431 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
5433 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
5434 net_nfvo
["status"] = "OK"
5435 net_nfvo
["uuid"] = net_id
5436 except db_base_Exception
as e
:
5440 net_nfvo
["status"] = "FAIL: " + str(e
)
5441 net_list
.append(net_nfvo
)
5444 def get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
):
5445 # obtain all network data
5447 if utils
.check_valid_uuid(network_id
):
5448 filter_dict
= {"id": network_id
}
5450 filter_dict
= {"name": network_id
}
5452 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5453 network
= myvim
.get_network_list(filter_dict
=filter_dict
)
5454 except vimconn
.vimconnException
as e
:
5455 raise NfvoException("Not possible to get_sdn_net_id from VIM: {}".format(str(e
)), e
.http_code
)
5457 # ensure the network is defined
5458 if len(network
) == 0:
5459 raise NfvoException("Network {} is not present in the system".format(network_id
),
5460 httperrors
.Bad_Request
)
5462 # ensure there is only one network with the provided name
5463 if len(network
) > 1:
5464 raise NfvoException("Multiple networks present in vim identified by {}".format(network_id
), httperrors
.Bad_Request
)
5466 # ensure it is a dataplane network
5467 if network
[0]['type'] != 'data':
5470 # ensure we use the id
5471 network_id
= network
[0]['id']
5473 # search in dabase mano_db in table instance nets for the sdn_net_id that corresponds to the vim_net_id==network_id
5474 # and with instance_scenario_id==NULL
5475 #search_dict = {'vim_net_id': network_id, 'instance_scenario_id': None}
5476 search_dict
= {'vim_net_id': network_id
}
5479 #sdn_network_id = mydb.get_rows(SELECT=('sdn_net_id',), FROM='instance_nets', WHERE=search_dict)[0]['sdn_net_id']
5480 result
= mydb
.get_rows(SELECT
=('sdn_net_id',), FROM
='instance_nets', WHERE
=search_dict
)
5481 except db_base_Exception
as e
:
5482 raise NfvoException("db_base_Exception obtaining SDN network to associated to vim network {}".format(
5483 network_id
) + str(e
), e
.http_code
)
5487 if net
['sdn_net_id'] != None:
5489 sdn_net_id
= net
['sdn_net_id']
5491 if sdn_net_counter
== 0:
5493 elif sdn_net_counter
== 1:
5496 raise NfvoException("More than one SDN network is associated to vim network {}".format(
5497 network_id
), httperrors
.Internal_Server_Error
)
5499 def get_sdn_controller_id(mydb
, datacenter
):
5500 # Obtain sdn controller id
5501 config
= mydb
.get_rows(SELECT
=('config',), FROM
='datacenters', WHERE
={'uuid': datacenter
})[0].get('config', '{}')
5505 return yaml
.load(config
, Loader
=yaml
.Loader
).get('sdn-controller')
5507 def vim_net_sdn_attach(mydb
, tenant_id
, datacenter
, network_id
, descriptor
):
5509 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
5510 if not sdn_network_id
:
5511 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
), httperrors
.Internal_Server_Error
)
5513 #Obtain sdn controller id
5514 controller_id
= get_sdn_controller_id(mydb
, datacenter
)
5515 if not controller_id
:
5516 raise NfvoException("No SDN controller is set for datacenter {}".format(datacenter
), httperrors
.Internal_Server_Error
)
5518 #Obtain sdn controller info
5519 sdn_controller
= ovim
.show_of_controller(controller_id
)
5522 'name': 'external_port',
5523 'net_id': sdn_network_id
,
5524 'ofc_id': controller_id
,
5525 'switch_dpid': sdn_controller
['dpid'],
5526 'switch_port': descriptor
['port']
5529 if 'vlan' in descriptor
:
5530 port_data
['vlan'] = descriptor
['vlan']
5531 if 'mac' in descriptor
:
5532 port_data
['mac'] = descriptor
['mac']
5534 result
= ovim
.new_port(port_data
)
5535 except ovimException
as e
:
5536 raise NfvoException("ovimException attaching SDN network {} to vim network {}".format(
5537 sdn_network_id
, network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5538 except db_base_Exception
as e
:
5539 raise NfvoException("db_base_Exception attaching SDN network to vim network {}".format(
5540 network_id
) + str(e
), e
.http_code
)
5542 return 'Port uuid: '+ result
5544 def vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, network_id
, port_id
=None):
5546 filter = {'uuid': port_id
}
5548 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
5549 if not sdn_network_id
:
5550 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
),
5551 httperrors
.Internal_Server_Error
)
5552 #in case no port_id is specified only ports marked as 'external_port' will be detached
5553 filter = {'name': 'external_port', 'net_id': sdn_network_id
}
5556 port_list
= ovim
.get_ports(columns
={'uuid'}, filter=filter)
5557 except ovimException
as e
:
5558 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
5559 httperrors
.Internal_Server_Error
)
5561 if len(port_list
) == 0:
5562 raise NfvoException("No ports attached to the network {} were found with the requested criteria".format(network_id
),
5563 httperrors
.Bad_Request
)
5566 for port
in port_list
:
5568 port_uuid_list
.append(port
['uuid'])
5569 ovim
.delete_port(port
['uuid'])
5570 except ovimException
as e
:
5571 raise NfvoException("ovimException deleting port {} for net {}. ".format(port
['uuid'], network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5573 return 'Detached ports uuid: {}'.format(','.join(port_uuid_list
))
5575 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
5576 #get datacenter info
5577 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5580 if utils
.check_valid_uuid(name
):
5581 filter_dict
["id"] = name
5583 filter_dict
["name"] = name
5585 if item
=="networks":
5586 #filter_dict['tenant_id'] = myvim['tenant_id']
5587 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
5589 if len(content
) == 0:
5590 raise NfvoException("Network {} is not present in the system. ".format(name
),
5591 httperrors
.Bad_Request
)
5593 #Update the networks with the attached ports
5595 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, net
['id'])
5596 if sdn_network_id
!= None:
5598 #port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan'}, filter={'name': 'external_port', 'net_id': sdn_network_id})
5599 port_list
= ovim
.get_ports(columns
={'uuid', 'switch_port', 'vlan','name'}, filter={'net_id': sdn_network_id
})
5600 except ovimException
as e
:
5601 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5602 #Remove field name and if port name is external_port save it as 'type'
5603 for port
in port_list
:
5604 if port
['name'] == 'external_port':
5605 port
['type'] = "External"
5607 net
['sdn_network_id'] = sdn_network_id
5608 net
['sdn_attached_ports'] = port_list
5610 elif item
=="tenants":
5611 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
5612 elif item
== "images":
5614 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
5616 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5617 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
5618 if name
and len(content
)==1:
5619 return {item
[:-1]: content
[0]}
5620 elif name
and len(content
)==0:
5621 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.items())),
5624 return {item
: content
}
5625 except vimconn
.vimconnException
as e
:
5626 print("vim_action Not possible to get_{}_list from VIM: {} ".format(item
, str(e
)))
5627 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
5630 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
5631 #get datacenter info
5632 if tenant_id
== "any":
5635 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5637 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
5638 logger
.debug("vim_action_delete vim response: " + str(content
))
5639 items
= next(iter(content
.values()))
5640 if type(items
)==list and len(items
)==0:
5641 raise NfvoException("Not found " + item
, httperrors
.Not_Found
)
5642 elif type(items
)==list and len(items
)>1:
5643 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), httperrors
.Not_Found
)
5644 else: # it is a dict
5645 item_id
= items
["id"]
5646 item_name
= str(items
.get("name"))
5649 if item
=="networks":
5650 # If there is a SDN network associated to the vim-network, proceed to clear the relationship and delete it
5651 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, item_id
)
5652 if sdn_network_id
!= None:
5653 #Delete any port attachment to this network
5655 port_list
= ovim
.get_ports(columns
={'uuid'}, filter={'net_id': sdn_network_id
})
5656 except ovimException
as e
:
5657 raise NfvoException(
5658 "ovimException obtaining external ports for net {}. ".format(sdn_network_id
) + str(e
),
5659 httperrors
.Internal_Server_Error
)
5661 # By calling one by one all ports to be detached we ensure that not only the external_ports get detached
5662 for port
in port_list
:
5663 vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, item_id
, port
['uuid'])
5665 #Delete from 'instance_nets' the correspondence between the vim-net-id and the sdn-net-id
5667 mydb
.delete_row(FROM
='instance_nets', WHERE
={'instance_scenario_id': None,
5668 'sdn_net_id': sdn_network_id
,
5669 'vim_net_id': item_id
})
5670 except db_base_Exception
as e
:
5671 raise NfvoException("Error deleting correspondence for VIM/SDN dataplane networks{}: {}".format(
5672 item_id
, e
), e
.http_code
)
5674 #Delete the SDN network
5676 ovim
.delete_network(sdn_network_id
)
5677 except ovimException
as e
:
5678 logger
.error("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
), exc_info
=True)
5679 raise NfvoException("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
),
5680 httperrors
.Internal_Server_Error
)
5682 content
= myvim
.delete_network(item_id
)
5683 elif item
=="tenants":
5684 content
= myvim
.delete_tenant(item_id
)
5685 elif item
== "images":
5686 content
= myvim
.delete_image(item_id
)
5688 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5689 except vimconn
.vimconnException
as e
:
5690 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
5691 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
5693 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
5696 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
5697 #get datacenter info
5698 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
5699 if tenant_id
== "any":
5701 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5703 if item
=="networks":
5704 net
= descriptor
["network"]
5705 net_name
= net
.pop("name")
5706 net_type
= net
.pop("type", "bridge")
5707 net_public
= net
.pop("shared", False)
5708 net_ipprofile
= net
.pop("ip_profile", None)
5709 net_vlan
= net
.pop("vlan", None)
5710 net_provider_network_profile
= None
5712 net_provider_network_profile
= {"segmentation-id": net_vlan
}
5713 content
, _
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, provider_network_profile
=net_provider_network_profile
) #, **net)
5715 #If the datacenter has a SDN controller defined and the network is of dataplane type, then create the sdn network
5716 if get_sdn_controller_id(mydb
, datacenter
) != None and (net_type
== 'data' or net_type
== 'ptp'):
5717 #obtain datacenter_tenant_id
5718 datacenter_tenant_id
= mydb
.get_rows(SELECT
=('uuid',),
5719 FROM
='datacenter_tenants',
5720 WHERE
={'datacenter_id': datacenter
})[0]['uuid']
5723 sdn_network
['vlan'] = net_vlan
5724 sdn_network
['type'] = net_type
5725 sdn_network
['name'] = net_name
5726 sdn_network
['region'] = datacenter_tenant_id
5727 ovim_content
= ovim
.new_network(sdn_network
)
5728 except ovimException
as e
:
5729 logger
.error("ovimException creating SDN network={} ".format(
5730 sdn_network
) + str(e
), exc_info
=True)
5731 raise NfvoException("ovimException creating SDN network={} ".format(sdn_network
) + str(e
),
5732 httperrors
.Internal_Server_Error
)
5734 # Save entry in in dabase mano_db in table instance_nets to stablish a dictionary vim_net_id <->sdn_net_id
5735 # use instance_scenario_id=None to distinguish from real instaces of nets
5736 correspondence
= {'instance_scenario_id': None,
5737 'sdn_net_id': ovim_content
,
5738 'vim_net_id': content
,
5739 'datacenter_tenant_id': datacenter_tenant_id
5742 mydb
.new_row('instance_nets', correspondence
, add_uuid
=True)
5743 except db_base_Exception
as e
:
5744 raise NfvoException("Error saving correspondence for VIM/SDN dataplane networks{}: {}".format(
5745 correspondence
, e
), e
.http_code
)
5746 elif item
=="tenants":
5747 tenant
= descriptor
["tenant"]
5748 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
5750 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5751 except vimconn
.vimconnException
as e
:
5752 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
5754 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
5756 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
5757 wim_id
= ovim
.new_of_controller(sdn_controller
)
5759 thread_name
= get_non_used_vim_name(sdn_controller
['name'], wim_id
, wim_id
, None)
5760 new_thread
= vim_thread(task_lock
, plugins
, thread_name
, wim_id
, None, db
=db
)
5763 vim_threads
["running"][thread_id
] = new_thread
5764 logger
.debug('New SDN controller created with uuid {}'.format(wim_id
))
5767 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
5768 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
5769 msg
= 'SDN controller {} updated'.format(data
)
5770 vim_threads
["running"][controller_id
].insert_task("reload")
5774 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
5775 if controller_id
== None:
5776 data
= ovim
.get_of_controllers()
5778 data
= ovim
.show_of_controller(controller_id
)
5780 msg
= 'SDN controller list:\n {}'.format(data
)
5784 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
5785 select_
= ('uuid', 'config')
5786 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
5787 for datacenter
in datacenters
:
5788 if datacenter
['config']:
5789 config
= yaml
.load(datacenter
['config'], Loader
=yaml
.Loader
)
5790 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
5791 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), httperrors
.Conflict
)
5793 data
= ovim
.delete_of_controller(controller_id
)
5794 msg
= 'SDN controller {} deleted'.format(data
)
5798 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
5799 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
5800 if len(controller
) < 1:
5801 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), httperrors
.Not_Found
)
5804 sdn_controller_id
= yaml
.load(controller
[0]["config"], Loader
=yaml
.Loader
)["sdn-controller"]
5806 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), httperrors
.Bad_Request
)
5808 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
5809 switch_dpid
= sdn_controller
["dpid"]
5812 for compute_node
in sdn_port_mapping
:
5813 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
5815 element
["compute_node"] = compute_node
["compute_node"]
5816 if compute_node
["ports"]:
5817 for port
in compute_node
["ports"]:
5818 pci
= port
.get("pci")
5819 element
["switch_port"] = port
.get("switch_port")
5820 element
["switch_mac"] = port
.get("switch_mac")
5821 if not element
["switch_port"] and not element
["switch_mac"]:
5822 raise NfvoException ("The mapping must contain 'switch_port' or 'switch_mac'", httperrors
.Bad_Request
)
5823 for pci_expanded
in utils
.expand_brackets(pci
):
5824 element
["pci"] = pci_expanded
5825 maps
.append(dict(element
))
5827 out
= ovim
.set_of_port_mapping(maps
, sdn_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, vim_id
=datacenter_id
)
5828 vim_threads
["running"][sdn_controller_id
].insert_task("reload")
5831 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
5832 maps
= ovim
.get_of_port_mappings(db_filter
={"datacenter_id": datacenter_id
})
5835 "sdn-controller": None,
5836 "datacenter-id": datacenter_id
,
5838 "ports_mapping": list()
5841 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
5842 if datacenter
['config']:
5843 config
= yaml
.load(datacenter
['config'], Loader
=yaml
.Loader
)
5844 if 'sdn-controller' in config
:
5845 controller_id
= config
['sdn-controller']
5846 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
5847 result
["sdn-controller"] = controller_id
5848 result
["dpid"] = sdn_controller
["dpid"]
5850 if result
["sdn-controller"] == None:
5851 raise NfvoException("SDN controller is not defined for datacenter {}".format(datacenter_id
), httperrors
.Bad_Request
)
5852 if result
["dpid"] == None:
5853 raise NfvoException("It was not possible to determine DPID for SDN controller {}".format(result
["sdn-controller"]),
5854 httperrors
.Internal_Server_Error
)
5859 ports_correspondence_dict
= dict()
5861 if result
["sdn-controller"] != link
["wim_id"]:
5862 raise NfvoException("The sdn-controller specified for different port mappings differ", httperrors
.Internal_Server_Error
)
5863 if result
["dpid"] != link
["switch_dpid"]:
5864 raise NfvoException("The dpid specified for different port mappings differ", httperrors
.Internal_Server_Error
)
5865 link_config
= link
["service_mapping_info"]
5867 element
["pci"] = link
.get("device_interface_id")
5868 if link
["switch_port"]:
5869 element
["switch_port"] = link
["switch_port"]
5870 if link_config
["switch_mac"]:
5871 element
["switch_mac"] = link_config
.get("switch_mac")
5873 if not link
.get("interface_id") in ports_correspondence_dict
:
5875 content
["compute_node"] = link
.get("interface_id")
5876 content
["ports"] = list()
5877 ports_correspondence_dict
[link
.get("interface_id")] = content
5879 ports_correspondence_dict
[link
["interface_id"]]["ports"].append(element
)
5881 for key
in sorted(ports_correspondence_dict
):
5882 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
5886 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
5887 return ovim
.clear_of_port_mapping(db_filter
={"datacenter_id":datacenter_id
})
5889 def create_RO_keypair(tenant_id
):
5891 Creates a public / private keys for a RO tenant and returns their values
5893 tenant_id: ID of the tenant
5895 public_key: Public key for the RO tenant
5896 private_key: Encrypted private key for RO tenant
5900 key
= RSA
.generate(bits
)
5902 public_key
= key
.publickey().exportKey('OpenSSH')
5903 if isinstance(public_key
, ValueError):
5904 raise NfvoException("Unable to create public key: {}".format(public_key
), httperrors
.Internal_Server_Error
)
5905 private_key
= key
.exportKey(passphrase
=tenant_id
, pkcs
=8)
5906 except (ValueError, NameError) as e
:
5907 raise NfvoException("Unable to create private key: {}".format(e
), httperrors
.Internal_Server_Error
)
5908 return public_key
, private_key
5910 def decrypt_key (key
, tenant_id
):
5912 Decrypts an encrypted RSA key
5914 key: Private key to be decrypted
5915 tenant_id: ID of the tenant
5917 unencrypted_key: Unencrypted private key for RO tenant
5920 key
= RSA
.importKey(key
,tenant_id
)
5921 unencrypted_key
= key
.exportKey('PEM')
5922 if isinstance(unencrypted_key
, ValueError):
5923 raise NfvoException("Unable to decrypt the private key: {}".format(unencrypted_key
), httperrors
.Internal_Server_Error
)
5924 except ValueError as e
:
5925 raise NfvoException("Unable to decrypt the private key: {}".format(e
), httperrors
.Internal_Server_Error
)
5926 return unencrypted_key