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)
2436 # table sce_interfaces (vld:vnfd-connection-point-ref)
2437 for iface
in vld
.get("vnfd-connection-point-ref").values():
2438 # Check if there are VDUs in the descriptor
2439 vnf_index
= str(iface
['member-vnf-index-ref'])
2440 existing_vdus
= mydb
.get_rows(SELECT
=('vms.uuid'), FROM
="vms", WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
]})
2442 # check correct parameters
2443 if vnf_index
not in vnf_index2vnf_uuid
:
2444 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2445 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2446 "'nsd':'constituent-vnfd'".format(
2447 str(nsd
["id"]), str(vld
["id"]), str(iface
["member-vnf-index-ref"])),
2448 httperrors
.Bad_Request
)
2450 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid', 'i.type as iface_type'),
2451 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2452 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2453 'external_name': get_str(iface
, "vnfd-connection-point-ref",
2455 if not existing_ifaces
:
2456 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2457 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2458 "connection-point name at VNFD '{}'".format(
2459 str(nsd
["id"]), str(vld
["id"]), str(iface
["vnfd-connection-point-ref"]),
2460 str(iface
.get("vnfd-id-ref"))[:255]),
2461 httperrors
.Bad_Request
)
2462 interface_uuid
= existing_ifaces
[0]["uuid"]
2463 if existing_ifaces
[0]["iface_type"] == "data":
2464 db_sce_net
["type"] = "data"
2465 sce_interface_uuid
= str(uuid4())
2466 uuid_list
.append(sce_net_uuid
)
2467 iface_ip_address
= None
2468 if iface
.get("ip-address"):
2469 iface_ip_address
= str(iface
.get("ip-address"))
2470 db_sce_interface
= {
2471 "uuid": sce_interface_uuid
,
2472 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2473 "sce_net_id": sce_net_uuid
,
2474 "interface_id": interface_uuid
,
2475 "ip_address": iface_ip_address
,
2477 db_sce_interfaces
.append(db_sce_interface
)
2478 if not db_sce_net
["type"]:
2479 db_sce_net
["type"] = "bridge"
2481 # table sce_vnffgs (vnffgd)
2482 for vnffg
in nsd
.get("vnffgd").values():
2483 sce_vnffg_uuid
= str(uuid4())
2484 uuid_list
.append(sce_vnffg_uuid
)
2486 "uuid": sce_vnffg_uuid
,
2487 "name": get_str(vnffg
, "name", 255),
2488 "scenario_id": scenario_uuid
,
2489 "vendor": get_str(vnffg
, "vendor", 255),
2490 "description": get_str(vld
, "description", 255),
2492 db_sce_vnffgs
.append(db_sce_vnffg
)
2495 for rsp
in vnffg
.get("rsp").values():
2496 sce_rsp_uuid
= str(uuid4())
2497 uuid_list
.append(sce_rsp_uuid
)
2499 "uuid": sce_rsp_uuid
,
2500 "name": get_str(rsp
, "name", 255),
2501 "sce_vnffg_id": sce_vnffg_uuid
,
2502 "id": get_str(rsp
, "id", 255), # only useful to link with classifiers; will be removed later in the code
2504 db_sce_rsps
.append(db_sce_rsp
)
2505 for iface
in rsp
.get("vnfd-connection-point-ref").values():
2506 vnf_index
= str(iface
['member-vnf-index-ref'])
2507 if_order
= int(iface
['order'])
2508 # check correct parameters
2509 if vnf_index
not in vnf_index2vnf_uuid
:
2510 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2511 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2512 "'nsd':'constituent-vnfd'".format(
2513 str(nsd
["id"]), str(rsp
["id"]), str(iface
["member-vnf-index-ref"])),
2514 httperrors
.Bad_Request
)
2516 ingress_existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2517 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2519 'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2520 'external_name': get_str(iface
, "vnfd-ingress-connection-point-ref",
2522 if not ingress_existing_ifaces
:
2523 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2524 "-ref':'vnfd-ingress-connection-point-ref':'{}'. Reference to a non-existing "
2525 "connection-point name at VNFD '{}'".format(
2526 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-ingress-connection-point-ref"]),
2527 str(iface
.get("vnfd-id-ref"))[:255]), httperrors
.Bad_Request
)
2529 egress_existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2530 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2532 'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2533 'external_name': get_str(iface
, "vnfd-egress-connection-point-ref",
2535 if not egress_existing_ifaces
:
2536 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2537 "-ref':'vnfd-egress-connection-point-ref':'{}'. Reference to a non-existing "
2538 "connection-point name at VNFD '{}'".format(
2539 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-egress-connection-point-ref"]),
2540 str(iface
.get("vnfd-id-ref"))[:255]), HTTP_Bad_Request
)
2542 ingress_interface_uuid
= ingress_existing_ifaces
[0]["uuid"]
2543 egress_interface_uuid
= egress_existing_ifaces
[0]["uuid"]
2544 sce_rsp_hop_uuid
= str(uuid4())
2545 uuid_list
.append(sce_rsp_hop_uuid
)
2547 "uuid": sce_rsp_hop_uuid
,
2548 "if_order": if_order
,
2549 "ingress_interface_id": ingress_interface_uuid
,
2550 "egress_interface_id": egress_interface_uuid
,
2551 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2552 "sce_rsp_id": sce_rsp_uuid
,
2554 db_sce_rsp_hops
.append(db_sce_rsp_hop
)
2556 # deal with classifiers
2557 for classifier
in vnffg
.get("classifier").values():
2558 sce_classifier_uuid
= str(uuid4())
2559 uuid_list
.append(sce_classifier_uuid
)
2562 vnf_index
= str(classifier
['member-vnf-index-ref'])
2563 if vnf_index
not in vnf_index2vnf_uuid
:
2564 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'classifier[{}]':'vnfd-connection-point"
2565 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2566 "'nsd':'constituent-vnfd'".format(
2567 str(nsd
["id"]), str(classifier
["id"]), str(classifier
["member-vnf-index-ref"])),
2568 httperrors
.Bad_Request
)
2569 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2570 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2571 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2572 'external_name': get_str(classifier
, "vnfd-connection-point-ref",
2574 if not existing_ifaces
:
2575 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2576 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2577 "connection-point name at VNFD '{}'".format(
2578 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-connection-point-ref"]),
2579 str(iface
.get("vnfd-id-ref"))[:255]),
2580 httperrors
.Bad_Request
)
2581 interface_uuid
= existing_ifaces
[0]["uuid"]
2583 db_sce_classifier
= {
2584 "uuid": sce_classifier_uuid
,
2585 "name": get_str(classifier
, "name", 255),
2586 "sce_vnffg_id": sce_vnffg_uuid
,
2587 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2588 "interface_id": interface_uuid
,
2590 rsp_id
= get_str(classifier
, "rsp-id-ref", 255)
2591 rsp
= next((item
for item
in db_sce_rsps
if item
["id"] == rsp_id
), None)
2592 db_sce_classifier
["sce_rsp_id"] = rsp
["uuid"]
2593 db_sce_classifiers
.append(db_sce_classifier
)
2595 for match
in classifier
.get("match-attributes").values():
2596 sce_classifier_match_uuid
= str(uuid4())
2597 uuid_list
.append(sce_classifier_match_uuid
)
2598 db_sce_classifier_match
= {
2599 "uuid": sce_classifier_match_uuid
,
2600 "ip_proto": get_str(match
, "ip-proto", 2),
2601 "source_ip": get_str(match
, "source-ip-address", 16),
2602 "destination_ip": get_str(match
, "destination-ip-address", 16),
2603 "source_port": get_str(match
, "source-port", 5),
2604 "destination_port": get_str(match
, "destination-port", 5),
2605 "sce_classifier_id": sce_classifier_uuid
,
2607 db_sce_classifier_matches
.append(db_sce_classifier_match
)
2610 # remove unneeded id's in sce_rsps
2611 for rsp
in db_sce_rsps
:
2615 {"scenarios": db_scenarios
},
2616 {"sce_nets": db_sce_nets
},
2617 {"ip_profiles": db_ip_profiles
},
2618 {"sce_vnfs": db_sce_vnfs
},
2619 {"sce_interfaces": db_sce_interfaces
},
2620 {"sce_vnffgs": db_sce_vnffgs
},
2621 {"sce_rsps": db_sce_rsps
},
2622 {"sce_rsp_hops": db_sce_rsp_hops
},
2623 {"sce_classifiers": db_sce_classifiers
},
2624 {"sce_classifier_matches": db_sce_classifier_matches
},
2627 logger
.debug("new_nsd_v3 done: %s",
2628 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
2629 mydb
.new_rows(db_tables
, uuid_list
)
2630 return nsd_uuid_list
2631 except NfvoException
:
2633 except Exception as e
:
2634 logger
.error("Exception {}".format(e
))
2635 raise # NfvoException("Exception {}".format(e), httperrors.Bad_Request)
2638 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
2639 data
["uuid"] = scenario_id
2640 data
["tenant_id"] = tenant_id
2641 c
= mydb
.edit_scenario( data
)
2645 @deprecated("Use create_instance")
2646 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
2647 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2648 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
2649 vims
= {datacenter_id
: myvim
}
2650 myvim_tenant
= myvim
['tenant_id']
2651 datacenter_name
= myvim
['name']
2655 #print "Checking that the scenario_id exists and getting the scenario dictionary"
2656 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
=datacenter_id
)
2657 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
2658 scenarioDict
['datacenter_id'] = datacenter_id
2659 #print '================scenarioDict======================='
2660 #print json.dumps(scenarioDict, indent=4)
2661 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
2663 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
2664 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2666 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
2667 auxNetDict
['scenario'] = {}
2669 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
2670 for sce_net
in scenarioDict
['nets']:
2671 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
2673 myNetName
= "{}.{}".format(instance_scenario_name
, sce_net
['name'])
2674 myNetName
= myNetName
[0:255] #limit length
2675 myNetType
= sce_net
['type']
2677 myNetDict
["name"] = myNetName
2678 myNetDict
["type"] = myNetType
2679 myNetDict
["tenant_id"] = myvim_tenant
2680 myNetIPProfile
= sce_net
.get('ip_profile', None)
2681 myProviderNetwork
= sce_net
.get('provider_network', None)
2683 #We should use the dictionary as input parameter for new_network
2685 if not sce_net
["external"]:
2686 network_id
, _
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
, provider_network_profile
=myProviderNetwork
)
2687 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
2688 sce_net
['vim_id'] = network_id
2689 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
2690 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2691 sce_net
["created"] = True
2693 if sce_net
['vim_id'] == None:
2694 error_text
= "Error, datacenter '{}' does not have external network '{}'.".format(
2695 datacenter_name
, sce_net
['name'])
2696 _
, message
= rollback(mydb
, vims
, rollbackList
)
2697 logger
.error("nfvo.start_scenario: %s", error_text
)
2698 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2699 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
2700 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
2702 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
2703 #For each vnf net, we create it and we add it to instanceNetlist.
2705 for sce_vnf
in scenarioDict
['vnfs']:
2706 for net
in sce_vnf
['nets']:
2707 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
2709 myNetName
= "{}.{}".format(instance_scenario_name
,net
['name'])
2710 myNetName
= myNetName
[0:255] #limit length
2711 myNetType
= net
['type']
2713 myNetDict
["name"] = myNetName
2714 myNetDict
["type"] = myNetType
2715 myNetDict
["tenant_id"] = myvim_tenant
2716 myNetIPProfile
= net
.get('ip_profile', None)
2717 myProviderNetwork
= sce_net
.get('provider_network', None)
2720 #We should use the dictionary as input parameter for new_network
2721 network_id
, _
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
, provider_network_profile
=myProviderNetwork
)
2722 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
2723 net
['vim_id'] = network_id
2724 if sce_vnf
['uuid'] not in auxNetDict
:
2725 auxNetDict
[sce_vnf
['uuid']] = {}
2726 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
2727 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2728 net
["created"] = True
2730 #print "auxNetDict:"
2731 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2733 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
2734 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2736 for sce_vnf
in scenarioDict
['vnfs']:
2737 vnf_availability_zones
= []
2738 for vm
in sce_vnf
['vms']:
2739 vm_av
= vm
.get('availability_zone')
2740 if vm_av
and vm_av
not in vnf_availability_zones
:
2741 vnf_availability_zones
.append(vm_av
)
2743 # check if there is enough availability zones available at vim level.
2744 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
2745 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
2746 raise NfvoException('No enough availability zones at VIM for this deployment', httperrors
.Bad_Request
)
2748 for vm
in sce_vnf
['vms']:
2751 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
2752 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
2753 #myVMDict['description'] = vm['description']
2754 myVMDict
['description'] = myVMDict
['name'][0:99]
2756 myVMDict
['start'] = "no"
2757 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2758 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
2760 #create image at vim in case it not exist
2761 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2762 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
2763 vm
['vim_image_id'] = image_id
2765 #create flavor at vim in case it not exist
2766 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2767 if flavor_dict
['extended']!=None:
2768 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'], Loader
=yaml
.Loader
)
2769 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
2770 vm
['vim_flavor_id'] = flavor_id
2773 myVMDict
['imageRef'] = vm
['vim_image_id']
2774 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2775 myVMDict
['networks'] = []
2776 for iface
in vm
['interfaces']:
2778 if iface
['type']=="data":
2779 netDict
['type'] = iface
['model']
2780 elif "model" in iface
and iface
["model"]!=None:
2781 netDict
['model']=iface
['model']
2782 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2783 #discover type of interface looking at flavor
2784 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2785 for flavor_iface
in numa
.get('interfaces',[]):
2786 if flavor_iface
.get('name') == iface
['internal_name']:
2787 if flavor_iface
['dedicated'] == 'yes':
2788 netDict
['type']="PF" #passthrough
2789 elif flavor_iface
['dedicated'] == 'no':
2790 netDict
['type']="VF" #siov
2791 elif flavor_iface
['dedicated'] == 'yes:sriov':
2792 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2793 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2795 netDict
["use"]=iface
['type']
2796 if netDict
["use"]=="data" and not netDict
.get("type"):
2797 #print "netDict", netDict
2798 #print "iface", iface
2799 e_text
= "Cannot determine the interface type PF or VF of VNF '{}' VM '{}' iface '{}'".format(
2800 sce_vnf
['name'], vm
['name'], iface
['internal_name'])
2801 if flavor_dict
.get('extended')==None:
2802 raise NfvoException(e_text
+ "After database migration some information is not available. \
2803 Try to delete and create the scenarios and VNFs again", httperrors
.Conflict
)
2805 raise NfvoException(e_text
, httperrors
.Internal_Server_Error
)
2806 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2807 netDict
["type"]="virtual"
2808 if "vpci" in iface
and iface
["vpci"] is not None:
2809 netDict
['vpci'] = iface
['vpci']
2810 if "mac" in iface
and iface
["mac"] is not None:
2811 netDict
['mac_address'] = iface
['mac']
2812 if "port-security" in iface
and iface
["port-security"] is not None:
2813 netDict
['port_security'] = iface
['port-security']
2814 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2815 netDict
['floating_ip'] = iface
['floating-ip']
2816 netDict
['name'] = iface
['internal_name']
2817 if iface
['net_id'] is None:
2818 for vnf_iface
in sce_vnf
["interfaces"]:
2821 if vnf_iface
['interface_id']==iface
['uuid']:
2822 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
2825 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2826 #skip bridge ifaces not connected to any net
2827 #if 'net_id' not in netDict or netDict['net_id']==None:
2829 myVMDict
['networks'].append(netDict
)
2830 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2831 #print myVMDict['name']
2832 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2833 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2834 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2836 if 'availability_zone' in myVMDict
:
2837 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
2841 vm_id
, _
= myvim
.new_vminstance(myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2842 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2843 availability_zone_index
=av_index
,
2844 availability_zone_list
=vnf_availability_zones
)
2845 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
2846 vm
['vim_id'] = vm_id
2847 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2848 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2849 for net
in myVMDict
['networks']:
2851 for iface
in vm
['interfaces']:
2852 if net
["name"]==iface
["internal_name"]:
2853 iface
["vim_id"]=net
["vim_id"]
2856 logger
.debug("start scenario Deployment done")
2857 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2858 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
2859 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
2860 return mydb
.get_instance_scenario(instance_id
)
2862 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
2863 _
, message
= rollback(mydb
, vims
, rollbackList
)
2864 if isinstance(e
, db_base_Exception
):
2865 error_text
= "Exception at database"
2867 error_text
= "Exception at VIM"
2868 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2869 #logger.error("start_scenario %s", error_text)
2870 raise NfvoException(error_text
, e
.http_code
)
2872 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
2873 """ join the cloud config information into cloud_config_preserve.
2874 In case of conflict cloud_config_preserve preserves
2877 if not cloud_config_preserve
and not cloud_config
:
2880 new_cloud_config
= {"key-pairs":[], "users":[]}
2882 if cloud_config_preserve
:
2883 for key
in cloud_config_preserve
.get("key-pairs", () ):
2884 if key
not in new_cloud_config
["key-pairs"]:
2885 new_cloud_config
["key-pairs"].append(key
)
2887 for key
in cloud_config
.get("key-pairs", () ):
2888 if key
not in new_cloud_config
["key-pairs"]:
2889 new_cloud_config
["key-pairs"].append(key
)
2890 if not new_cloud_config
["key-pairs"]:
2891 del new_cloud_config
["key-pairs"]
2895 new_cloud_config
["users"] += cloud_config
.get("users", () )
2896 if cloud_config_preserve
:
2897 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
2898 index_to_delete
= []
2899 users
= new_cloud_config
.get("users", [])
2900 for index0
in range(0,len(users
)):
2901 if index0
in index_to_delete
:
2903 for index1
in range(index0
+1,len(users
)):
2904 if index1
in index_to_delete
:
2906 if users
[index0
]["name"] == users
[index1
]["name"]:
2907 index_to_delete
.append(index1
)
2908 for key
in users
[index1
].get("key-pairs",()):
2909 if "key-pairs" not in users
[index0
]:
2910 users
[index0
]["key-pairs"] = [key
]
2911 elif key
not in users
[index0
]["key-pairs"]:
2912 users
[index0
]["key-pairs"].append(key
)
2913 index_to_delete
.sort(reverse
=True)
2914 for index
in index_to_delete
:
2916 if not new_cloud_config
["users"]:
2917 del new_cloud_config
["users"]
2920 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
2921 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
2922 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
2923 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
2926 new_cloud_config
["user-data"] = []
2927 if cloud_config
and cloud_config
.get("user-data"):
2928 if isinstance(cloud_config
["user-data"], list):
2929 new_cloud_config
["user-data"] += cloud_config
["user-data"]
2931 new_cloud_config
["user-data"].append(cloud_config
["user-data"])
2932 if cloud_config_preserve
and cloud_config_preserve
.get("user-data"):
2933 if isinstance(cloud_config_preserve
["user-data"], list):
2934 new_cloud_config
["user-data"] += cloud_config_preserve
["user-data"]
2936 new_cloud_config
["user-data"].append(cloud_config_preserve
["user-data"])
2937 if not new_cloud_config
["user-data"]:
2938 del new_cloud_config
["user-data"]
2941 new_cloud_config
["config-files"] = []
2942 if cloud_config
and cloud_config
.get("config-files") != None:
2943 new_cloud_config
["config-files"] += cloud_config
["config-files"]
2944 if cloud_config_preserve
:
2945 for file in cloud_config_preserve
.get("config-files", ()):
2946 for index
in range(0, len(new_cloud_config
["config-files"])):
2947 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
2948 new_cloud_config
["config-files"][index
] = file
2951 new_cloud_config
["config-files"].append(file)
2952 if not new_cloud_config
["config-files"]:
2953 del new_cloud_config
["config-files"]
2954 return new_cloud_config
2957 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
2958 datacenter_id
= None
2959 datacenter_name
= None
2962 if datacenter_tenant_id
:
2963 thread_id
= datacenter_tenant_id
2964 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
2966 where_
={"td.nfvo_tenant_id": tenant_id
}
2967 if datacenter_id_name
:
2968 if utils
.check_valid_uuid(datacenter_id_name
):
2969 datacenter_id
= datacenter_id_name
2970 where_
["dt.datacenter_id"] = datacenter_id
2972 datacenter_name
= datacenter_id_name
2973 where_
["d.name"] = datacenter_name
2974 if datacenter_tenant_id
:
2975 where_
["dt.uuid"] = datacenter_tenant_id
2976 datacenters
= mydb
.get_rows(
2977 SELECT
=("dt.uuid as datacenter_tenant_id",),
2978 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
2979 "join datacenters as d on d.uuid=dt.datacenter_id",
2981 if len(datacenters
) > 1:
2982 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
2984 thread_id
= datacenters
[0]["datacenter_tenant_id"]
2985 thread
= vim_threads
["running"].get(thread_id
)
2987 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
2988 return thread_id
, thread
2989 except db_base_Exception
as e
:
2990 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
2993 def get_datacenter_uuid(mydb
, tenant_id
, datacenter_id_name
):
2995 if utils
.check_valid_uuid(datacenter_id_name
):
2996 WHERE_dict
['d.uuid'] = datacenter_id_name
2998 WHERE_dict
['d.name'] = datacenter_id_name
3001 WHERE_dict
['nfvo_tenant_id'] = tenant_id
3002 from_
= "tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join datacenter_tenants as" \
3003 " dt on td.datacenter_tenant_id=dt.uuid"
3005 from_
= 'datacenters as d'
3006 vimaccounts
= mydb
.get_rows(FROM
=from_
, SELECT
=("d.uuid as uuid, d.name as name",), WHERE
=WHERE_dict
)
3007 if len(vimaccounts
) == 0:
3008 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
3009 elif len(vimaccounts
)>1:
3010 #print "nfvo.datacenter_action() error. Several datacenters found"
3011 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
3012 return vimaccounts
[0]["uuid"], vimaccounts
[0]["name"]
3015 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
3016 datacenter_id
= None
3017 datacenter_name
= None
3018 if datacenter_id_name
:
3019 if utils
.check_valid_uuid(datacenter_id_name
):
3020 datacenter_id
= datacenter_id_name
3022 datacenter_name
= datacenter_id_name
3023 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
3025 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
3027 #print "nfvo.datacenter_action() error. Several datacenters found"
3028 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
3029 for vim_id
, vim_content
in vims
.items():
3030 return vim_id
, vim_content
3034 """Takes dict d and updates it with the values in dict u.
3035 It merges all depth levels"""
3036 for k
, v
in u
.items():
3037 if isinstance(v
, collections
.Mapping
):
3038 r
= update(d
.get(k
, {}), v
)
3045 def _get_wim(db
, wim_account_id
):
3046 # get wim from wim_account
3047 wim_accounts
= db
.get_rows(FROM
='wim_accounts', WHERE
={"uuid": wim_account_id
})
3048 if not wim_accounts
:
3049 raise NfvoException("Not found sdn id={}".format(wim_account_id
), http_code
=httperrors
.Not_Found
)
3050 return wim_accounts
[0]["wim_id"]
3053 def create_instance(mydb
, tenant_id
, instance_dict
):
3054 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
3055 # logger.debug("Creating instance...")
3057 scenario
= instance_dict
["scenario"]
3059 # find main datacenter
3061 myvim_threads_id
= {}
3062 datacenter
= instance_dict
.get("datacenter")
3063 default_wim_account
= instance_dict
.get("wim_account")
3064 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3065 myvims
[default_datacenter_id
] = vim
3066 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
3067 tenant
= mydb
.get_rows_by_id('nfvo_tenants', tenant_id
)
3068 # myvim_tenant = myvim['tenant_id']
3071 # print "Checking that the scenario exists and getting the scenario dictionary"
3072 if isinstance(scenario
, str):
3073 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, datacenter_vim_id
=myvim_threads_id
[default_datacenter_id
],
3074 datacenter_id
=default_datacenter_id
)
3076 scenarioDict
= scenario
3077 scenarioDict
["uuid"] = None
3079 # logger.debug(">>>>>> Dictionaries before merging")
3080 # logger.debug(">>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
3081 # logger.debug(">>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
3083 db_instance_vnfs
= []
3084 db_instance_vms
= []
3085 db_instance_interfaces
= []
3086 db_instance_sfis
= []
3087 db_instance_sfs
= []
3088 db_instance_classifications
= []
3089 db_instance_sfps
= []
3094 instance_name
= instance_dict
["name"]
3095 instance_uuid
= str(uuid4())
3096 uuid_list
.append(instance_uuid
)
3097 db_instance_scenario
= {
3098 "uuid": instance_uuid
,
3099 "name": instance_name
,
3100 "tenant_id": tenant_id
,
3101 "scenario_id": scenarioDict
['uuid'],
3102 "datacenter_id": default_datacenter_id
,
3103 # filled bellow 'datacenter_tenant_id'
3104 "description": instance_dict
.get("description"),
3106 if scenarioDict
.get("cloud-config"):
3107 db_instance_scenario
["cloud_config"] = yaml
.safe_dump(scenarioDict
["cloud-config"],
3108 default_flow_style
=True, width
=256)
3109 instance_action_id
= get_task_id()
3110 db_instance_action
= {
3111 "uuid": instance_action_id
, # same uuid for the instance and the action on create
3112 "tenant_id": tenant_id
,
3113 "instance_id": instance_uuid
,
3114 "description": "CREATE",
3117 # Auxiliary dictionaries from x to y
3118 sce_net2wim_instance
= {}
3119 sce_net2instance
= {}
3120 net2task_id
= {'scenario': {}}
3121 # Mapping between local networks and WIMs
3124 def ip_profile_IM2RO(ip_profile_im
):
3125 # translate from input format to database format
3127 if 'subnet-address' in ip_profile_im
:
3128 ip_profile_ro
['subnet_address'] = ip_profile_im
['subnet-address']
3129 if 'ip-version' in ip_profile_im
:
3130 ip_profile_ro
['ip_version'] = ip_profile_im
['ip-version']
3131 if 'gateway-address' in ip_profile_im
:
3132 ip_profile_ro
['gateway_address'] = ip_profile_im
['gateway-address']
3133 if 'dns-address' in ip_profile_im
:
3134 ip_profile_ro
['dns_address'] = ip_profile_im
['dns-address']
3135 if isinstance(ip_profile_ro
['dns_address'], (list, tuple)):
3136 ip_profile_ro
['dns_address'] = ";".join(ip_profile_ro
['dns_address'])
3137 if 'dhcp' in ip_profile_im
:
3138 ip_profile_ro
['dhcp_start_address'] = ip_profile_im
['dhcp'].get('start-address')
3139 ip_profile_ro
['dhcp_enabled'] = ip_profile_im
['dhcp'].get('enabled', True)
3140 ip_profile_ro
['dhcp_count'] = ip_profile_im
['dhcp'].get('count')
3141 return ip_profile_ro
3143 # logger.debug("Creating instance from scenario-dict:\n%s",
3144 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
3146 # 0 check correct parameters
3147 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).items():
3148 for scenario_net
in scenarioDict
['nets']:
3149 if net_name
== scenario_net
.get("name") or net_name
== scenario_net
.get("osm_id") or net_name
== scenario_net
.get("uuid"):
3152 raise NfvoException("Invalid scenario network name or id '{}' at instance:networks".format(net_name
),
3153 httperrors
.Bad_Request
)
3154 if "sites" not in net_instance_desc
:
3155 net_instance_desc
["sites"] = [ {} ]
3156 site_without_datacenter_field
= False
3157 for site
in net_instance_desc
["sites"]:
3158 if site
.get("datacenter"):
3159 site
["datacenter"], _
= get_datacenter_uuid(mydb
, tenant_id
, site
["datacenter"])
3160 if site
["datacenter"] not in myvims
:
3161 # Add this datacenter to myvims
3162 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
3164 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
3165 site
["datacenter"] = d
# change name to id
3167 if site_without_datacenter_field
:
3168 raise NfvoException("Found more than one entries without datacenter field at "
3169 "instance:networks:{}:sites".format(net_name
), httperrors
.Bad_Request
)
3170 site_without_datacenter_field
= True
3171 site
["datacenter"] = default_datacenter_id
# change name to id
3173 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).items():
3174 for scenario_vnf
in scenarioDict
['vnfs']:
3175 if vnf_name
== scenario_vnf
['member_vnf_index'] or vnf_name
== scenario_vnf
['uuid'] or vnf_name
== scenario_vnf
['name']:
3178 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_name
), httperrors
.Bad_Request
)
3179 if "datacenter" in vnf_instance_desc
:
3180 # Add this datacenter to myvims
3181 vnf_instance_desc
["datacenter"], _
= get_datacenter_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3182 if vnf_instance_desc
["datacenter"] not in myvims
:
3183 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3185 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3186 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
3188 for net_id
, net_instance_desc
in vnf_instance_desc
.get("networks", {}).items():
3189 for scenario_net
in scenario_vnf
['nets']:
3190 if net_id
== scenario_net
['osm_id'] or net_id
== scenario_net
['uuid'] or net_id
== scenario_net
["name"]:
3193 raise NfvoException("Invalid net id or name '{}' at instance:vnfs:networks".format(net_id
), httperrors
.Bad_Request
)
3194 if net_instance_desc
.get("vim-network-name"):
3195 scenario_net
["vim-network-name"] = net_instance_desc
["vim-network-name"]
3196 if net_instance_desc
.get("vim-network-id"):
3197 scenario_net
["vim-network-id"] = net_instance_desc
["vim-network-id"]
3198 if net_instance_desc
.get("name"):
3199 scenario_net
["name"] = net_instance_desc
["name"]
3200 if 'ip-profile' in net_instance_desc
:
3201 ipprofile_db
= ip_profile_IM2RO(net_instance_desc
['ip-profile'])
3202 if 'ip_profile' not in scenario_net
:
3203 scenario_net
['ip_profile'] = ipprofile_db
3205 update(scenario_net
['ip_profile'], ipprofile_db
)
3207 if 'provider-network' in net_instance_desc
:
3208 provider_network_db
= net_instance_desc
['provider-network']
3209 if 'provider-network' not in scenario_net
:
3210 scenario_net
['provider-network'] = provider_network_db
3212 update(scenario_net
['provider-network'], provider_network_db
)
3214 for vdu_id
, vdu_instance_desc
in vnf_instance_desc
.get("vdus", {}).items():
3215 for scenario_vm
in scenario_vnf
['vms']:
3216 if vdu_id
== scenario_vm
['osm_id'] or vdu_id
== scenario_vm
["name"]:
3219 raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id
), httperrors
.Bad_Request
)
3220 scenario_vm
["instance_parameters"] = vdu_instance_desc
3221 for iface_id
, iface_instance_desc
in vdu_instance_desc
.get("interfaces", {}).items():
3222 for scenario_interface
in scenario_vm
['interfaces']:
3223 if iface_id
== scenario_interface
['internal_name'] or iface_id
== scenario_interface
["external_name"]:
3224 scenario_interface
.update(iface_instance_desc
)
3227 raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id
), httperrors
.Bad_Request
)
3229 # 0.1 parse cloud-config parameters
3230 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
3232 # 0.2 merge instance information into scenario
3233 # Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
3234 # However, this is not possible yet.
3235 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).items():
3236 for scenario_net
in scenarioDict
['nets']:
3237 if net_name
== scenario_net
.get("name") or net_name
== scenario_net
.get("osm_id") or net_name
== scenario_net
.get("uuid"):
3238 if "wim_account" in net_instance_desc
and net_instance_desc
["wim_account"] is not None:
3239 scenario_net
["wim_account"] = net_instance_desc
["wim_account"]
3240 if 'ip-profile' in net_instance_desc
:
3241 ipprofile_db
= ip_profile_IM2RO(net_instance_desc
['ip-profile'])
3242 if 'ip_profile' not in scenario_net
:
3243 scenario_net
['ip_profile'] = ipprofile_db
3245 update(scenario_net
['ip_profile'], ipprofile_db
)
3246 if 'provider-network' in net_instance_desc
:
3247 provider_network_db
= net_instance_desc
['provider-network']
3249 if 'provider-network' not in scenario_net
:
3250 scenario_net
['provider_network'] = provider_network_db
3252 update(scenario_net
['provider-network'], provider_network_db
)
3254 for interface
in net_instance_desc
.get('interfaces', ()):
3255 if 'ip_address' in interface
:
3256 for vnf
in scenarioDict
['vnfs']:
3257 if interface
['vnf'] == vnf
['name']:
3258 for vnf_interface
in vnf
['interfaces']:
3259 if interface
['vnf_interface'] == vnf_interface
['external_name']:
3260 vnf_interface
['ip_address'] = interface
['ip_address']
3262 # logger.debug(">>>>>>>> Merged dictionary")
3263 # logger.debug("Creating instance scenario-dict MERGED:\n%s",
3264 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
3267 # 1. Creating new nets (sce_nets) in the VIM"
3268 number_mgmt_networks
= 0
3269 db_instance_nets
= []
3270 db_instance_wim_nets
= []
3271 for sce_net
in scenarioDict
['nets']:
3273 sce_net_uuid
= sce_net
.get('uuid', sce_net
["name"])
3274 # get involved datacenters where this network need to be created
3275 involved_datacenters
= []
3276 for sce_vnf
in scenarioDict
.get("vnfs", ()):
3277 vnf_datacenter
= sce_vnf
.get("datacenter", default_datacenter_id
)
3278 if vnf_datacenter
in involved_datacenters
:
3280 if sce_vnf
.get("interfaces"):
3281 for sce_vnf_ifaces
in sce_vnf
["interfaces"]:
3282 if sce_vnf_ifaces
.get("sce_net_id") == sce_net
["uuid"]:
3283 involved_datacenters
.append(vnf_datacenter
)
3285 if not involved_datacenters
:
3286 involved_datacenters
.append(default_datacenter_id
)
3287 target_wim_account
= sce_net
.get("wim_account", default_wim_account
)
3290 # TODO: use this information during network creation
3291 wim_account_id
= wim_account_name
= None
3292 if len(involved_datacenters
) > 1 and 'uuid' in sce_net
:
3293 if target_wim_account
is None or target_wim_account
is True: # automatic selection of WIM
3294 # OBS: sce_net without uuid are used internally to VNFs
3295 # and the assumption is that VNFs will not be split among
3296 # different datacenters
3297 wim_account
= wim_engine
.find_suitable_wim_account(
3298 involved_datacenters
, tenant_id
)
3299 wim_account_id
= wim_account
['uuid']
3300 wim_account_name
= wim_account
['name']
3301 wim_usage
[sce_net
['uuid']] = wim_account_id
3302 elif isinstance(target_wim_account
, str): # manual selection of WIM
3303 wim_account
.persist
.get_wim_account_by(target_wim_account
, tenant_id
)
3304 wim_account_id
= wim_account
['uuid']
3305 wim_account_name
= wim_account
['name']
3306 wim_usage
[sce_net
['uuid']] = wim_account_id
3307 else: # not WIM usage
3308 wim_usage
[sce_net
['uuid']] = False
3312 if instance_dict
.get("networks"):
3313 if sce_net
.get("uuid") in instance_dict
["networks"]:
3314 descriptor_net
= instance_dict
["networks"][sce_net
["uuid"]]
3315 descriptor_net_name
= sce_net
["uuid"]
3316 elif sce_net
.get("osm_id") in instance_dict
["networks"]:
3317 descriptor_net
= instance_dict
["networks"][sce_net
["osm_id"]]
3318 descriptor_net_name
= sce_net
["osm_id"]
3319 elif sce_net
["name"] in instance_dict
["networks"]:
3320 descriptor_net
= instance_dict
["networks"][sce_net
["name"]]
3321 descriptor_net_name
= sce_net
["name"]
3322 net_name
= descriptor_net
.get("vim-network-name")
3323 # add datacenters from instantiation parameters
3324 if descriptor_net
.get("sites"):
3325 for site
in descriptor_net
["sites"]:
3326 if site
.get("datacenter") and site
["datacenter"] not in involved_datacenters
:
3327 involved_datacenters
.append(site
["datacenter"])
3328 sce_net2instance
[sce_net_uuid
] = {}
3329 sce_net2wim_instance
[sce_net_uuid
] = {}
3330 net2task_id
['scenario'][sce_net_uuid
] = {}
3333 related_network
= None
3334 if descriptor_net
.get("use-network"):
3335 target_instance_nets
= mydb
.get_rows(
3337 FROM
="instance_nets",
3338 WHERE
={"instance_scenario_id": descriptor_net
["use-network"]["instance_scenario_id"],
3339 "osm_id": descriptor_net
["use-network"]["osm_id"]},
3341 if not target_instance_nets
:
3342 raise NfvoException(
3343 "Cannot find the target network at instance:networks[{}]:use-network".format(descriptor_net_name
),
3344 httperrors
.Bad_Request
)
3346 use_network
= target_instance_nets
[0]["related"]
3348 if sce_net
["external"]:
3349 number_mgmt_networks
+= 1
3351 for datacenter_id
in involved_datacenters
:
3353 netmap_create
= None
3354 if descriptor_net
.get("sites"):
3355 for site
in descriptor_net
["sites"]:
3356 if site
.get("datacenter") == datacenter_id
:
3357 netmap_use
= site
.get("netmap-use")
3358 netmap_create
= site
.get("netmap-create")
3361 vim
= myvims
[datacenter_id
]
3362 myvim_thread_id
= myvim_threads_id
[datacenter_id
]
3364 net_type
= sce_net
['type']
3366 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} # 'shared': True
3369 if sce_net
["external"]:
3370 net_name
= sce_net
["name"]
3372 net_name
= "{}-{}".format(instance_name
, sce_net
["name"])
3373 net_name
= net_name
[:255] # limit length
3375 if netmap_use
or netmap_create
:
3376 create_network
= False
3377 lookfor_network
= False
3379 lookfor_network
= True
3380 if utils
.check_valid_uuid(netmap_use
):
3381 lookfor_filter
["id"] = netmap_use
3383 lookfor_filter
["name"] = netmap_use
3385 create_network
= True
3386 net_vim_name
= net_name
3387 if isinstance(netmap_create
, str):
3388 net_vim_name
= netmap_create
3389 elif sce_net
.get("vim_network_name"):
3390 create_network
= False
3391 lookfor_network
= True
3392 lookfor_filter
["name"] = sce_net
.get("vim_network_name")
3393 elif sce_net
["external"]:
3394 if sce_net
.get('vim_id'):
3395 # there is a netmap at datacenter_nets database # TODO REVISE!!!!
3396 create_network
= False
3397 lookfor_network
= True
3398 lookfor_filter
["id"] = sce_net
['vim_id']
3399 elif vim
["config"].get("management_network_id") or vim
["config"].get("management_network_name"):
3400 if number_mgmt_networks
> 1:
3401 raise NfvoException("Found several VLD of type mgmt. "
3402 "You must concrete what vim-network must be use for each one",
3403 httperrors
.Bad_Request
)
3404 create_network
= False
3405 lookfor_network
= True
3406 if vim
["config"].get("management_network_id"):
3407 lookfor_filter
["id"] = vim
["config"]["management_network_id"]
3409 lookfor_filter
["name"] = vim
["config"]["management_network_name"]
3411 # There is not a netmap, look at datacenter for a net with this name and create if not found
3412 create_network
= True
3413 lookfor_network
= True
3414 lookfor_filter
["name"] = sce_net
["name"]
3415 net_vim_name
= sce_net
["name"]
3417 net_vim_name
= net_name
3418 create_network
= True
3419 lookfor_network
= False
3423 task_action
= "CREATE"
3424 task_extra
["params"] = (net_vim_name
, net_type
, sce_net
.get('ip_profile', None), False,
3425 sce_net
.get('provider_network', None), wim_account_name
)
3428 task_extra
["find"] = (lookfor_filter
,)
3429 elif lookfor_network
:
3430 task_action
= "FIND"
3431 task_extra
["params"] = (lookfor_filter
,)
3433 # fill database content
3434 net_uuid
= str(uuid4())
3435 uuid_list
.append(net_uuid
)
3436 sce_net2instance
[sce_net_uuid
][datacenter_id
] = net_uuid
3437 if not related_network
: # all db_instance_nets will have same related
3438 related_network
= use_network
or net_uuid
3440 sdn_controller
= vim
.config
.get('sdn-controller')
3441 sce_net2wim_instance
[sce_net_uuid
][datacenter_id
] = None
3442 if sdn_controller
and net_type
in ("data", "ptp"):
3443 wim_id
= _get_wim(mydb
, sdn_controller
)
3444 sdn_net_id
= str(uuid4())
3445 sce_net2wim_instance
[sce_net_uuid
][datacenter_id
] = sdn_net_id
3446 task_extra
["sdn_net_id"] = sdn_net_id
3447 db_instance_wim_nets
.append({
3449 "instance_scenario_id": instance_uuid
,
3450 "sce_net_id": sce_net
.get("uuid"),
3452 "wim_account_id": sdn_controller
,
3453 'status': 'BUILD', # if create_network else "ACTIVE"
3454 "related": related_network
,
3455 'multipoint': True if net_type
=="data" else False,
3456 "created": create_network
, # TODO py3
3459 task_wim_extra
= {"params": [net_type
, wim_account_name
]}
3461 "instance_action_id": instance_action_id
,
3462 "status": "SCHEDULED",
3463 "task_index": task_index
,
3464 # "datacenter_vim_id": myvim_thread_id,
3465 "wim_account_id": sdn_controller
,
3466 "action": task_action
,
3467 "item": "instance_wim_nets",
3468 "item_id": sdn_net_id
,
3469 "related": related_network
,
3470 "extra": yaml
.safe_dump(task_wim_extra
, default_flow_style
=True, width
=256)
3473 db_vim_actions
.append(db_vim_action
)
3476 "osm_id": sce_net
.get("osm_id") or sce_net
["name"],
3477 "related": related_network
,
3479 "vim_name": net_vim_name
,
3480 "instance_scenario_id": instance_uuid
,
3481 "sce_net_id": sce_net
.get("uuid"),
3482 "created": create_network
,
3483 'datacenter_id': datacenter_id
,
3484 'datacenter_tenant_id': myvim_thread_id
,
3485 'status': 'BUILD', # if create_network else "ACTIVE"
3486 'sdn_net_id': sdn_net_id
,
3488 db_instance_nets
.append(db_net
)
3490 "instance_action_id": instance_action_id
,
3491 "status": "SCHEDULED",
3492 "task_index": task_index
,
3493 "datacenter_vim_id": myvim_thread_id
,
3494 "action": task_action
,
3495 "item": "instance_nets",
3496 "item_id": net_uuid
,
3497 "related": related_network
,
3498 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
3500 net2task_id
['scenario'][sce_net_uuid
][datacenter_id
] = task_index
3502 db_vim_actions
.append(db_vim_action
)
3504 if 'ip_profile' in sce_net
:
3506 'instance_net_id': net_uuid
,
3507 'ip_version': sce_net
['ip_profile']['ip_version'],
3508 'subnet_address': sce_net
['ip_profile']['subnet_address'],
3509 'gateway_address': sce_net
['ip_profile']['gateway_address'],
3510 'dns_address': sce_net
['ip_profile']['dns_address'],
3511 'dhcp_enabled': sce_net
['ip_profile']['dhcp_enabled'],
3512 'dhcp_start_address': sce_net
['ip_profile']['dhcp_start_address'],
3513 'dhcp_count': sce_net
['ip_profile']['dhcp_count'],
3515 db_ip_profiles
.append(db_ip_profile
)
3519 "default_datacenter_id": default_datacenter_id
,
3520 "myvim_threads_id": myvim_threads_id
,
3521 "instance_uuid": instance_uuid
,
3522 "instance_name": instance_name
,
3523 "instance_action_id": instance_action_id
,
3525 "cloud_config": cloud_config
,
3526 "RO_pub_key": tenant
[0].get('RO_pub_key'),
3527 "instance_parameters": instance_dict
,
3530 "task_index": task_index
,
3531 "uuid_list": uuid_list
,
3532 "db_instance_nets": db_instance_nets
,
3533 "db_instance_wim_nets": db_instance_wim_nets
,
3534 "db_vim_actions": db_vim_actions
,
3535 "db_ip_profiles": db_ip_profiles
,
3536 "db_instance_vnfs": db_instance_vnfs
,
3537 "db_instance_vms": db_instance_vms
,
3538 "db_instance_interfaces": db_instance_interfaces
,
3539 "net2task_id": net2task_id
,
3540 "sce_net2instance": sce_net2instance
,
3541 "sce_net2wim_instance": sce_net2wim_instance
,
3543 # sce_vnf_list = sorted(scenarioDict['vnfs'], key=lambda k: k['name'])
3544 for sce_vnf
in scenarioDict
.get('vnfs', ()): # sce_vnf_list:
3545 instantiate_vnf(mydb
, sce_vnf
, vnf_params
, vnf_params_out
, rollbackList
)
3546 task_index
= vnf_params_out
["task_index"]
3547 uuid_list
= vnf_params_out
["uuid_list"]
3550 # task_depends_on = []
3551 for vnffg
in scenarioDict
.get('vnffgs', ()):
3552 for rsp
in vnffg
['rsps']:
3554 for cp
in rsp
['connection_points']:
3555 count
= mydb
.get_rows(
3557 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_rsp_hops as h "
3558 "on interfaces.uuid=h.ingress_interface_id",
3559 WHERE
={'h.uuid': cp
['uuid']})[0]['count']
3560 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == cp
['sce_vnf_id']), None)
3561 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3563 for instance_vm
in instance_vms
:
3564 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3566 dependencies
.append(action
['task_index'])
3567 # TODO: throw exception if count != len(instance_vms)
3568 # TODO: and action shouldn't ever be None
3570 for i
in range(count
):
3572 sfi_uuid
= str(uuid4())
3574 "ingress_interface_id": cp
["ingress_interface_id"],
3575 "egress_interface_id": cp
["egress_interface_id"]
3577 uuid_list
.append(sfi_uuid
)
3580 "related": sfi_uuid
,
3581 "instance_scenario_id": instance_uuid
,
3582 'sce_rsp_hop_id': cp
['uuid'],
3583 'datacenter_id': datacenter_id
,
3584 'datacenter_tenant_id': myvim_thread_id
,
3585 "vim_sfi_id": None, # vim thread will populate
3587 db_instance_sfis
.append(db_sfi
)
3589 "instance_action_id": instance_action_id
,
3590 "task_index": task_index
,
3591 "datacenter_vim_id": myvim_thread_id
,
3593 "status": "SCHEDULED",
3594 "item": "instance_sfis",
3595 "item_id": sfi_uuid
,
3596 "related": sfi_uuid
,
3597 "extra": yaml
.safe_dump({"params": extra_params
, "depends_on": [dependencies
[i
]]},
3598 default_flow_style
=True, width
=256)
3600 sfis_created
.append(task_index
)
3602 db_vim_actions
.append(db_vim_action
)
3604 sf_uuid
= str(uuid4())
3605 uuid_list
.append(sf_uuid
)
3609 "instance_scenario_id": instance_uuid
,
3610 'sce_rsp_hop_id': cp
['uuid'],
3611 'datacenter_id': datacenter_id
,
3612 'datacenter_tenant_id': myvim_thread_id
,
3613 "vim_sf_id": None, # vim thread will populate
3615 db_instance_sfs
.append(db_sf
)
3617 "instance_action_id": instance_action_id
,
3618 "task_index": task_index
,
3619 "datacenter_vim_id": myvim_thread_id
,
3621 "status": "SCHEDULED",
3622 "item": "instance_sfs",
3625 "extra": yaml
.safe_dump({"params": "", "depends_on": sfis_created
},
3626 default_flow_style
=True, width
=256)
3628 sfs_created
.append(task_index
)
3630 db_vim_actions
.append(db_vim_action
)
3631 classifier
= rsp
['classifier']
3633 # TODO the following ~13 lines can be reused for the sfi case
3634 count
= mydb
.get_rows(
3635 SELECT
=('vms.count'),
3636 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_classifiers as c on interfaces.uuid=c.interface_id",
3637 WHERE
={'c.uuid': classifier
['uuid']})[0]['count']
3638 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == classifier
['sce_vnf_id']), None)
3639 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3641 for instance_vm
in instance_vms
:
3642 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3644 dependencies
.append(action
['task_index'])
3645 # TODO: throw exception if count != len(instance_vms)
3646 # TODO: and action shouldn't ever be None
3647 classifications_created
= []
3648 for i
in range(count
):
3649 for match
in classifier
['matches']:
3650 # create classifications
3651 classification_uuid
= str(uuid4())
3652 uuid_list
.append(classification_uuid
)
3653 db_classification
= {
3654 "uuid": classification_uuid
,
3655 "related": classification_uuid
,
3656 "instance_scenario_id": instance_uuid
,
3657 'sce_classifier_match_id': match
['uuid'],
3658 'datacenter_id': datacenter_id
,
3659 'datacenter_tenant_id': myvim_thread_id
,
3660 "vim_classification_id": None, # vim thread will populate
3662 db_instance_classifications
.append(db_classification
)
3663 classification_params
= {
3664 "ip_proto": match
["ip_proto"],
3665 "source_ip": match
["source_ip"],
3666 "destination_ip": match
["destination_ip"],
3667 "source_port": match
["source_port"],
3668 "destination_port": match
["destination_port"],
3669 "logical_source_port": classifier
["interface_id"]
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 instance_wim_net_id
= None
4079 task_depends_on
.append(net2task_id
[sce_vnf
['uuid']][iface
['net_id']])
4080 # skip bridge ifaces not connected to any net
4081 if 'net_id' not in netDict
or netDict
['net_id'] == None:
4083 myVMDict
['networks'].append(netDict
)
4086 # 'instance_vm_id': instance_vm_uuid,
4087 "instance_net_id": instance_net_id
,
4088 "instance_wim_net_id": instance_wim_net_id
,
4089 'interface_id': iface
['uuid'],
4090 # 'vim_interface_id': ,
4091 'type': 'external' if iface
['external_name'] is not None else 'internal',
4092 'model': iface
['model'],
4093 'ip_address': iface
.get('ip_address'),
4094 'mac_address': iface
.get('mac'),
4095 'floating_ip': int(iface
.get('floating-ip', False)),
4096 'port_security': int(iface
.get('port-security', True))
4098 db_vm_ifaces
.append(db_vm_iface
)
4099 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
4100 # print myVMDict['name']
4101 # print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
4102 # print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
4103 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
4105 # We add the RO key to cloud_config if vnf will need ssh access
4106 cloud_config_vm
= cloud_config
4107 if is_management_vm
and params
["instance_parameters"].get("mgmt_keys"):
4108 cloud_config_vm
= unify_cloud_config({"key-pairs": params
["instance_parameters"]["mgmt_keys"]},
4111 if vm
.get("instance_parameters") and "mgmt_keys" in vm
["instance_parameters"]:
4112 if vm
["instance_parameters"]["mgmt_keys"]:
4113 cloud_config_vm
= unify_cloud_config({"key-pairs": vm
["instance_parameters"]["mgmt_keys"]},
4116 cloud_config_vm
= unify_cloud_config(cloud_config_vm
, {"key-pairs": [RO_pub_key
]})
4117 if vm
.get("boot_data"):
4118 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config_vm
)
4120 if myVMDict
.get('availability_zone'):
4121 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
4124 for vm_index
in range(0, vm
.get('count', 1)):
4125 vm_name
= myVMDict
['name'] + "-" + str(vm_index
+1)
4126 task_params
= (vm_name
, myVMDict
['description'], myVMDict
.get('start', None),
4127 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'], cloud_config_vm
,
4128 myVMDict
['disks'], av_index
, vnf_availability_zones
)
4129 # put interface uuid back to scenario[vnfs][vms[[interfaces]
4130 for net
in myVMDict
['networks']:
4132 for iface
in vm
['interfaces']:
4133 if net
["name"] == iface
["internal_name"]:
4134 iface
["vim_id"] = net
["vim_id"]
4136 vm_uuid
= str(uuid4())
4137 uuid_list
.append(vm_uuid
)
4141 'instance_vnf_id': vnf_uuid
,
4142 # TODO delete "vim_vm_id": vm_id,
4143 "vm_id": vm
["uuid"],
4144 "vim_name": vm_name
,
4147 db_instance_vms
.append(db_vm
)
4150 for db_vm_iface
in db_vm_ifaces
:
4151 iface_uuid
= str(uuid4())
4152 uuid_list
.append(iface_uuid
)
4153 db_vm_iface_instance
= {
4155 "instance_vm_id": vm_uuid
4157 db_vm_iface_instance
.update(db_vm_iface
)
4158 if db_vm_iface_instance
.get("ip_address"): # increment ip_address
4159 ip
= db_vm_iface_instance
.get("ip_address")
4164 ip
= ip
[i
:] + str(int(ip
[:i
]) + 1)
4165 db_vm_iface_instance
["ip_address"] = ip
4167 db_vm_iface_instance
["ip_address"] = None
4168 db_instance_interfaces
.append(db_vm_iface_instance
)
4169 myVMDict
['networks'][iface_index
]["uuid"] = iface_uuid
4173 "instance_action_id": instance_action_id
,
4174 "task_index": task_index
,
4175 "datacenter_vim_id": myvim_thread_id
,
4177 "status": "SCHEDULED",
4178 "item": "instance_vms",
4181 "extra": yaml
.safe_dump({"params": task_params
, "depends_on": task_depends_on
},
4182 default_flow_style
=True, width
=256)
4185 db_vim_actions
.append(db_vim_action
)
4186 params_out
["task_index"] = task_index
4187 params_out
["uuid_list"] = uuid_list
4190 def delete_instance(mydb
, tenant_id
, instance_id
):
4191 # print "Checking that the instance_id exists and getting the instance dictionary"
4192 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
4193 # print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
4194 tenant_id
= instanceDict
["tenant_id"]
4197 # We need to retrieve the WIM Actions now, before the instance_scenario is
4198 # deleted. The reason for that is that: ON CASCADE rules will delete the
4199 # instance_wim_nets record in the database
4200 wim_actions
= wim_engine
.delete_actions(instance_scenario_id
=instance_id
)
4203 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
4204 # 1. Delete from Database
4205 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
4207 # 2. delete from VIM
4211 vimthread_affected
= {}
4212 net2vm_dependencies
= {}
4215 instance_action_id
= get_task_id()
4217 db_instance_action
= {
4218 "uuid": instance_action_id
, # same uuid for the instance and the action on create
4219 "tenant_id": tenant_id
,
4220 "instance_id": instance_id
,
4221 "description": "DELETE",
4222 # "number_tasks": 0 # filled bellow
4225 # 2.1 deleting VNFFGs
4226 for sfp
in instanceDict
.get('sfps', ()):
4227 vimthread_affected
[sfp
["datacenter_tenant_id"]] = None
4228 datacenter_key
= (sfp
["datacenter_id"], sfp
["datacenter_tenant_id"])
4229 if datacenter_key
not in myvims
:
4231 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sfp
["datacenter_id"], sfp
["datacenter_tenant_id"])
4232 except NfvoException
as e
:
4233 logger
.error(str(e
))
4235 myvim_threads
[datacenter_key
] = myvim_thread
4236 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sfp
["datacenter_id"],
4237 datacenter_tenant_id
=sfp
["datacenter_tenant_id"])
4239 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfp
["datacenter_id"], sfp
["datacenter_tenant_id"]))
4240 myvims
[datacenter_key
] = None
4242 myvims
[datacenter_key
] = next(iter(vims
.values()))
4243 myvim
= myvims
[datacenter_key
]
4244 myvim_thread
= myvim_threads
[datacenter_key
]
4247 error_msg
+= "\n vim_sfp_id={} cannot be deleted because datacenter={} not found".format(sfp
['vim_sfp_id'], sfp
["datacenter_id"])
4249 extra
= {"params": (sfp
['vim_sfp_id'])}
4251 "instance_action_id": instance_action_id
,
4252 "task_index": task_index
,
4253 "datacenter_vim_id": sfp
["datacenter_tenant_id"],
4255 "status": "SCHEDULED",
4256 "item": "instance_sfps",
4257 "item_id": sfp
["uuid"],
4258 "related": sfp
["related"],
4259 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4262 db_vim_actions
.append(db_vim_action
)
4264 for classification
in instanceDict
['classifications']:
4265 vimthread_affected
[classification
["datacenter_tenant_id"]] = None
4266 datacenter_key
= (classification
["datacenter_id"], classification
["datacenter_tenant_id"])
4267 if datacenter_key
not in myvims
:
4269 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, classification
["datacenter_id"], classification
["datacenter_tenant_id"])
4270 except NfvoException
as e
:
4271 logger
.error(str(e
))
4273 myvim_threads
[datacenter_key
] = myvim_thread
4274 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=classification
["datacenter_id"],
4275 datacenter_tenant_id
=classification
["datacenter_tenant_id"])
4277 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(classification
["datacenter_id"],
4278 classification
["datacenter_tenant_id"]))
4279 myvims
[datacenter_key
] = None
4281 myvims
[datacenter_key
] = next(iter(vims
.values()))
4282 myvim
= myvims
[datacenter_key
]
4283 myvim_thread
= myvim_threads
[datacenter_key
]
4286 error_msg
+= "\n vim_classification_id={} cannot be deleted because datacenter={} not found".format(classification
['vim_classification_id'],
4287 classification
["datacenter_id"])
4289 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfps"]
4290 extra
= {"params": (classification
['vim_classification_id']), "depends_on": depends_on
}
4292 "instance_action_id": instance_action_id
,
4293 "task_index": task_index
,
4294 "datacenter_vim_id": classification
["datacenter_tenant_id"],
4296 "status": "SCHEDULED",
4297 "item": "instance_classifications",
4298 "item_id": classification
["uuid"],
4299 "related": classification
["related"],
4300 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4303 db_vim_actions
.append(db_vim_action
)
4305 for sf
in instanceDict
.get('sfs', ()):
4306 vimthread_affected
[sf
["datacenter_tenant_id"]] = None
4307 datacenter_key
= (sf
["datacenter_id"], sf
["datacenter_tenant_id"])
4308 if datacenter_key
not in myvims
:
4310 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sf
["datacenter_id"], sf
["datacenter_tenant_id"])
4311 except NfvoException
as e
:
4312 logger
.error(str(e
))
4314 myvim_threads
[datacenter_key
] = myvim_thread
4315 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sf
["datacenter_id"],
4316 datacenter_tenant_id
=sf
["datacenter_tenant_id"])
4318 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sf
["datacenter_id"], sf
["datacenter_tenant_id"]))
4319 myvims
[datacenter_key
] = None
4321 myvims
[datacenter_key
] = next(iter(vims
.values()))
4322 myvim
= myvims
[datacenter_key
]
4323 myvim_thread
= myvim_threads
[datacenter_key
]
4326 error_msg
+= "\n vim_sf_id={} cannot be deleted because datacenter={} not found".format(sf
['vim_sf_id'], sf
["datacenter_id"])
4328 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfps"]
4329 extra
= {"params": (sf
['vim_sf_id']), "depends_on": depends_on
}
4331 "instance_action_id": instance_action_id
,
4332 "task_index": task_index
,
4333 "datacenter_vim_id": sf
["datacenter_tenant_id"],
4335 "status": "SCHEDULED",
4336 "item": "instance_sfs",
4337 "item_id": sf
["uuid"],
4338 "related": sf
["related"],
4339 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4342 db_vim_actions
.append(db_vim_action
)
4344 for sfi
in instanceDict
.get('sfis', ()):
4345 vimthread_affected
[sfi
["datacenter_tenant_id"]] = None
4346 datacenter_key
= (sfi
["datacenter_id"], sfi
["datacenter_tenant_id"])
4347 if datacenter_key
not in myvims
:
4349 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sfi
["datacenter_id"], sfi
["datacenter_tenant_id"])
4350 except NfvoException
as e
:
4351 logger
.error(str(e
))
4353 myvim_threads
[datacenter_key
] = myvim_thread
4354 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sfi
["datacenter_id"],
4355 datacenter_tenant_id
=sfi
["datacenter_tenant_id"])
4357 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfi
["datacenter_id"], sfi
["datacenter_tenant_id"]))
4358 myvims
[datacenter_key
] = None
4360 myvims
[datacenter_key
] = next(iter(vims
.values()))
4361 myvim
= myvims
[datacenter_key
]
4362 myvim_thread
= myvim_threads
[datacenter_key
]
4365 error_msg
+= "\n vim_sfi_id={} cannot be deleted because datacenter={} not found".format(sfi
['vim_sfi_id'], sfi
["datacenter_id"])
4367 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfs"]
4368 extra
= {"params": (sfi
['vim_sfi_id']), "depends_on": depends_on
}
4370 "instance_action_id": instance_action_id
,
4371 "task_index": task_index
,
4372 "datacenter_vim_id": sfi
["datacenter_tenant_id"],
4374 "status": "SCHEDULED",
4375 "item": "instance_sfis",
4376 "item_id": sfi
["uuid"],
4377 "related": sfi
["related"],
4378 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4381 db_vim_actions
.append(db_vim_action
)
4385 for sce_vnf
in instanceDict
.get('vnfs', ()):
4386 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
4387 vimthread_affected
[sce_vnf
["datacenter_tenant_id"]] = None
4388 if datacenter_key
not in myvims
:
4390 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
4391 except NfvoException
as e
:
4392 logger
.error(str(e
))
4394 myvim_threads
[datacenter_key
] = myvim_thread
4395 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
4396 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
4398 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
4399 sce_vnf
["datacenter_tenant_id"]))
4400 myvims
[datacenter_key
] = None
4402 myvims
[datacenter_key
] = next(iter(vims
.values()))
4403 myvim
= myvims
[datacenter_key
]
4404 myvim_thread
= myvim_threads
[datacenter_key
]
4406 for vm
in sce_vnf
['vms']:
4408 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
4410 sfi_dependencies
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfis"]
4412 "instance_action_id": instance_action_id
,
4413 "task_index": task_index
,
4414 "datacenter_vim_id": sce_vnf
["datacenter_tenant_id"],
4416 "status": "SCHEDULED",
4417 "item": "instance_vms",
4418 "item_id": vm
["uuid"],
4419 "related": vm
["related"],
4420 "extra": yaml
.safe_dump({"params": vm
["interfaces"], "depends_on": sfi_dependencies
},
4421 default_flow_style
=True, width
=256)
4423 db_vim_actions
.append(db_vim_action
)
4424 for interface
in vm
["interfaces"]:
4425 if not interface
.get("instance_net_id"):
4427 if interface
["instance_net_id"] not in net2vm_dependencies
:
4428 net2vm_dependencies
[interface
["instance_net_id"]] = []
4429 net2vm_dependencies
[interface
["instance_net_id"]].append(task_index
)
4434 for net
in instanceDict
['nets']:
4435 vimthread_affected
[net
["datacenter_tenant_id"]] = None
4436 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
4437 if datacenter_key
not in myvims
:
4439 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, net
["datacenter_id"], net
["datacenter_tenant_id"])
4440 except NfvoException
as e
:
4441 logger
.error(str(e
))
4443 myvim_threads
[datacenter_key
] = myvim_thread
4444 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
4445 datacenter_tenant_id
=net
["datacenter_tenant_id"])
4447 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
4448 myvims
[datacenter_key
] = None
4450 myvims
[datacenter_key
] = next(iter(vims
.values()))
4451 myvim
= myvims
[datacenter_key
]
4452 myvim_thread
= myvim_threads
[datacenter_key
]
4455 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
4457 extra
= {"params": (net
['vim_net_id'], net
['sdn_net_id'])}
4458 if net2vm_dependencies
.get(net
["uuid"]):
4459 extra
["depends_on"] = net2vm_dependencies
[net
["uuid"]]
4460 sfi_dependencies
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfis"]
4461 if len(sfi_dependencies
) > 0:
4462 if "depends_on" in extra
:
4463 extra
["depends_on"] += sfi_dependencies
4465 extra
["depends_on"] = sfi_dependencies
4467 "instance_action_id": instance_action_id
,
4468 "task_index": task_index
,
4469 "datacenter_vim_id": net
["datacenter_tenant_id"],
4471 "status": "SCHEDULED",
4472 "item": "instance_nets",
4473 "item_id": net
["uuid"],
4474 "related": net
["related"],
4475 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4478 db_vim_actions
.append(db_vim_action
)
4479 for sdn_net
in instanceDict
['sdn_nets']:
4480 if not sdn_net
["sdn"]:
4484 "instance_action_id": instance_action_id
,
4485 "task_index": task_index
,
4486 "wim_account_id": sdn_net
["wim_account_id"],
4488 "status": "SCHEDULED",
4489 "item": "instance_wim_nets",
4490 "item_id": sdn_net
["uuid"],
4491 "related": sdn_net
["related"],
4492 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4495 db_vim_actions
.append(db_vim_action
)
4497 db_instance_action
["number_tasks"] = task_index
4500 wim_actions
, db_instance_action
= (
4501 wim_engine
.incorporate_actions(wim_actions
, db_instance_action
))
4505 {"instance_actions": db_instance_action
},
4506 {"vim_wim_actions": db_vim_actions
+ wim_actions
}
4509 logger
.debug("delete_instance done DB tables: %s",
4510 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
4511 mydb
.new_rows(db_tables
, ())
4512 for myvim_thread_id
in vimthread_affected
.keys():
4513 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
4515 wim_engine
.dispatch(wim_actions
)
4517 if len(error_msg
) > 0:
4518 return 'action_id={} instance {} deleted but some elements could not be deleted, or already deleted '\
4519 '(error: 404) from VIM: {}'.format(instance_action_id
, message
, error_msg
)
4521 return "action_id={} instance {} deleted".format(instance_action_id
, message
)
4523 def get_instance_id(mydb
, tenant_id
, instance_id
):
4525 #check valid tenant_id
4526 check_tenant(mydb
, tenant_id
)
4529 instance_dict
= mydb
.get_instance_scenario(instance_id
, tenant_id
, verbose
=True)
4531 # for net in instance_dict["nets"]:
4532 # if net.get("sdn_net_id"):
4533 # net_sdn = ovim.show_network(net["sdn_net_id"])
4534 # net["sdn_info"] = {
4535 # "admin_state_up": net_sdn.get("admin_state_up"),
4536 # "flows": net_sdn.get("flows"),
4537 # "last_error": net_sdn.get("last_error"),
4538 # "ports": net_sdn.get("ports"),
4539 # "type": net_sdn.get("type"),
4540 # "status": net_sdn.get("status"),
4541 # "vlan": net_sdn.get("vlan"),
4543 return instance_dict
4545 @deprecated("Instance is automatically refreshed by vim_threads")
4546 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
4547 '''Refreshes a scenario instance. It modifies instanceDict'''
4549 - 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
4552 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
4553 # #print "nfvo.refresh_instance begins"
4554 # #print json.dumps(instanceDict, indent=4)
4556 # #print "Getting the VIM URL and the VIM tenant_id"
4559 # # 1. Getting VIM vm and net list
4560 # vms_updated = [] #List of VM instance uuids in openmano that were updated
4563 # for sce_vnf in instanceDict['vnfs']:
4564 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
4565 # if datacenter_key not in vm_list:
4566 # vm_list[datacenter_key] = []
4567 # if datacenter_key not in myvims:
4568 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
4569 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
4570 # if len(vims) == 0:
4571 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
4572 # myvims[datacenter_key] = None
4574 # myvims[datacenter_key] = next(iter(vims.values()))
4575 # for vm in sce_vnf['vms']:
4576 # vm_list[datacenter_key].append(vm['vim_vm_id'])
4577 # vms_notupdated.append(vm["uuid"])
4579 # nets_updated = [] #List of VM instance uuids in openmano that were updated
4580 # nets_notupdated=[]
4582 # for net in instanceDict['nets']:
4583 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
4584 # if datacenter_key not in net_list:
4585 # net_list[datacenter_key] = []
4586 # if datacenter_key not in myvims:
4587 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
4588 # datacenter_tenant_id=net["datacenter_tenant_id"])
4589 # if len(vims) == 0:
4590 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
4591 # myvims[datacenter_key] = None
4593 # myvims[datacenter_key] = next(iter(vims.values()))
4595 # net_list[datacenter_key].append(net['vim_net_id'])
4596 # nets_notupdated.append(net["uuid"])
4598 # # 1. Getting the status of all VMs
4600 # for datacenter_key in myvims:
4601 # if not vm_list.get(datacenter_key):
4605 # if not myvims[datacenter_key]:
4606 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
4609 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
4611 # except vimconn.vimconnException as e:
4612 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
4613 # failed_message = str(e)
4615 # for vm in vm_list[datacenter_key]:
4616 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
4618 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
4619 # for sce_vnf in instanceDict['vnfs']:
4620 # for vm in sce_vnf['vms']:
4621 # vm_id = vm['vim_vm_id']
4622 # interfaces = vm_dict[vm_id].pop('interfaces', [])
4623 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
4624 # has_mgmt_iface = False
4625 # for iface in vm["interfaces"]:
4626 # if iface["type"]=="mgmt":
4627 # has_mgmt_iface = True
4628 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
4629 # vm_dict[vm_id]['status'] = "ACTIVE"
4630 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
4631 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
4632 # 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'):
4633 # vm['status'] = vm_dict[vm_id]['status']
4634 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
4635 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
4636 # # 2.1. Update in openmano DB the VMs whose status changed
4638 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
4639 # vms_notupdated.remove(vm["uuid"])
4641 # vms_updated.append(vm["uuid"])
4642 # except db_base_Exception as e:
4643 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
4644 # # 2.2. Update in openmano DB the interface VMs
4645 # for interface in interfaces:
4646 # #translate from vim_net_id to instance_net_id
4647 # network_id_list=[]
4648 # for net in instanceDict['nets']:
4649 # if net["vim_net_id"] == interface["vim_net_id"]:
4650 # network_id_list.append(net["uuid"])
4651 # if not network_id_list:
4653 # del interface["vim_net_id"]
4655 # for network_id in network_id_list:
4656 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
4657 # except db_base_Exception as e:
4658 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
4660 # # 3. Getting the status of all nets
4662 # for datacenter_key in myvims:
4663 # if not net_list.get(datacenter_key):
4666 # failed_message = ""
4667 # if not myvims[datacenter_key]:
4668 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
4671 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
4673 # except vimconn.vimconnException as e:
4674 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
4675 # failed_message = str(e)
4677 # for net in net_list[datacenter_key]:
4678 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
4680 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
4681 # # TODO: update nets inside a vnf
4682 # for net in instanceDict['nets']:
4683 # net_id = net['vim_net_id']
4684 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
4685 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
4686 # 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'):
4687 # net['status'] = net_dict[net_id]['status']
4688 # net['error_msg'] = net_dict[net_id].get('error_msg')
4689 # net['vim_info'] = net_dict[net_id].get('vim_info')
4690 # # 5.1. Update in openmano DB the nets whose status changed
4692 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
4693 # nets_notupdated.remove(net["uuid"])
4695 # nets_updated.append(net["uuid"])
4696 # except db_base_Exception as e:
4697 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
4699 # # Returns appropriate output
4700 # #print "nfvo.refresh_instance finishes"
4701 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
4702 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
4703 instance_id
= instanceDict
['uuid']
4704 # if len(vms_notupdated)+len(nets_notupdated)>0:
4705 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
4706 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
4708 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
4710 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
4711 #print "Checking that the instance_id exists and getting the instance dictionary"
4712 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
4713 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
4715 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
4716 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
4718 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), httperrors
.Not_Found
)
4719 myvim
= next(iter(vims
.values()))
4724 myvim_threads_id
= {}
4725 if action_dict
.get("vdu-scaling"):
4726 db_instance_vms
= []
4728 db_instance_interfaces
= []
4729 instance_action_id
= get_task_id()
4730 db_instance_action
= {
4731 "uuid": instance_action_id
, # same uuid for the instance and the action on create
4732 "tenant_id": nfvo_tenant
,
4733 "instance_id": instance_id
,
4734 "description": "SCALE",
4736 vm_result
["instance_action_id"] = instance_action_id
4737 vm_result
["created"] = []
4738 vm_result
["deleted"] = []
4740 for vdu
in action_dict
["vdu-scaling"]:
4741 vdu_id
= vdu
.get("vdu-id")
4742 osm_vdu_id
= vdu
.get("osm_vdu_id")
4743 member_vnf_index
= vdu
.get("member-vnf-index")
4744 vdu_count
= vdu
.get("count", 1)
4746 target_vms
= mydb
.get_rows(
4747 FROM
="instance_vms as vms join instance_vnfs as vnfs on vms.instance_vnf_id=vnfs.uuid",
4748 WHERE
={"vms.uuid": vdu_id
},
4749 ORDER_BY
="vms.created_at"
4752 raise NfvoException("Cannot find the vdu with id {}".format(vdu_id
), httperrors
.Not_Found
)
4754 if not osm_vdu_id
and not member_vnf_index
:
4755 raise NfvoException("Invalid input vdu parameters. Must supply either 'vdu-id' of 'osm_vdu_id','member-vnf-index'")
4756 target_vms
= mydb
.get_rows(
4757 # SELECT=("ivms.uuid", "ivnfs.datacenter_id", "ivnfs.datacenter_tenant_id"),
4758 FROM
="instance_vms as ivms join instance_vnfs as ivnfs on ivms.instance_vnf_id=ivnfs.uuid"\
4759 " join sce_vnfs as svnfs on ivnfs.sce_vnf_id=svnfs.uuid"\
4760 " join vms on ivms.vm_id=vms.uuid",
4761 WHERE
={"vms.osm_id": osm_vdu_id
, "svnfs.member_vnf_index": member_vnf_index
,
4762 "ivnfs.instance_scenario_id": instance_id
},
4763 ORDER_BY
="ivms.created_at"
4766 raise NfvoException("Cannot find the vdu with osm_vdu_id {} and member-vnf-index {}".format(osm_vdu_id
, member_vnf_index
), httperrors
.Not_Found
)
4767 vdu_id
= target_vms
[-1]["uuid"]
4768 target_vm
= target_vms
[-1]
4769 datacenter
= target_vm
["datacenter_id"]
4770 myvim_threads_id
[datacenter
], _
= get_vim_thread(mydb
, nfvo_tenant
, datacenter
)
4772 if vdu
["type"] == "delete":
4773 for index
in range(0, vdu_count
):
4774 target_vm
= target_vms
[-1-index
]
4775 vdu_id
= target_vm
["uuid"]
4777 vm_interfaces
= None
4778 for sce_vnf
in instanceDict
['vnfs']:
4779 for vm
in sce_vnf
['vms']:
4780 if vm
["uuid"] == vdu_id
:
4781 # TODO revise this should not be vm["uuid"] instance_vms["vm_id"]
4782 vm_interfaces
= vm
["interfaces"]
4786 "instance_action_id": instance_action_id
,
4787 "task_index": task_index
,
4788 "datacenter_vim_id": target_vm
["datacenter_tenant_id"],
4790 "status": "SCHEDULED",
4791 "item": "instance_vms",
4793 "related": target_vm
["related"],
4794 "extra": yaml
.safe_dump({"params": vm_interfaces
},
4795 default_flow_style
=True, width
=256)
4798 db_vim_actions
.append(db_vim_action
)
4799 vm_result
["deleted"].append(vdu_id
)
4800 # delete from database
4801 db_instance_vms
.append({"TO-DELETE": vdu_id
})
4803 else: # vdu["type"] == "create":
4805 where
= {"item": "instance_vms", "item_id": target_vm
["uuid"], "action": "CREATE"}
4807 vim_action_to_clone
= mydb
.get_rows(FROM
="vim_wim_actions", WHERE
=where
)
4808 if not vim_action_to_clone
:
4809 raise NfvoException("Cannot find the vim_action at database with {}".format(where
), httperrors
.Internal_Server_Error
)
4810 vim_action_to_clone
= vim_action_to_clone
[0]
4811 extra
= yaml
.safe_load(vim_action_to_clone
["extra"])
4813 # generate a new depends_on. Convert format TASK-Y into new format TASK-ACTION-XXXX.XXXX.Y
4814 # TODO do the same for flavor and image when available
4815 task_depends_on
= []
4816 task_params
= extra
["params"]
4817 task_params_networks
= deepcopy(task_params
[5])
4818 for iface
in task_params
[5]:
4819 if iface
["net_id"].startswith("TASK-"):
4820 if "." not in iface
["net_id"]:
4821 task_depends_on
.append("{}.{}".format(vim_action_to_clone
["instance_action_id"],
4822 iface
["net_id"][5:]))
4823 iface
["net_id"] = "TASK-{}.{}".format(vim_action_to_clone
["instance_action_id"],
4824 iface
["net_id"][5:])
4826 task_depends_on
.append(iface
["net_id"][5:])
4827 if "mac_address" in iface
:
4828 del iface
["mac_address"]
4830 vm_ifaces_to_clone
= mydb
.get_rows(FROM
="instance_interfaces", WHERE
={"instance_vm_id": target_vm
["uuid"]})
4831 for index
in range(0, vdu_count
):
4832 vm_uuid
= str(uuid4())
4833 vm_name
= target_vm
.get('vim_name')
4835 suffix
= vm_name
.rfind("-")
4836 vm_name
= vm_name
[:suffix
+1] + str(index
+ 1 + int(vm_name
[suffix
+1:]))
4842 'instance_vnf_id': target_vm
['instance_vnf_id'],
4843 'vm_id': target_vm
['vm_id'],
4844 'vim_name': vm_name
,
4846 db_instance_vms
.append(db_instance_vm
)
4848 for vm_iface
in vm_ifaces_to_clone
:
4849 iface_uuid
= str(uuid4())
4850 iface2iface
[vm_iface
["uuid"]] = iface_uuid
4853 'instance_vm_id': vm_uuid
,
4854 "instance_net_id": vm_iface
["instance_net_id"],
4855 'interface_id': vm_iface
['interface_id'],
4856 'type': vm_iface
['type'],
4857 'floating_ip': vm_iface
['floating_ip'],
4858 'port_security': vm_iface
['port_security']
4860 db_instance_interfaces
.append(db_vm_iface
)
4861 task_params_copy
= deepcopy(task_params
)
4862 for iface
in task_params_copy
[5]:
4863 iface
["uuid"] = iface2iface
[iface
["uuid"]]
4864 # increment ip_address
4865 if "ip_address" in iface
:
4866 ip
= iface
.get("ip_address")
4871 ip
= ip
[i
:] + str(int(ip
[:i
]) + 1)
4872 iface
["ip_address"] = ip
4874 iface
["ip_address"] = None
4876 task_params_copy
[0] = vm_name
4878 "instance_action_id": instance_action_id
,
4879 "task_index": task_index
,
4880 "datacenter_vim_id": vim_action_to_clone
["datacenter_vim_id"],
4882 "status": "SCHEDULED",
4883 "item": "instance_vms",
4888 # TODO examinar parametros, quitar MAC o incrementar. Incrementar IP y colocar las dependencias con ACTION-asdfasd.
4891 "extra": yaml
.safe_dump({"params": task_params_copy
, "depends_on": task_depends_on
}, default_flow_style
=True, width
=256)
4894 db_vim_actions
.append(db_vim_action
)
4895 vm_result
["created"].append(vm_uuid
)
4897 db_instance_action
["number_tasks"] = task_index
4899 {"instance_vms": db_instance_vms
},
4900 {"instance_interfaces": db_instance_interfaces
},
4901 {"instance_actions": db_instance_action
},
4903 # {"instance_sfis": db_instance_sfis},
4904 # {"instance_sfs": db_instance_sfs},
4905 # {"instance_classifications": db_instance_classifications},
4906 # {"instance_sfps": db_instance_sfps},
4907 {"vim_wim_actions": db_vim_actions
}
4909 logger
.debug("create_vdu done DB tables: %s",
4910 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
4911 mydb
.new_rows(db_tables
, [])
4912 for myvim_thread
in myvim_threads_id
.values():
4913 vim_threads
["running"][myvim_thread
].insert_task(db_vim_actions
)
4917 input_vnfs
= action_dict
.pop("vnfs", [])
4918 input_vms
= action_dict
.pop("vms", [])
4919 action_over_all
= True if not input_vnfs
and not input_vms
else False
4920 for sce_vnf
in instanceDict
['vnfs']:
4921 for vm
in sce_vnf
['vms']:
4922 if not action_over_all
and sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
4923 sce_vnf
['member_vnf_index'] not in input_vnfs
and \
4924 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
and \
4925 sce_vnf
['member_vnf_index'] + "-" + vm
['vdu_osm_id'] not in input_vms
: # TODO conside vm_count_index
4928 if "add_public_key" in action_dict
:
4929 if sce_vnf
.get('mgmt_access'):
4930 mgmt_access
= yaml
.load(sce_vnf
['mgmt_access'], Loader
=yaml
.Loader
)
4931 if not input_vms
and mgmt_access
.get("vdu-id") != vm
['vdu_osm_id']:
4933 default_user
= mgmt_access
.get("default-user")
4934 password
= mgmt_access
.get("password")
4935 if mgmt_access
.get(vm
['vdu_osm_id']):
4936 default_user
= mgmt_access
[vm
['vdu_osm_id']].get("default-user", default_user
)
4937 password
= mgmt_access
[vm
['vdu_osm_id']].get("password", password
)
4939 tenant
= mydb
.get_rows_by_id('nfvo_tenants', nfvo_tenant
)
4941 if 'ip_address' in vm
:
4942 mgmt_ip
= vm
['ip_address'].split(';')
4943 priv_RO_key
= decrypt_key(tenant
[0]['encrypted_RO_priv_key'], tenant
[0]['uuid'])
4944 data
= myvim
.inject_user_key(mgmt_ip
[0], action_dict
.get('user', default_user
),
4945 action_dict
['add_public_key'],
4946 password
=password
, ro_key
=priv_RO_key
)
4947 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4948 "description": "Public key injected",
4952 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4953 httperrors
.Internal_Server_Error
)
4955 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4956 httperrors
.Internal_Server_Error
)
4958 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
4959 if "console" in action_dict
:
4960 if not global_config
["http_console_proxy"]:
4961 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4962 "description": "{protocol}//{ip}:{port}/{suffix}".format(
4963 protocol
=data
["protocol"],
4964 ip
= data
["server"],
4965 port
= data
["port"],
4966 suffix
= data
["suffix"]),
4970 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
4971 vm_result
[ vm
['uuid'] ] = {"vim_result": -httperrors
.Unauthorized
,
4972 "description": "this console is only reachable by local interface",
4977 #print "console data", data
4979 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
4980 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4981 "description": "{protocol}//{ip}:{port}/{suffix}".format(
4982 protocol
=data
["protocol"],
4983 ip
= global_config
["http_console_host"],
4984 port
= console_thread
.port
,
4985 suffix
= data
["suffix"]),
4989 except NfvoException
as e
:
4990 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
4994 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
4996 except vimconn
.vimconnException
as e
:
4997 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
5000 if vm_ok
==0: #all goes wrong
5005 def instance_action_get(mydb
, nfvo_tenant
, instance_id
, action_id
):
5007 if nfvo_tenant
and nfvo_tenant
!= "any":
5008 filter["tenant_id"] = nfvo_tenant
5009 if instance_id
and instance_id
!= "any":
5010 filter["instance_id"] = instance_id
5012 filter["uuid"] = action_id
5013 rows
= mydb
.get_rows(FROM
="instance_actions", WHERE
=filter)
5016 raise NfvoException("Not found any action with this criteria", httperrors
.Not_Found
)
5017 vim_wim_actions
= mydb
.get_rows(FROM
="vim_wim_actions", WHERE
={"instance_action_id": action_id
})
5018 rows
[0]["vim_wim_actions"] = vim_wim_actions
5019 # for backward compatibility set vim_actions = vim_wim_actions
5020 rows
[0]["vim_actions"] = vim_wim_actions
5021 return {"actions": rows
}
5024 def create_or_use_console_proxy_thread(console_server
, console_port
):
5025 #look for a non-used port
5026 console_thread_key
= console_server
+ ":" + str(console_port
)
5027 if console_thread_key
in global_config
["console_thread"]:
5028 #global_config["console_thread"][console_thread_key].start_timeout()
5029 return global_config
["console_thread"][console_thread_key
]
5031 for port
in global_config
["console_port_iterator"]():
5032 #print "create_or_use_console_proxy_thread() port:", port
5033 if port
in global_config
["console_ports"]:
5036 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
5038 global_config
["console_thread"][console_thread_key
] = clithread
5039 global_config
["console_ports"][port
] = console_thread_key
5041 except cli
.ConsoleProxyExceptionPortUsed
as e
:
5042 #port used, try with onoher
5044 except cli
.ConsoleProxyException
as e
:
5045 raise NfvoException(str(e
), httperrors
.Bad_Request
)
5046 raise NfvoException("Not found any free 'http_console_ports'", httperrors
.Conflict
)
5049 def check_tenant(mydb
, tenant_id
):
5050 '''check that tenant exists at database'''
5051 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
5053 raise NfvoException("tenant '{}' not found".format(tenant_id
), httperrors
.Not_Found
)
5056 def new_tenant(mydb
, tenant_dict
):
5058 tenant_uuid
= str(uuid4())
5059 tenant_dict
['uuid'] = tenant_uuid
5061 pub_key
, priv_key
= create_RO_keypair(tenant_uuid
)
5062 tenant_dict
['RO_pub_key'] = pub_key
5063 tenant_dict
['encrypted_RO_priv_key'] = priv_key
5064 mydb
.new_row("nfvo_tenants", tenant_dict
, confidential_data
=True)
5065 except db_base_Exception
as e
:
5066 raise NfvoException("Error creating the new tenant: {} ".format(tenant_dict
['name']) + str(e
), e
.http_code
)
5069 def delete_tenant(mydb
, tenant
):
5070 #get nfvo_tenant info
5072 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
5073 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
5074 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
5077 def new_datacenter(mydb
, datacenter_descriptor
):
5078 sdn_port_mapping
= None
5079 if "config" in datacenter_descriptor
:
5080 sdn_port_mapping
= datacenter_descriptor
["config"].pop("sdn-port-mapping", None)
5081 datacenter_descriptor
["config"] = yaml
.safe_dump(datacenter_descriptor
["config"], default_flow_style
=True,
5083 # Check that datacenter-type is correct
5084 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
5085 # module_info = None
5088 plugin_name
= "rovim_" + datacenter_type
5089 if plugin_name
not in plugins
:
5090 _load_plugin(plugin_name
, type="vim")
5092 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True, confidential_data
=True)
5093 if sdn_port_mapping
:
5095 datacenter_sdn_port_mapping_set(mydb
, None, datacenter_id
, sdn_port_mapping
)
5096 except Exception as e
:
5097 mydb
.delete_row_by_id("datacenters", datacenter_id
) # Rollback
5099 return datacenter_id
5102 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
5103 # obtain data, check that only one exist
5104 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
5107 datacenter_id
= datacenter
['uuid']
5108 where
= {'uuid': datacenter
['uuid']}
5109 remove_port_mapping
= False
5110 new_sdn_port_mapping
= None
5111 if "config" in datacenter_descriptor
:
5112 if datacenter_descriptor
['config'] != None:
5114 new_config_dict
= datacenter_descriptor
["config"]
5115 if "sdn-port-mapping" in new_config_dict
:
5116 remove_port_mapping
= True
5117 new_sdn_port_mapping
= new_config_dict
.pop("sdn-port-mapping")
5118 # delete null fields
5120 for k
in new_config_dict
:
5121 if new_config_dict
[k
] is None:
5123 if k
== 'sdn-controller':
5124 remove_port_mapping
= True
5126 config_text
= datacenter
.get("config")
5129 config_dict
= yaml
.load(config_text
, Loader
=yaml
.Loader
)
5130 config_dict
.update(new_config_dict
)
5131 # delete null fields
5134 except Exception as e
:
5135 raise NfvoException("Bad format at datacenter:config " + str(e
), httperrors
.Bad_Request
)
5137 datacenter_descriptor
["config"] = yaml
.safe_dump(config_dict
, default_flow_style
=True, width
=256)
5139 datacenter_descriptor
["config"] = None
5140 if remove_port_mapping
:
5142 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_id
)
5143 except ovimException
as e
:
5144 raise NfvoException("Error deleting datacenter-port-mapping " + str(e
), httperrors
.Conflict
)
5146 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
5147 if new_sdn_port_mapping
:
5149 datacenter_sdn_port_mapping_set(mydb
, None, datacenter_id
, new_sdn_port_mapping
)
5150 except ovimException
as e
:
5152 mydb
.update_rows('datacenters', datacenter
, where
)
5153 raise NfvoException("Error adding datacenter-port-mapping " + str(e
), httperrors
.Conflict
)
5154 return datacenter_id
5157 def delete_datacenter(mydb
, datacenter
):
5158 #get nfvo_tenant info
5159 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
5160 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
5162 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_dict
['uuid'])
5163 except ovimException
as e
:
5164 raise NfvoException("Error deleting datacenter-port-mapping " + str(e
))
5165 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
5168 def create_vim_account(mydb
, nfvo_tenant
, datacenter_id
, name
=None, vim_id
=None, vim_tenant
=None, vim_tenant_name
=None,
5169 vim_username
=None, vim_password
=None, config
=None):
5170 # get datacenter info
5172 if not datacenter_id
:
5174 raise NfvoException("You must provide 'vim_id", http_code
=httperrors
.Bad_Request
)
5175 datacenter_id
= vim_id
5176 datacenter_id
, datacenter_name
= get_datacenter_uuid(mydb
, None, datacenter_id
)
5178 create_vim_tenant
= True if not vim_tenant
and not vim_tenant_name
else False
5180 # get nfvo_tenant info
5181 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
5182 if vim_tenant_name
==None:
5183 vim_tenant_name
=tenant_dict
['name']
5185 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
5186 # #check that this association does not exist before
5187 # tenants_datacenters = mydb.get_rows(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict)
5188 # if len(tenants_datacenters)>0:
5189 # raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id, tenant_dict['uuid']), httperrors.Conflict)
5191 vim_tenant_id_exist_atdb
=False
5192 if not create_vim_tenant
:
5193 where_
={"datacenter_id": datacenter_id
}
5194 if vim_tenant
!=None:
5195 where_
["vim_tenant_id"] = vim_tenant
5196 if vim_tenant_name
!=None:
5197 where_
["vim_tenant_name"] = vim_tenant_name
5198 #check if vim_tenant_id is already at database
5199 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
5200 if len(datacenter_tenants_dict
)>=1:
5201 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
5202 vim_tenant_id_exist_atdb
=True
5203 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
5205 datacenter_tenants_dict
= {}
5206 #insert at table datacenter_tenants
5207 else: #if vim_tenant==None:
5208 #create tenant at VIM if not provided
5210 _
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
, vim_user
=vim_username
,
5211 vim_passwd
=vim_password
)
5212 datacenter_name
= myvim
["name"]
5213 vim_tenant
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
5214 except vimconn
.vimconnException
as e
:
5215 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), httperrors
.Internal_Server_Error
)
5216 datacenter_tenants_dict
= {}
5217 datacenter_tenants_dict
["created"]="true"
5219 #fill datacenter_tenants table
5220 if not vim_tenant_id_exist_atdb
:
5221 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant
5222 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
5223 datacenter_tenants_dict
["user"] = vim_username
5224 datacenter_tenants_dict
["passwd"] = vim_password
5225 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
5227 datacenter_tenants_dict
["name"] = name
5229 datacenter_tenants_dict
["name"] = datacenter_name
5231 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
5232 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True, confidential_data
=True)
5233 datacenter_tenants_dict
["uuid"] = id_
5235 #fill tenants_datacenters table
5236 datacenter_tenant_id
= datacenter_tenants_dict
["uuid"]
5237 tenants_datacenter_dict
["datacenter_tenant_id"] = datacenter_tenant_id
5238 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
5241 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
5242 new_thread
= vim_thread(task_lock
, plugins
, thread_name
, None, datacenter_tenant_id
, db
=db
)
5244 thread_id
= datacenter_tenants_dict
["uuid"]
5245 vim_threads
["running"][thread_id
] = new_thread
5247 except vimconn
.vimconnException
as e
:
5248 raise NfvoException(str(e
), httperrors
.Bad_Request
)
5251 def edit_vim_account(mydb
, nfvo_tenant
, datacenter_tenant_id
, datacenter_id
=None, name
=None, vim_tenant
=None,
5252 vim_tenant_name
=None, vim_username
=None, vim_password
=None, config
=None):
5254 # get vim_account; check is valid for this tenant
5255 from_
= "datacenter_tenants as dt JOIN tenants_datacenters as td ON dt.uuid=td.datacenter_tenant_id"
5256 where_
= {"td.nfvo_tenant_id": nfvo_tenant
}
5257 if datacenter_tenant_id
:
5258 where_
["dt.uuid"] = datacenter_tenant_id
5260 where_
["dt.datacenter_id"] = datacenter_id
5261 vim_accounts
= mydb
.get_rows(SELECT
="dt.uuid as uuid, config", FROM
=from_
, WHERE
=where_
)
5262 if not vim_accounts
:
5263 raise NfvoException("vim_account not found for this tenant", http_code
=httperrors
.Not_Found
)
5264 elif len(vim_accounts
) > 1:
5265 raise NfvoException("found more than one vim_account for this tenant", http_code
=httperrors
.Conflict
)
5266 datacenter_tenant_id
= vim_accounts
[0]["uuid"]
5267 original_config
= vim_accounts
[0]["config"]
5271 original_config_dict
= yaml
.load(original_config
, Loader
=yaml
.Loader
)
5272 original_config_dict
.update(config
)
5273 update
["config"] = yaml
.safe_dump(original_config_dict
, default_flow_style
=True, width
=256)
5275 update_
['name'] = name
5277 update_
['vim_tenant_id'] = vim_tenant
5279 update_
['vim_tenant_name'] = vim_tenant_name
5281 update_
['user'] = vim_username
5283 update_
['passwd'] = vim_password
5285 mydb
.update_rows("datacenter_tenants", UPDATE
=update_
, WHERE
={"uuid": datacenter_tenant_id
})
5287 vim_threads
["running"][datacenter_tenant_id
].insert_task("reload")
5288 return datacenter_tenant_id
5290 def delete_vim_account(mydb
, tenant_id
, vim_account_id
, datacenter
=None):
5291 #get nfvo_tenant info
5292 if not tenant_id
or tenant_id
=="any":
5295 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
5296 tenant_uuid
= tenant_dict
['uuid']
5298 #check that this association exist before
5299 tenants_datacenter_dict
= {}
5301 datacenter_id
, _
= get_datacenter_uuid(mydb
, tenant_uuid
, datacenter
)
5302 tenants_datacenter_dict
["datacenter_id"] = datacenter_id
5303 elif vim_account_id
:
5304 tenants_datacenter_dict
["datacenter_tenant_id"] = vim_account_id
5306 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
5307 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
5308 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
5309 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), httperrors
.Not_Found
)
5311 #delete this association
5312 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
5314 #get vim_tenant info and deletes
5316 for tenant_datacenter_item
in tenant_datacenter_list
:
5317 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
5318 #try to delete vim:tenant
5320 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
5321 if vim_tenant_dict
['created']=='true':
5322 #delete tenant at VIM if created by NFVO
5324 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5325 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
5326 except vimconn
.vimconnException
as e
:
5327 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
5328 logger
.warn(warning
)
5329 except db_base_Exception
as e
:
5330 logger
.error("Cannot delete datacenter_tenants " + str(e
))
5331 pass # the error will be caused because dependencies, vim_tenant can not be deleted
5332 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
5333 thread
= vim_threads
["running"].get(thread_id
)
5335 thread
.insert_task("exit")
5336 vim_threads
["deleting"][thread_id
] = thread
5337 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
5340 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
5342 #get datacenter info
5343 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5345 if 'check-connectivity' in action_dict
:
5347 myvim
.check_vim_connectivity()
5348 except vimconn
.vimconnException
as e
:
5349 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
5350 raise NfvoException(str(e
), e
.http_code
)
5351 elif 'net-update' in action_dict
:
5353 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
5355 except vimconn
.vimconnException
as e
:
5356 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
5357 raise NfvoException(str(e
), httperrors
.Internal_Server_Error
)
5358 #update nets Change from VIM format to NFVO format
5361 net_nfvo
={'datacenter_id': datacenter_id
}
5362 net_nfvo
['name'] = net
['name']
5363 #net_nfvo['description']= net['name']
5364 net_nfvo
['vim_net_id'] = net
['id']
5365 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
5366 net_nfvo
['shared'] = net
['shared']
5367 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
5368 net_list
.append(net_nfvo
)
5369 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
5370 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
5372 elif 'net-edit' in action_dict
:
5373 net
= action_dict
['net-edit'].pop('net')
5374 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
5375 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
5376 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
5378 elif 'net-delete' in action_dict
:
5379 net
= action_dict
['net-deelte'].get('net')
5380 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
5381 result
= mydb
.delete_row(FROM
='datacenter_nets',
5382 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
5386 raise NfvoException("Unknown action " + str(action_dict
), httperrors
.Bad_Request
)
5389 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
5390 #get datacenter info
5391 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5393 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
5394 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
5395 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
5399 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
5400 #get datacenter info
5401 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5404 action_dict
= action_dict
["netmap"]
5405 if 'vim_id' in action_dict
:
5406 filter_dict
["id"] = action_dict
['vim_id']
5407 if 'vim_name' in action_dict
:
5408 filter_dict
["name"] = action_dict
['vim_name']
5410 filter_dict
["shared"] = True
5413 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
5414 except vimconn
.vimconnException
as e
:
5415 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
5416 raise NfvoException(str(e
), httperrors
.Internal_Server_Error
)
5417 if len(vim_nets
)>1 and action_dict
:
5418 raise NfvoException("more than two networks found, specify with vim_id", httperrors
.Conflict
)
5419 elif len(vim_nets
)==0: # and action_dict:
5420 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), httperrors
.Not_Found
)
5422 for net
in vim_nets
:
5423 net_nfvo
={'datacenter_id': datacenter_id
}
5424 if action_dict
and "name" in action_dict
:
5425 net_nfvo
['name'] = action_dict
['name']
5427 net_nfvo
['name'] = net
['name']
5428 #net_nfvo['description']= net['name']
5429 net_nfvo
['vim_net_id'] = net
['id']
5430 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
5431 net_nfvo
['shared'] = net
['shared']
5432 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
5434 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
5435 net_nfvo
["status"] = "OK"
5436 net_nfvo
["uuid"] = net_id
5437 except db_base_Exception
as e
:
5441 net_nfvo
["status"] = "FAIL: " + str(e
)
5442 net_list
.append(net_nfvo
)
5445 def get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
):
5446 # obtain all network data
5448 if utils
.check_valid_uuid(network_id
):
5449 filter_dict
= {"id": network_id
}
5451 filter_dict
= {"name": network_id
}
5453 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5454 network
= myvim
.get_network_list(filter_dict
=filter_dict
)
5455 except vimconn
.vimconnException
as e
:
5456 raise NfvoException("Not possible to get_sdn_net_id from VIM: {}".format(str(e
)), e
.http_code
)
5458 # ensure the network is defined
5459 if len(network
) == 0:
5460 raise NfvoException("Network {} is not present in the system".format(network_id
),
5461 httperrors
.Bad_Request
)
5463 # ensure there is only one network with the provided name
5464 if len(network
) > 1:
5465 raise NfvoException("Multiple networks present in vim identified by {}".format(network_id
), httperrors
.Bad_Request
)
5467 # ensure it is a dataplane network
5468 if network
[0]['type'] != 'data':
5471 # ensure we use the id
5472 network_id
= network
[0]['id']
5474 # search in dabase mano_db in table instance nets for the sdn_net_id that corresponds to the vim_net_id==network_id
5475 # and with instance_scenario_id==NULL
5476 #search_dict = {'vim_net_id': network_id, 'instance_scenario_id': None}
5477 search_dict
= {'vim_net_id': network_id
}
5480 #sdn_network_id = mydb.get_rows(SELECT=('sdn_net_id',), FROM='instance_nets', WHERE=search_dict)[0]['sdn_net_id']
5481 result
= mydb
.get_rows(SELECT
=('sdn_net_id',), FROM
='instance_nets', WHERE
=search_dict
)
5482 except db_base_Exception
as e
:
5483 raise NfvoException("db_base_Exception obtaining SDN network to associated to vim network {}".format(
5484 network_id
) + str(e
), e
.http_code
)
5488 if net
['sdn_net_id'] != None:
5490 sdn_net_id
= net
['sdn_net_id']
5492 if sdn_net_counter
== 0:
5494 elif sdn_net_counter
== 1:
5497 raise NfvoException("More than one SDN network is associated to vim network {}".format(
5498 network_id
), httperrors
.Internal_Server_Error
)
5500 def get_sdn_controller_id(mydb
, datacenter
):
5501 # Obtain sdn controller id
5502 config
= mydb
.get_rows(SELECT
=('config',), FROM
='datacenters', WHERE
={'uuid': datacenter
})[0].get('config', '{}')
5506 return yaml
.load(config
, Loader
=yaml
.Loader
).get('sdn-controller')
5508 def vim_net_sdn_attach(mydb
, tenant_id
, datacenter
, network_id
, descriptor
):
5510 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
5511 if not sdn_network_id
:
5512 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
), httperrors
.Internal_Server_Error
)
5514 #Obtain sdn controller id
5515 controller_id
= get_sdn_controller_id(mydb
, datacenter
)
5516 if not controller_id
:
5517 raise NfvoException("No SDN controller is set for datacenter {}".format(datacenter
), httperrors
.Internal_Server_Error
)
5519 #Obtain sdn controller info
5520 sdn_controller
= ovim
.show_of_controller(controller_id
)
5523 'name': 'external_port',
5524 'net_id': sdn_network_id
,
5525 'ofc_id': controller_id
,
5526 'switch_dpid': sdn_controller
['dpid'],
5527 'switch_port': descriptor
['port']
5530 if 'vlan' in descriptor
:
5531 port_data
['vlan'] = descriptor
['vlan']
5532 if 'mac' in descriptor
:
5533 port_data
['mac'] = descriptor
['mac']
5535 result
= ovim
.new_port(port_data
)
5536 except ovimException
as e
:
5537 raise NfvoException("ovimException attaching SDN network {} to vim network {}".format(
5538 sdn_network_id
, network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5539 except db_base_Exception
as e
:
5540 raise NfvoException("db_base_Exception attaching SDN network to vim network {}".format(
5541 network_id
) + str(e
), e
.http_code
)
5543 return 'Port uuid: '+ result
5545 def vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, network_id
, port_id
=None):
5547 filter = {'uuid': port_id
}
5549 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
5550 if not sdn_network_id
:
5551 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
),
5552 httperrors
.Internal_Server_Error
)
5553 #in case no port_id is specified only ports marked as 'external_port' will be detached
5554 filter = {'name': 'external_port', 'net_id': sdn_network_id
}
5557 port_list
= ovim
.get_ports(columns
={'uuid'}, filter=filter)
5558 except ovimException
as e
:
5559 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
5560 httperrors
.Internal_Server_Error
)
5562 if len(port_list
) == 0:
5563 raise NfvoException("No ports attached to the network {} were found with the requested criteria".format(network_id
),
5564 httperrors
.Bad_Request
)
5567 for port
in port_list
:
5569 port_uuid_list
.append(port
['uuid'])
5570 ovim
.delete_port(port
['uuid'])
5571 except ovimException
as e
:
5572 raise NfvoException("ovimException deleting port {} for net {}. ".format(port
['uuid'], network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5574 return 'Detached ports uuid: {}'.format(','.join(port_uuid_list
))
5576 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
5577 #get datacenter info
5578 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5581 if utils
.check_valid_uuid(name
):
5582 filter_dict
["id"] = name
5584 filter_dict
["name"] = name
5586 if item
=="networks":
5587 #filter_dict['tenant_id'] = myvim['tenant_id']
5588 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
5590 if len(content
) == 0:
5591 raise NfvoException("Network {} is not present in the system. ".format(name
),
5592 httperrors
.Bad_Request
)
5594 #Update the networks with the attached ports
5596 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, net
['id'])
5597 if sdn_network_id
!= None:
5599 #port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan'}, filter={'name': 'external_port', 'net_id': sdn_network_id})
5600 port_list
= ovim
.get_ports(columns
={'uuid', 'switch_port', 'vlan','name'}, filter={'net_id': sdn_network_id
})
5601 except ovimException
as e
:
5602 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5603 #Remove field name and if port name is external_port save it as 'type'
5604 for port
in port_list
:
5605 if port
['name'] == 'external_port':
5606 port
['type'] = "External"
5608 net
['sdn_network_id'] = sdn_network_id
5609 net
['sdn_attached_ports'] = port_list
5611 elif item
=="tenants":
5612 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
5613 elif item
== "images":
5615 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
5617 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5618 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
5619 if name
and len(content
)==1:
5620 return {item
[:-1]: content
[0]}
5621 elif name
and len(content
)==0:
5622 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.items())),
5625 return {item
: content
}
5626 except vimconn
.vimconnException
as e
:
5627 print("vim_action Not possible to get_{}_list from VIM: {} ".format(item
, str(e
)))
5628 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
5631 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
5632 #get datacenter info
5633 if tenant_id
== "any":
5636 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5638 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
5639 logger
.debug("vim_action_delete vim response: " + str(content
))
5640 items
= next(iter(content
.values()))
5641 if type(items
)==list and len(items
)==0:
5642 raise NfvoException("Not found " + item
, httperrors
.Not_Found
)
5643 elif type(items
)==list and len(items
)>1:
5644 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), httperrors
.Not_Found
)
5645 else: # it is a dict
5646 item_id
= items
["id"]
5647 item_name
= str(items
.get("name"))
5650 if item
=="networks":
5651 # If there is a SDN network associated to the vim-network, proceed to clear the relationship and delete it
5652 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, item_id
)
5653 if sdn_network_id
!= None:
5654 #Delete any port attachment to this network
5656 port_list
= ovim
.get_ports(columns
={'uuid'}, filter={'net_id': sdn_network_id
})
5657 except ovimException
as e
:
5658 raise NfvoException(
5659 "ovimException obtaining external ports for net {}. ".format(sdn_network_id
) + str(e
),
5660 httperrors
.Internal_Server_Error
)
5662 # By calling one by one all ports to be detached we ensure that not only the external_ports get detached
5663 for port
in port_list
:
5664 vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, item_id
, port
['uuid'])
5666 #Delete from 'instance_nets' the correspondence between the vim-net-id and the sdn-net-id
5668 mydb
.delete_row(FROM
='instance_nets', WHERE
={'instance_scenario_id': None,
5669 'sdn_net_id': sdn_network_id
,
5670 'vim_net_id': item_id
})
5671 except db_base_Exception
as e
:
5672 raise NfvoException("Error deleting correspondence for VIM/SDN dataplane networks{}: {}".format(
5673 item_id
, e
), e
.http_code
)
5675 #Delete the SDN network
5677 ovim
.delete_network(sdn_network_id
)
5678 except ovimException
as e
:
5679 logger
.error("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
), exc_info
=True)
5680 raise NfvoException("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
),
5681 httperrors
.Internal_Server_Error
)
5683 content
= myvim
.delete_network(item_id
)
5684 elif item
=="tenants":
5685 content
= myvim
.delete_tenant(item_id
)
5686 elif item
== "images":
5687 content
= myvim
.delete_image(item_id
)
5689 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5690 except vimconn
.vimconnException
as e
:
5691 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
5692 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
5694 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
5697 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
5698 #get datacenter info
5699 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
5700 if tenant_id
== "any":
5702 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5704 if item
=="networks":
5705 net
= descriptor
["network"]
5706 net_name
= net
.pop("name")
5707 net_type
= net
.pop("type", "bridge")
5708 net_public
= net
.pop("shared", False)
5709 net_ipprofile
= net
.pop("ip_profile", None)
5710 net_vlan
= net
.pop("vlan", None)
5711 net_provider_network_profile
= None
5713 net_provider_network_profile
= {"segmentation-id": net_vlan
}
5714 content
, _
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, provider_network_profile
=net_provider_network_profile
) #, **net)
5716 #If the datacenter has a SDN controller defined and the network is of dataplane type, then create the sdn network
5717 if get_sdn_controller_id(mydb
, datacenter
) != None and (net_type
== 'data' or net_type
== 'ptp'):
5718 #obtain datacenter_tenant_id
5719 datacenter_tenant_id
= mydb
.get_rows(SELECT
=('uuid',),
5720 FROM
='datacenter_tenants',
5721 WHERE
={'datacenter_id': datacenter
})[0]['uuid']
5724 sdn_network
['vlan'] = net_vlan
5725 sdn_network
['type'] = net_type
5726 sdn_network
['name'] = net_name
5727 sdn_network
['region'] = datacenter_tenant_id
5728 ovim_content
= ovim
.new_network(sdn_network
)
5729 except ovimException
as e
:
5730 logger
.error("ovimException creating SDN network={} ".format(
5731 sdn_network
) + str(e
), exc_info
=True)
5732 raise NfvoException("ovimException creating SDN network={} ".format(sdn_network
) + str(e
),
5733 httperrors
.Internal_Server_Error
)
5735 # Save entry in in dabase mano_db in table instance_nets to stablish a dictionary vim_net_id <->sdn_net_id
5736 # use instance_scenario_id=None to distinguish from real instaces of nets
5737 correspondence
= {'instance_scenario_id': None,
5738 'sdn_net_id': ovim_content
,
5739 'vim_net_id': content
,
5740 'datacenter_tenant_id': datacenter_tenant_id
5743 mydb
.new_row('instance_nets', correspondence
, add_uuid
=True)
5744 except db_base_Exception
as e
:
5745 raise NfvoException("Error saving correspondence for VIM/SDN dataplane networks{}: {}".format(
5746 correspondence
, e
), e
.http_code
)
5747 elif item
=="tenants":
5748 tenant
= descriptor
["tenant"]
5749 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
5751 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5752 except vimconn
.vimconnException
as e
:
5753 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
5755 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
5757 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
5759 wim_id
= ovim
.new_of_controller(sdn_controller
)
5761 # Load plugin if not previously loaded
5762 controller_type
= sdn_controller
.get("type")
5763 plugin_name
= "rosdn_" + controller_type
5764 if plugin_name
not in plugins
:
5765 _load_plugin(plugin_name
, type="sdn")
5767 thread_name
= get_non_used_vim_name(sdn_controller
['name'], wim_id
, wim_id
, None)
5768 new_thread
= vim_thread(task_lock
, plugins
, thread_name
, wim_id
, None, db
=db
)
5771 vim_threads
["running"][thread_id
] = new_thread
5772 logger
.debug('New SDN controller created with uuid {}'.format(wim_id
))
5774 except ovimException
as e
:
5775 raise NfvoException(e
) from e
5777 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
5778 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
5779 msg
= 'SDN controller {} updated'.format(data
)
5780 vim_threads
["running"][controller_id
].insert_task("reload")
5784 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
5785 if controller_id
== None:
5786 data
= ovim
.get_of_controllers()
5788 data
= ovim
.show_of_controller(controller_id
)
5790 msg
= 'SDN controller list:\n {}'.format(data
)
5794 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
5795 select_
= ('uuid', 'config')
5796 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
5797 for datacenter
in datacenters
:
5798 if datacenter
['config']:
5799 config
= yaml
.load(datacenter
['config'], Loader
=yaml
.Loader
)
5800 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
5801 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), httperrors
.Conflict
)
5803 data
= ovim
.delete_of_controller(controller_id
)
5804 msg
= 'SDN controller {} deleted'.format(data
)
5808 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
5809 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
5810 if len(controller
) < 1:
5811 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), httperrors
.Not_Found
)
5814 sdn_controller_id
= yaml
.load(controller
[0]["config"], Loader
=yaml
.Loader
)["sdn-controller"]
5816 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), httperrors
.Bad_Request
)
5818 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
5819 switch_dpid
= sdn_controller
["dpid"]
5822 for compute_node
in sdn_port_mapping
:
5823 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
5825 element
["compute_node"] = compute_node
["compute_node"]
5826 if compute_node
["ports"]:
5827 for port
in compute_node
["ports"]:
5828 pci
= port
.get("pci")
5829 element
["switch_port"] = port
.get("switch_port")
5830 element
["switch_mac"] = port
.get("switch_mac")
5831 if not element
["switch_port"] and not element
["switch_mac"]:
5832 raise NfvoException ("The mapping must contain 'switch_port' or 'switch_mac'", httperrors
.Bad_Request
)
5833 for pci_expanded
in utils
.expand_brackets(pci
):
5834 element
["pci"] = pci_expanded
5835 maps
.append(dict(element
))
5837 out
= ovim
.set_of_port_mapping(maps
, sdn_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, vim_id
=datacenter_id
)
5838 vim_threads
["running"][sdn_controller_id
].insert_task("reload")
5841 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
5842 maps
= ovim
.get_of_port_mappings(db_filter
={"datacenter_id": datacenter_id
})
5845 "sdn-controller": None,
5846 "datacenter-id": datacenter_id
,
5848 "ports_mapping": list()
5851 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
5852 if datacenter
['config']:
5853 config
= yaml
.load(datacenter
['config'], Loader
=yaml
.Loader
)
5854 if 'sdn-controller' in config
:
5855 controller_id
= config
['sdn-controller']
5856 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
5857 result
["sdn-controller"] = controller_id
5858 result
["dpid"] = sdn_controller
["dpid"]
5860 if result
["sdn-controller"] == None:
5861 raise NfvoException("SDN controller is not defined for datacenter {}".format(datacenter_id
), httperrors
.Bad_Request
)
5862 if result
["dpid"] == None:
5863 raise NfvoException("It was not possible to determine DPID for SDN controller {}".format(result
["sdn-controller"]),
5864 httperrors
.Internal_Server_Error
)
5869 ports_correspondence_dict
= dict()
5871 if result
["sdn-controller"] != link
["wim_id"]:
5872 raise NfvoException("The sdn-controller specified for different port mappings differ", httperrors
.Internal_Server_Error
)
5873 if result
["dpid"] != link
["switch_dpid"]:
5874 raise NfvoException("The dpid specified for different port mappings differ", httperrors
.Internal_Server_Error
)
5875 link_config
= link
["service_mapping_info"]
5877 element
["pci"] = link
.get("device_interface_id")
5878 if link
["switch_port"]:
5879 element
["switch_port"] = link
["switch_port"]
5880 if link_config
["switch_mac"]:
5881 element
["switch_mac"] = link_config
.get("switch_mac")
5883 if not link
.get("interface_id") in ports_correspondence_dict
:
5885 content
["compute_node"] = link
.get("interface_id")
5886 content
["ports"] = list()
5887 ports_correspondence_dict
[link
.get("interface_id")] = content
5889 ports_correspondence_dict
[link
["interface_id"]]["ports"].append(element
)
5891 for key
in sorted(ports_correspondence_dict
):
5892 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
5896 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
5897 return ovim
.clear_of_port_mapping(db_filter
={"datacenter_id":datacenter_id
})
5899 def create_RO_keypair(tenant_id
):
5901 Creates a public / private keys for a RO tenant and returns their values
5903 tenant_id: ID of the tenant
5905 public_key: Public key for the RO tenant
5906 private_key: Encrypted private key for RO tenant
5910 key
= RSA
.generate(bits
)
5912 public_key
= key
.publickey().exportKey('OpenSSH')
5913 if isinstance(public_key
, ValueError):
5914 raise NfvoException("Unable to create public key: {}".format(public_key
), httperrors
.Internal_Server_Error
)
5915 private_key
= key
.exportKey(passphrase
=tenant_id
, pkcs
=8)
5916 except (ValueError, NameError) as e
:
5917 raise NfvoException("Unable to create private key: {}".format(e
), httperrors
.Internal_Server_Error
)
5918 if isinstance(public_key
, bytes
):
5919 public_key
= public_key
.decode(encoding
='UTF-8')
5920 if isinstance(private_key
, bytes
):
5921 private_key
= private_key
.decode(encoding
='UTF-8')
5922 return public_key
, private_key
5924 def decrypt_key (key
, tenant_id
):
5926 Decrypts an encrypted RSA key
5928 key: Private key to be decrypted
5929 tenant_id: ID of the tenant
5931 unencrypted_key: Unencrypted private key for RO tenant
5934 key
= RSA
.importKey(key
,tenant_id
)
5935 unencrypted_key
= key
.exportKey('PEM')
5936 if isinstance(unencrypted_key
, ValueError):
5937 raise NfvoException("Unable to decrypt the private key: {}".format(unencrypted_key
), httperrors
.Internal_Server_Error
)
5938 if isinstance(unencrypted_key
, bytes
):
5939 unencrypted_key
= unencrypted_key
.decode(encoding
='UTF-8')
5940 except ValueError as e
:
5941 raise NfvoException("Unable to decrypt the private key: {}".format(e
), httperrors
.Internal_Server_Error
)
5942 return unencrypted_key