1 # -*- coding: utf-8 -*-
4 # Copyright 2015 Telefonica Investigacion y Desarrollo, S.A.U.
5 # This file is part of openmano
8 # Licensed under the Apache License, Version 2.0 (the "License"); you may
9 # not use this file except in compliance with the License. You may obtain
10 # a copy of the License at
12 # http://www.apache.org/licenses/LICENSE-2.0
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17 # License for the specific language governing permissions and limitations
20 # For those usages not covered by the Apache License, Version 2.0 please
21 # contact with: nfvlabs@tid.es
25 NFVO engine, implementing all the methods for the creation, deletion and management of vnfs, scenarios and instances
27 __author__
="Alfonso Tierno, Gerardo Garcia, Pablo Montes"
28 __date__
="$16-sep-2014 22:05:01$"
33 from osm_ro
import utils
34 from osm_ro
.utils
import deprecated
35 from osm_ro
.vim_thread
import vim_thread
36 import osm_ro
.console_proxy_thread
as cli
37 from osm_ro
import vimconn
41 from uuid
import uuid4
42 from osm_ro
.db_base
import db_base_Exception
44 from osm_ro
import nfvo_db
45 from threading
import Lock
48 from osm_ro
.sdn
import Sdn
, SdnException
as ovimException
49 # from lib_osm_openvim.ovim import ovimException
50 # from unittest.mock import MagicMock
51 # class ovimException(Exception):
55 from Crypto
.PublicKey
import RSA
57 import osm_im
.vnfd
as vnfd_catalog
58 import osm_im
.nsd
as nsd_catalog
59 from pyangbind
.lib
.serialise
import pybindJSONDecoder
60 from copy
import deepcopy
61 from pkg_resources
import iter_entry_points
65 from .wim
import sdnconn
66 from .wim
.wimconn_fake
import FakeConnector
67 from .wim
.failing_connector
import FailingConnector
68 from .http_tools
import errors
as httperrors
69 from .wim
.engine
import WimEngine
70 from .wim
.persistence
import WimPersistence
71 from copy
import deepcopy
72 from pprint
import pformat
79 global sdnconn_imported
82 global default_volume_size
83 default_volume_size
= '5' #size in GB
88 plugins
= {} # dictionary with VIM type as key, loaded module as value
89 vim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-VIMs
90 vim_persistent_info
= {}
92 sdnconn_imported
= {} # dictionary with WIM type as key, loaded module as value
93 wim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-WIMs
94 wim_persistent_info
= {}
97 logger
= logging
.getLogger('openmano.nfvo')
104 class NfvoException(httperrors
.HttpMappedError
):
105 """Common Class for NFVO errors"""
107 def _load_plugin(name
, type="vim"):
108 # type can be vim or sdn
111 for v
in iter_entry_points('osm_ro{}.plugins'.format(type), name
):
112 plugins
[name
] = v
.load()
113 except Exception as e
:
114 logger
.critical("Cannot load osm_{}: {}".format(name
, e
))
116 plugins
[name
] = FailingConnector("Cannot load osm_{}: {}".format(name
, e
))
117 if name
and name
not in plugins
:
118 error_text
= "Cannot load a module for {t} type '{n}'. The plugin 'osm_{n}' has not been" \
119 " registered".format(t
=type, n
=name
)
120 logger
.critical(error_text
)
121 plugins
[name
] = FailingConnector(error_text
)
122 # raise NfvoException("Cannot load a module for {t} type '{n}'. The plugin 'osm_{n}' has not been registered".
123 # format(t=type, n=name), httperrors.Bad_Request)
128 if task_id
<= last_task_id
:
129 task_id
= last_task_id
+ 0.000001
130 last_task_id
= task_id
131 return "ACTION-{:.6f}".format(task_id
)
132 # return (t.strftime("%Y%m%dT%H%M%S.{}%Z", t.localtime(task_id))).format(int((task_id % 1)*1e6))
135 def new_task(name
, params
, depends
=None):
137 task_id
= get_task_id()
138 task
= {"status": "enqueued", "id": task_id
, "name": name
, "params": params
}
140 task
["depends"] = depends
145 return True if id[:5] == "TASK-" else False
148 def get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_name
, tenant_id
):
149 name
= datacenter_name
[:16]
150 if name
not in vim_threads
["names"]:
151 vim_threads
["names"].append(name
)
154 name
= datacenter_name
[:16] + "." + tenant_name
[:16]
155 if name
not in vim_threads
["names"]:
156 vim_threads
["names"].append(name
)
159 vim_threads
["names"].append(name
)
163 def get_non_used_wim_name(wim_name
, wim_id
, tenant_name
, tenant_id
):
165 if name
not in wim_threads
["names"]:
166 wim_threads
["names"].append(name
)
168 name
= wim_name
[:16] + "." + tenant_name
[:16]
169 if name
not in wim_threads
["names"]:
170 wim_threads
["names"].append(name
)
172 name
= wim_id
+ "-" + tenant_id
173 wim_threads
["names"].append(name
)
177 def start_service(mydb
, persistence
=None, wim
=None):
178 global db
, global_config
, plugins
, ovim
179 db
= nfvo_db
.nfvo_db(lock
=db_lock
)
181 db
.connect(global_config
['db_host'], global_config
['db_user'], global_config
['db_passwd'], global_config
['db_name'])
183 persistence
= persistence
or WimPersistence(db
)
186 if "rosdn_fake" not in plugins
:
187 plugins
["rosdn_fake"] = FakeConnector
188 # starts ovim library
189 ovim
= Sdn(db
, plugins
)
192 wim_engine
= wim
or WimEngine(persistence
, plugins
)
193 wim_engine
.ovim
= ovim
197 #delete old unneeded vim_wim_actions
201 from_
= 'tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join '\
202 'datacenter_tenants as dt on td.datacenter_tenant_id=dt.uuid'
203 select_
= ('type', 'd.config as config', 'd.uuid as datacenter_id', 'vim_url', 'vim_url_admin',
204 'd.name as datacenter_name', 'dt.uuid as datacenter_tenant_id',
205 'dt.vim_tenant_name as vim_tenant_name', 'dt.vim_tenant_id as vim_tenant_id',
206 'user', 'passwd', 'dt.config as dt_config', 'nfvo_tenant_id')
207 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
)
209 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
210 'datacenter_id': vim
.get('datacenter_id')}
212 extra
.update(yaml
.load(vim
["config"], Loader
=yaml
.Loader
))
213 if vim
.get('dt_config'):
214 extra
.update(yaml
.load(vim
["dt_config"], Loader
=yaml
.Loader
))
215 plugin_name
= "rovim_" + vim
["type"]
216 if plugin_name
not in plugins
:
217 _load_plugin(plugin_name
, type="vim")
219 thread_id
= vim
['datacenter_tenant_id']
220 vim_persistent_info
[thread_id
] = {}
223 # return -httperrors.Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
224 myvim
= plugins
[plugin_name
].vimconnector(
225 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
226 tenant_id
=vim
['vim_tenant_id'], tenant_name
=vim
['vim_tenant_name'],
227 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
228 user
=vim
['user'], passwd
=vim
['passwd'],
229 config
=extra
, persistent_info
=vim_persistent_info
[thread_id
]
231 except vimconn
.vimconnException
as e
:
233 logger
.error("Cannot launch thread for VIM {} '{}': {}".format(vim
['datacenter_name'],
234 vim
['datacenter_id'], e
))
235 except Exception as e
:
236 logger
.critical("Cannot launch thread for VIM {} '{}': {}".format(vim
['datacenter_name'],
237 vim
['datacenter_id'], e
))
238 # raise NfvoException("Error at VIM {}; {}: {}".format(vim["type"], type(e).__name__, e),
239 # httperrors.Internal_Server_Error)
240 thread_name
= get_non_used_vim_name(vim
['datacenter_name'], vim
['datacenter_id'], vim
['vim_tenant_name'],
241 vim
['vim_tenant_id'])
242 new_thread
= vim_thread(task_lock
, plugins
, thread_name
, None,
243 vim
['datacenter_tenant_id'], db
=db
)
245 vim_threads
["running"][thread_id
] = new_thread
246 wims
= mydb
.get_rows(FROM
="wim_accounts join wims on wim_accounts.wim_id=wims.uuid",
247 WHERE
={"sdn": "true"},
248 SELECT
=("wim_accounts.uuid as uuid", "type", "wim_accounts.name as name"))
250 plugin_name
= "rosdn_" + wim
["type"]
251 if plugin_name
not in plugins
:
252 _load_plugin(plugin_name
, type="sdn")
254 thread_id
= wim
['uuid']
255 thread_name
= get_non_used_vim_name(wim
['name'], wim
['uuid'], wim
['uuid'], None)
256 new_thread
= vim_thread(task_lock
, plugins
, thread_name
, wim
['uuid'], None, db
=db
)
258 vim_threads
["running"][thread_id
] = new_thread
259 wim_engine
.start_threads()
260 except db_base_Exception
as e
:
261 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
262 except ovimException
as e
:
264 if message
[:22] == "DATABASE wrong version":
265 message
= "DATABASE wrong version of lib_osm_openvim {msg} -d{dbname} -u{dbuser} -p{dbpass} {ver}' "\
266 "at host {dbhost}".format(
267 msg
=message
[22:-3], dbname
=global_config
["db_ovim_name"],
268 dbuser
=global_config
["db_ovim_user"], dbpass
=global_config
["db_ovim_passwd"],
269 ver
=message
[-3:-1], dbhost
=global_config
["db_ovim_host"])
270 raise NfvoException(message
, httperrors
.Bad_Request
)
274 global ovim
, global_config
277 for thread_id
, thread
in vim_threads
["running"].items():
278 thread
.insert_task("exit")
279 vim_threads
["deleting"][thread_id
] = thread
280 vim_threads
["running"] = {}
283 wim_engine
.stop_threads()
285 if global_config
and global_config
.get("console_thread"):
286 for thread
in global_config
["console_thread"]:
287 thread
.terminate
= True
290 return ("openmanod version {} {}\n(c) Copyright Telefonica".format(global_config
["version"],
291 global_config
["version_date"] ))
295 Clean unused or old entries at database to avoid unlimited growing
296 :param mydb: database connector
299 # get and delete unused vim_wim_actions: all elements deleted, one week before, instance not present
300 now
= t
.time()-3600*24*7
301 instance_action_id
= None
304 actions_to_delete
= mydb
.get_rows(
305 SELECT
=("item", "item_id", "instance_action_id"),
306 FROM
="vim_wim_actions as va join instance_actions as ia on va.instance_action_id=ia.uuid "
307 "left join instance_scenarios as i on ia.instance_id=i.uuid",
308 WHERE
={"va.action": "DELETE", "va.modified_at<": now
, "i.uuid": None,
309 "va.status": ("DONE", "SUPERSEDED")},
312 for to_delete
in actions_to_delete
:
313 mydb
.delete_row(FROM
="vim_wim_actions", WHERE
=to_delete
)
314 if instance_action_id
!= to_delete
["instance_action_id"]:
315 instance_action_id
= to_delete
["instance_action_id"]
316 mydb
.delete_row(FROM
="instance_actions", WHERE
={"uuid": instance_action_id
})
317 nb_deleted
+= len(actions_to_delete
)
318 if len(actions_to_delete
) < 100:
321 mydb
.update_rows("vim_wim_actions", UPDATE
={"worker": None}, WHERE
={"worker<>": None})
324 logger
.debug("Removed {} unused vim_wim_actions".format(nb_deleted
))
327 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
329 return result, content:
330 <0, error_text upon error
331 nb_records, flavor_list on success
334 WHERE_dict
['vnf_id'] = vnf_id
335 if nfvo_tenant
is not None:
336 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
338 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
339 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
340 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
341 #print "get_flavor_list result:", result
342 #print "get_flavor_list content:", content
344 for flavor
in flavors
:
345 flavorList
.append(flavor
['flavor_id'])
349 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
351 Get used images of all vms belonging to this VNFD
352 :param mydb: database conector
353 :param vnf_id: vnfd uuid
354 :param nfvo_tenant: tenant, not used
355 :return: The list of image uuid used
358 vms
= mydb
.get_rows(SELECT
=('image_id','image_list'), FROM
='vms', WHERE
={'vnf_id': vnf_id
})
360 if vm
["image_id"] and vm
["image_id"] not in image_list
:
361 image_list
.append(vm
["image_id"])
363 vm_image_list
= yaml
.load(vm
["image_list"], Loader
=yaml
.Loader
)
364 for image_dict
in vm_image_list
:
365 if image_dict
["image_id"] not in image_list
:
366 image_list
.append(image_dict
["image_id"])
370 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
371 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None, ignore_errors
=False):
372 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
373 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
374 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
375 raise exception upon error
379 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
380 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
381 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
382 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
383 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
384 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
385 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
386 from_
= 'tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join datacenter_tenants as dt on td.datacenter_tenant_id=dt.uuid'
387 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
388 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
389 'user','passwd', 'dt.config as dt_config')
391 from_
= 'datacenters as d'
392 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
394 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
397 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
398 'datacenter_id': vim
.get('datacenter_id'),
399 '_vim_type_internal': vim
.get('type')}
401 extra
.update(yaml
.load(vim
["config"], Loader
=yaml
.Loader
))
402 if vim
.get('dt_config'):
403 extra
.update(yaml
.load(vim
["dt_config"], Loader
=yaml
.Loader
))
404 plugin_name
= "rovim_" + vim
["type"]
405 if plugin_name
not in plugins
:
407 _load_plugin(plugin_name
, type="vim")
408 except NfvoException
as e
:
410 logger
.error("{}".format(e
))
415 if 'datacenter_tenant_id' in vim
:
416 thread_id
= vim
["datacenter_tenant_id"]
417 if thread_id
not in vim_persistent_info
:
418 vim_persistent_info
[thread_id
] = {}
419 persistent_info
= vim_persistent_info
[thread_id
]
423 # return -httperrors.Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
424 vim_dict
[vim
['datacenter_id']] = plugins
[plugin_name
].vimconnector(
425 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
426 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
),
427 tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
428 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
429 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
430 config
=extra
, persistent_info
=persistent_info
432 except Exception as e
:
434 logger
.error("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)))
436 http_code
= httperrors
.Internal_Server_Error
437 if isinstance(e
, vimconn
.vimconnException
):
438 http_code
= e
.http_code
439 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), http_code
)
441 except db_base_Exception
as e
:
442 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
445 def rollback(mydb
, vims
, rollback_list
):
447 #delete things by reverse order
448 for i
in range(len(rollback_list
)-1, -1, -1):
449 item
= rollback_list
[i
]
450 if item
["where"]=="vim":
451 if item
["vim_id"] not in vims
:
453 if is_task_id(item
["uuid"]):
455 vim
= vims
[item
["vim_id"]]
457 if item
["what"]=="image":
458 vim
.delete_image(item
["uuid"])
459 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_vim_id": vim
["id"], "vim_id":item
["uuid"]})
460 elif item
["what"]=="flavor":
461 vim
.delete_flavor(item
["uuid"])
462 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_vim_id": vim
["id"], "vim_id":item
["uuid"]})
463 elif item
["what"]=="network":
464 vim
.delete_network(item
["uuid"])
465 elif item
["what"]=="vm":
466 vim
.delete_vminstance(item
["uuid"])
467 except vimconn
.vimconnException
as e
:
468 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
469 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
470 except db_base_Exception
as e
:
471 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
475 if item
["what"]=="image":
476 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
477 elif item
["what"]=="flavor":
478 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
479 except db_base_Exception
as e
:
480 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
481 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
482 if len(undeleted_items
)==0:
483 return True," Rollback successful."
485 return False," Rollback fails to delete: " + str(undeleted_items
)
488 def check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1):
490 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
492 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
494 #dataplane interfaces
495 for numa
in vnfc
.get("numas",() ):
496 for interface
in numa
.get("interfaces",()):
497 if interface
["name"] in name_dict
:
499 "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
500 vnfc
["name"], interface
["name"]),
501 httperrors
.Bad_Request
)
502 name_dict
[ interface
["name"] ] = "underlay"
504 for interface
in vnfc
.get("bridge-ifaces",() ):
505 if interface
["name"] in name_dict
:
507 "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
508 vnfc
["name"], interface
["name"]),
509 httperrors
.Bad_Request
)
510 name_dict
[ interface
["name"] ] = "overlay"
511 vnfc_interfaces
[ vnfc
["name"] ] = name_dict
512 # check bood-data info
513 # if "boot-data" in vnfc:
514 # # check that user-data is incompatible with users and config-files
515 # if (vnfc["boot-data"].get("users") or vnfc["boot-data"].get("config-files")) and vnfc["boot-data"].get("user-data"):
516 # raise NfvoException(
517 # "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
518 # httperrors.Bad_Request)
520 #check if the info in external_connections matches with the one in the vnfcs
522 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
523 if external_connection
["name"] in name_list
:
525 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
526 external_connection
["name"]),
527 httperrors
.Bad_Request
)
528 name_list
.append(external_connection
["name"])
529 if external_connection
["VNFC"] not in vnfc_interfaces
:
531 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
532 external_connection
["name"], external_connection
["VNFC"]),
533 httperrors
.Bad_Request
)
535 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
537 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
538 external_connection
["name"],
539 external_connection
["local_iface_name"]),
540 httperrors
.Bad_Request
)
542 #check if the info in internal_connections matches with the one in the vnfcs
544 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
545 if internal_connection
["name"] in name_list
:
547 "Error at vnf:internal-connections:name, value '{}' already used as an internal-connection".format(
548 internal_connection
["name"]),
549 httperrors
.Bad_Request
)
550 name_list
.append(internal_connection
["name"])
551 #We should check that internal-connections of type "ptp" have only 2 elements
553 if len(internal_connection
["elements"])>2 and (internal_connection
.get("type") == "ptp" or internal_connection
.get("type") == "e-line"):
555 "Error at 'vnf:internal-connections[name:'{}']:elements', size must be 2 for a '{}' type. Consider change it to '{}' type".format(
556 internal_connection
["name"],
557 'ptp' if vnf_descriptor_version
==1 else 'e-line',
558 'data' if vnf_descriptor_version
==1 else "e-lan"),
559 httperrors
.Bad_Request
)
560 for port
in internal_connection
["elements"]:
562 iface
= port
["local_iface_name"]
563 if vnf
not in vnfc_interfaces
:
565 "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
566 internal_connection
["name"], vnf
),
567 httperrors
.Bad_Request
)
568 if iface
not in vnfc_interfaces
[ vnf
]:
570 "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
571 internal_connection
["name"], iface
),
572 httperrors
.Bad_Request
)
573 return -httperrors
.Bad_Request
,
574 if vnf_descriptor_version
==1 and "type" not in internal_connection
:
575 if vnfc_interfaces
[vnf
][iface
] == "overlay":
576 internal_connection
["type"] = "bridge"
578 internal_connection
["type"] = "data"
579 if vnf_descriptor_version
==2 and "implementation" not in internal_connection
:
580 if vnfc_interfaces
[vnf
][iface
] == "overlay":
581 internal_connection
["implementation"] = "overlay"
583 internal_connection
["implementation"] = "underlay"
584 if (internal_connection
.get("type") == "data" or internal_connection
.get("type") == "ptp" or \
585 internal_connection
.get("implementation") == "underlay") and vnfc_interfaces
[vnf
][iface
] == "overlay":
587 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
588 internal_connection
["name"],
589 iface
, 'bridge' if vnf_descriptor_version
==1 else 'overlay',
590 'data' if vnf_descriptor_version
==1 else 'underlay'),
591 httperrors
.Bad_Request
)
592 if (internal_connection
.get("type") == "bridge" or internal_connection
.get("implementation") == "overlay") and \
593 vnfc_interfaces
[vnf
][iface
] == "underlay":
595 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
596 internal_connection
["name"], iface
,
597 'data' if vnf_descriptor_version
==1 else 'underlay',
598 'bridge' if vnf_descriptor_version
==1 else 'overlay'),
599 httperrors
.Bad_Request
)
602 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=None):
604 if only_create_at_vim
:
605 image_mano_id
= image_dict
['uuid']
606 if return_on_error
== None:
607 return_on_error
= True
609 if image_dict
['location']:
610 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
612 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
614 image_mano_id
= images
[0]['uuid']
616 #create image in MANO DB
617 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
618 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
619 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
621 #temp_image_dict['location'] = image_dict.get('new_location') if image_dict['location'] is None
622 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
623 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
624 #create image at every vim
625 for vim_id
,vim
in vims
.items():
626 datacenter_vim_id
= vim
["config"]["datacenter_tenant_id"]
627 image_created
="false"
629 image_db
= mydb
.get_rows(FROM
="datacenters_images",
630 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'image_id': image_mano_id
})
631 #look at VIM if this image exist
633 if image_dict
['location'] is not None:
634 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
637 filter_dict
['name'] = image_dict
['universal_name']
638 if image_dict
.get('checksum') != None:
639 filter_dict
['checksum'] = image_dict
['checksum']
640 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
641 vim_images
= vim
.get_image_list(filter_dict
)
642 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
643 if len(vim_images
) > 1:
644 raise vimconn
.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict
)), httperrors
.Conflict
)
645 elif len(vim_images
) == 0:
646 raise vimconn
.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict
)))
648 #logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
649 image_vim_id
= vim_images
[0]['id']
651 except vimconn
.vimconnNotFoundException
as e
:
652 #Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
654 #image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
655 if image_dict
['location']:
656 image_vim_id
= vim
.new_image(image_dict
)
657 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
660 #If we reach this point, then the image has image name, and optionally checksum, and could not be found
661 raise vimconn
.vimconnException(str(e
))
662 except vimconn
.vimconnException
as e
:
664 logger
.error("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
667 logger
.warn("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
669 except vimconn
.vimconnException
as e
:
671 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
673 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
676 #if we reach here, the image has been created or existed
678 #add new vim_id at datacenters_images
679 mydb
.new_row('datacenters_images', {'datacenter_vim_id': datacenter_vim_id
,
680 'image_id':image_mano_id
,
681 'vim_id': image_vim_id
,
682 'created':image_created
})
683 elif image_db
[0]["vim_id"]!=image_vim_id
:
684 #modify existing vim_id at datacenters_images
685 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_vim_id':vim_id
, 'image_id':image_mano_id
})
687 return image_vim_id
if only_create_at_vim
else image_mano_id
690 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
691 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',0),
692 'ram':flavor_dict
.get('ram'),
693 'vcpus':flavor_dict
.get('vcpus'),
695 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
696 del flavor_dict
['extended']
697 if 'extended' in flavor_dict
:
698 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
700 #look if flavor exist
701 if only_create_at_vim
:
702 flavor_mano_id
= flavor_dict
['uuid']
703 if return_on_error
== None:
704 return_on_error
= True
706 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
708 flavor_mano_id
= flavors
[0]['uuid']
711 #create one by one the images of aditional disks
712 dev_image_list
=[] #list of images
713 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
715 for device
in flavor_dict
['extended'].get('devices',[]):
716 if "image" not in device
and "image name" not in device
:
719 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
720 image_dict
['universal_name']=device
.get('image name')
721 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
722 image_dict
['location']=device
.get('image')
723 #image_dict['new_location']=vnfc.get('image location')
724 image_dict
['checksum']=device
.get('image checksum')
725 image_metadata_dict
= device
.get('image metadata', None)
726 image_metadata_str
= None
727 if image_metadata_dict
!= None:
728 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
729 image_dict
['metadata']=image_metadata_str
730 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
731 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
732 dev_image_list
.append(image_id
)
734 temp_flavor_dict
['name'] = flavor_dict
['name']
735 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
736 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
737 flavor_mano_id
= content
738 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
739 #create flavor at every vim
740 if 'uuid' in flavor_dict
:
741 del flavor_dict
['uuid']
743 for vim_id
,vim
in vims
.items():
744 datacenter_vim_id
= vim
["config"]["datacenter_tenant_id"]
745 flavor_created
="false"
747 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors",
748 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
})
749 #look at VIM if this flavor exist SKIPPED
750 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
752 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
756 # Create the flavor in VIM
757 # Translate images at devices from MANO id to VIM id
759 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
760 # make a copy of original devices
763 for device
in flavor_dict
["extended"].get("devices",[]):
766 devices_original
.append(dev
)
767 if 'image' in device
:
769 if 'image metadata' in device
:
770 del device
['image metadata']
771 if 'image checksum' in device
:
772 del device
['image checksum']
774 for index
in range(0,len(devices_original
)) :
775 device
=devices_original
[index
]
776 if "image" not in device
and "image name" not in device
:
777 # if 'size' in device:
778 disk_list
.append({'size': device
.get('size', default_volume_size
), 'name': device
.get('name')})
781 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
782 image_dict
['universal_name']=device
.get('image name')
783 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
784 image_dict
['location']=device
.get('image')
785 # image_dict['new_location']=device.get('image location')
786 image_dict
['checksum']=device
.get('image checksum')
787 image_metadata_dict
= device
.get('image metadata', None)
788 image_metadata_str
= None
789 if image_metadata_dict
!= None:
790 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
791 image_dict
['metadata']=image_metadata_str
792 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
793 image_dict
["uuid"]=image_mano_id
794 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
796 #save disk information (image must be based on and size
797 disk_list
.append({'image_id': image_vim_id
, 'size': device
.get('size', default_volume_size
)})
799 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
802 #check that this vim_id exist in VIM, if not create
803 flavor_vim_id
=flavor_db
[0]["vim_id"]
805 vim
.get_flavor(flavor_vim_id
)
806 continue #flavor exist
807 except vimconn
.vimconnException
:
809 #create flavor at vim
810 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
813 flavor_vim_id
=vim
.get_flavor_id_from_data(flavor_dict
)
814 flavor_created
="false"
815 except vimconn
.vimconnException
as e
:
818 if not flavor_vim_id
:
819 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
820 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
821 flavor_created
="true"
822 except vimconn
.vimconnException
as e
:
824 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
826 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
829 #if reach here the flavor has been create or exist
830 if len(flavor_db
)==0:
831 #add new vim_id at datacenters_flavors
832 extended_devices_yaml
= None
833 if len(disk_list
) > 0:
834 extended_devices
= dict()
835 extended_devices
['disks'] = disk_list
836 extended_devices_yaml
= yaml
.safe_dump(extended_devices
,default_flow_style
=True,width
=256)
837 mydb
.new_row('datacenters_flavors',
838 {'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
, 'vim_id': flavor_vim_id
,
839 'created': flavor_created
, 'extended': extended_devices_yaml
})
840 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
841 #modify existing vim_id at datacenters_flavors
842 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
},
843 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
})
845 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
848 def get_str(obj
, field
, length
):
850 Obtain the str value,
855 value
= obj
.get(field
)
856 if value
is not None:
857 value
= str(value
)[:length
]
860 def _lookfor_or_create_image(db_image
, mydb
, descriptor
):
862 fill image content at db_image dictionary. Check if the image with this image and checksum exist
863 :param db_image: dictionary to insert data
864 :param mydb: database connector
865 :param descriptor: yang descriptor
866 :return: uuid if the image exist at DB, or None if a new image must be created with the data filled at db_image
869 db_image
["name"] = get_str(descriptor
, "image", 255)
870 db_image
["checksum"] = get_str(descriptor
, "image-checksum", 32)
871 if not db_image
["checksum"]: # Ensure that if empty string, None is stored
872 db_image
["checksum"] = None
873 if db_image
["name"].startswith("/"):
874 db_image
["location"] = db_image
["name"]
875 existing_images
= mydb
.get_rows(FROM
="images", WHERE
={'location': db_image
["location"]})
877 db_image
["universal_name"] = db_image
["name"]
878 existing_images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name': db_image
['universal_name'],
879 'checksum': db_image
['checksum']})
881 return existing_images
[0]["uuid"]
883 image_uuid
= str(uuid4())
884 db_image
["uuid"] = image_uuid
887 def get_resource_allocation_params(quota_descriptor
):
889 read the quota_descriptor from vnfd and fetch the resource allocation properties from the descriptor object
890 :param quota_descriptor: cpu/mem/vif/disk-io quota descriptor
891 :return: quota params for limit, reserve, shares from the descriptor object
894 if quota_descriptor
.get("limit"):
895 quota
["limit"] = int(quota_descriptor
["limit"])
896 if quota_descriptor
.get("reserve"):
897 quota
["reserve"] = int(quota_descriptor
["reserve"])
898 if quota_descriptor
.get("shares"):
899 quota
["shares"] = int(quota_descriptor
["shares"])
902 def new_vnfd_v3(mydb
, tenant_id
, vnf_descriptor
):
904 Parses an OSM IM vnfd_catalog and insert at DB
907 :param vnf_descriptor:
908 :return: The list of cretated vnf ids
911 myvnfd
= vnfd_catalog
.vnfd()
913 pybindJSONDecoder
.load_ietf_json(vnf_descriptor
, None, None, obj
=myvnfd
, path_helper
=True,
915 except Exception as e
:
916 raise NfvoException("Error. Invalid VNF descriptor format " + str(e
), httperrors
.Bad_Request
)
924 db_ip_profiles_index
= 0
928 vnfd_catalog_descriptor
= vnf_descriptor
.get("vnfd:vnfd-catalog")
929 if not vnfd_catalog_descriptor
:
930 vnfd_catalog_descriptor
= vnf_descriptor
.get("vnfd-catalog")
931 vnfd_descriptor_list
= vnfd_catalog_descriptor
.get("vnfd")
932 if not vnfd_descriptor_list
:
933 vnfd_descriptor_list
= vnfd_catalog_descriptor
.get("vnfd:vnfd")
934 for vnfd_yang
in myvnfd
.vnfd_catalog
.vnfd
.values():
935 vnfd
= vnfd_yang
.get()
938 vnf_uuid
= str(uuid4())
939 uuid_list
.append(vnf_uuid
)
940 vnfd_uuid_list
.append(vnf_uuid
)
941 vnfd_id
= get_str(vnfd
, "id", 255)
945 "name": get_str(vnfd
, "name", 255),
946 "description": get_str(vnfd
, "description", 255),
947 "tenant_id": tenant_id
,
948 "vendor": get_str(vnfd
, "vendor", 255),
949 "short_name": get_str(vnfd
, "short-name", 255),
950 "descriptor": str(vnf_descriptor
)[:60000]
953 for vnfd_descriptor
in vnfd_descriptor_list
:
954 if vnfd_descriptor
["id"] == str(vnfd
["id"]):
957 # table ip_profiles (ip-profiles)
958 ip_profile_name2db_table_index
= {}
959 for ip_profile
in vnfd
.get("ip-profiles").values():
961 "ip_version": str(ip_profile
["ip-profile-params"].get("ip-version", "ipv4")),
962 "subnet_address": str(ip_profile
["ip-profile-params"].get("subnet-address")),
963 "gateway_address": str(ip_profile
["ip-profile-params"].get("gateway-address")),
964 "dhcp_enabled": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("enabled", True)),
965 "dhcp_start_address": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("start-address")),
966 "dhcp_count": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("count")),
969 for dns
in ip_profile
["ip-profile-params"]["dns-server"].values():
970 dns_list
.append(str(dns
.get("address")))
971 db_ip_profile
["dns_address"] = ";".join(dns_list
)
972 if ip_profile
["ip-profile-params"].get('security-group'):
973 db_ip_profile
["security_group"] = ip_profile
["ip-profile-params"]['security-group']
974 ip_profile_name2db_table_index
[str(ip_profile
["name"])] = db_ip_profiles_index
975 db_ip_profiles_index
+= 1
976 db_ip_profiles
.append(db_ip_profile
)
978 # table nets (internal-vld)
979 net_id2uuid
= {} # for mapping interface with network
980 for vld
in vnfd
.get("internal-vld").values():
981 net_uuid
= str(uuid4())
982 uuid_list
.append(net_uuid
)
984 "name": get_str(vld
, "name", 255),
987 "description": get_str(vld
, "description", 255),
988 "osm_id": get_str(vld
, "id", 255),
989 "type": "bridge", # TODO adjust depending on connection point type
991 net_id2uuid
[vld
.get("id")] = net_uuid
992 db_nets
.append(db_net
)
993 # ip-profile, link db_ip_profile with db_sce_net
994 if vld
.get("ip-profile-ref"):
995 ip_profile_name
= vld
.get("ip-profile-ref")
996 if ip_profile_name
not in ip_profile_name2db_table_index
:
997 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vld[{}]':'ip-profile-ref':"
998 "'{}'. Reference to a non-existing 'ip_profiles'".format(
999 str(vnfd
["id"]), str(vld
["id"]), str(vld
["ip-profile-ref"])),
1000 httperrors
.Bad_Request
)
1001 db_ip_profiles
[ip_profile_name2db_table_index
[ip_profile_name
]]["net_id"] = net_uuid
1002 else: #check no ip-address has been defined
1003 for icp
in vld
.get("internal-connection-point").values():
1004 if icp
.get("ip-address"):
1005 raise NfvoException("Error at 'vnfd[{}]':'vld[{}]':'internal-connection-point[{}]' "
1006 "contains an ip-address but no ip-profile has been defined at VLD".format(
1007 str(vnfd
["id"]), str(vld
["id"]), str(icp
["id"])),
1008 httperrors
.Bad_Request
)
1010 # connection points vaiable declaration
1011 cp_name2iface_uuid
= {}
1013 cp_name2vm_uuid
= {}
1014 cp_name2db_interface
= {}
1015 vdu_id2cp_name
= {} # stored only when one external connection point is presented at this VDU
1019 vdu_id2db_table_index
= {}
1021 for vdu
in vnfd
.get("vdu").values():
1023 for vdu_descriptor
in vnfd_descriptor
["vdu"]:
1024 if vdu_descriptor
["id"] == str(vdu
["id"]):
1026 vm_uuid
= str(uuid4())
1027 uuid_list
.append(vm_uuid
)
1028 vdu_id
= get_str(vdu
, "id", 255)
1032 "name": get_str(vdu
, "name", 255),
1033 "description": get_str(vdu
, "description", 255),
1034 "pdu_type": get_str(vdu
, "pdu-type", 255),
1037 vdu_id2uuid
[db_vm
["osm_id"]] = vm_uuid
1038 vdu_id2db_table_index
[db_vm
["osm_id"]] = db_vms_index
1039 if vdu
.get("count"):
1040 db_vm
["count"] = int(vdu
["count"])
1043 image_present
= False
1044 if vdu
.get("image"):
1045 image_present
= True
1047 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, vdu
)
1049 image_uuid
= db_image
["uuid"]
1050 db_images
.append(db_image
)
1051 db_vm
["image_id"] = image_uuid
1052 if vdu
.get("alternative-images"):
1053 vm_alternative_images
= []
1054 for alt_image
in vdu
.get("alternative-images").values():
1056 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, alt_image
)
1058 image_uuid
= db_image
["uuid"]
1059 db_images
.append(db_image
)
1060 vm_alternative_images
.append({
1061 "image_id": image_uuid
,
1062 "vim_type": str(alt_image
["vim-type"]),
1063 # "universal_name": str(alt_image["image"]),
1064 # "checksum": str(alt_image["image-checksum"]) if alt_image.get("image-checksum") else None
1067 db_vm
["image_list"] = yaml
.safe_dump(vm_alternative_images
, default_flow_style
=True, width
=256)
1071 if vdu
.get("volumes"):
1072 for volume_key
in vdu
["volumes"]:
1073 volume
= vdu
["volumes"][volume_key
]
1074 if not image_present
:
1075 # Convert the first volume to vnfc.image
1076 image_present
= True
1078 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, volume
)
1080 image_uuid
= db_image
["uuid"]
1081 db_images
.append(db_image
)
1082 db_vm
["image_id"] = image_uuid
1084 # Add Openmano devices
1085 device
= {"name": str(volume
.get("name"))}
1086 device
["type"] = str(volume
.get("device-type"))
1087 if volume
.get("size"):
1088 device
["size"] = int(volume
["size"])
1089 if volume
.get("image"):
1090 device
["image name"] = str(volume
["image"])
1091 if volume
.get("image-checksum"):
1092 device
["image checksum"] = str(volume
["image-checksum"])
1094 devices
.append(device
)
1096 if not db_vm
.get("image_id"):
1097 if not db_vm
["pdu_type"]:
1098 raise NfvoException("Not defined image for VDU")
1099 # create a fake image
1103 if vdu
.get("cloud-init"):
1104 boot_data
["user-data"] = str(vdu
["cloud-init"])
1105 elif vdu
.get("cloud-init-file"):
1106 # TODO Where this file content is present???
1107 # boot_data["user-data"] = vnfd_yang.files[vdu["cloud-init-file"]]
1108 boot_data
["user-data"] = str(vdu
["cloud-init-file"])
1110 if vdu
.get("supplemental-boot-data"):
1111 if vdu
["supplemental-boot-data"].get('boot-data-drive'):
1112 boot_data
['boot-data-drive'] = True
1113 if vdu
["supplemental-boot-data"].get('config-file'):
1114 om_cfgfile_list
= list()
1115 for custom_config_file
in vdu
["supplemental-boot-data"]['config-file'].values():
1116 # TODO Where this file content is present???
1117 cfg_source
= str(custom_config_file
["source"])
1118 om_cfgfile_list
.append({"dest": custom_config_file
["dest"],
1119 "content": cfg_source
})
1120 boot_data
['config-files'] = om_cfgfile_list
1122 db_vm
["boot_data"] = yaml
.safe_dump(boot_data
, default_flow_style
=True, width
=256)
1124 db_vms
.append(db_vm
)
1127 # table interfaces (internal/external interfaces)
1128 flavor_epa_interfaces
= []
1129 # for iface in chain(vdu.get("internal-interface").values(), vdu.get("external-interface").values()):
1130 for iface
in vdu
.get("interface").values():
1131 flavor_epa_interface
= {}
1132 iface_uuid
= str(uuid4())
1133 uuid_list
.append(iface_uuid
)
1136 "internal_name": get_str(iface
, "name", 255),
1139 flavor_epa_interface
["name"] = db_interface
["internal_name"]
1140 if iface
.get("virtual-interface").get("vpci"):
1141 db_interface
["vpci"] = get_str(iface
.get("virtual-interface"), "vpci", 12)
1142 flavor_epa_interface
["vpci"] = db_interface
["vpci"]
1144 if iface
.get("virtual-interface").get("bandwidth"):
1145 bps
= int(iface
.get("virtual-interface").get("bandwidth"))
1146 db_interface
["bw"] = int(math
.ceil(bps
/ 1000000.0))
1147 flavor_epa_interface
["bandwidth"] = "{} Mbps".format(db_interface
["bw"])
1149 if iface
.get("virtual-interface").get("type") == "OM-MGMT":
1150 db_interface
["type"] = "mgmt"
1151 elif iface
.get("virtual-interface").get("type") in ("VIRTIO", "E1000", "PARAVIRT"):
1152 db_interface
["type"] = "bridge"
1153 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1154 elif iface
.get("virtual-interface").get("type") in ("SR-IOV", "PCI-PASSTHROUGH"):
1155 db_interface
["type"] = "data"
1156 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1157 flavor_epa_interface
["dedicated"] = "no" if iface
["virtual-interface"]["type"] == "SR-IOV" \
1159 flavor_epa_interfaces
.append(flavor_epa_interface
)
1161 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vdu[{}]':'interface':'virtual"
1162 "-interface':'type':'{}'. Interface type is not supported".format(
1163 vnfd_id
, vdu_id
, iface
.get("virtual-interface").get("type")),
1164 httperrors
.Bad_Request
)
1166 if iface
.get("mgmt-interface"):
1167 db_interface
["type"] = "mgmt"
1169 if iface
.get("external-connection-point-ref"):
1171 cp
= vnfd
.get("connection-point")[iface
.get("external-connection-point-ref")]
1172 db_interface
["external_name"] = get_str(cp
, "name", 255)
1173 cp_name2iface_uuid
[db_interface
["external_name"]] = iface_uuid
1174 cp_name2vdu_id
[db_interface
["external_name"]] = vdu_id
1175 cp_name2vm_uuid
[db_interface
["external_name"]] = vm_uuid
1176 cp_name2db_interface
[db_interface
["external_name"]] = db_interface
1177 for cp_descriptor
in vnfd_descriptor
["connection-point"]:
1178 if cp_descriptor
["name"] == db_interface
["external_name"]:
1183 if vdu_id
in vdu_id2cp_name
:
1184 vdu_id2cp_name
[vdu_id
] = None # more than two connecdtion point for this VDU
1186 vdu_id2cp_name
[vdu_id
] = db_interface
["external_name"]
1189 if str(cp_descriptor
.get("port-security-enabled")).lower() == "false":
1190 db_interface
["port_security"] = 0
1191 elif str(cp_descriptor
.get("port-security-enabled")).lower() == "true":
1192 db_interface
["port_security"] = 1
1194 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1195 "'interface[{iface}]':'vnfd-connection-point-ref':'{cp}' is not present"
1196 " at connection-point".format(
1197 vnf
=vnfd_id
, vdu
=vdu_id
, iface
=iface
["name"],
1198 cp
=iface
.get("vnfd-connection-point-ref")),
1199 httperrors
.Bad_Request
)
1200 elif iface
.get("internal-connection-point-ref"):
1202 for icp_descriptor
in vdu_descriptor
["internal-connection-point"]:
1203 if icp_descriptor
["id"] == str(iface
.get("internal-connection-point-ref")):
1206 raise KeyError("does not exist at vdu:internal-connection-point")
1209 for vld
in vnfd
.get("internal-vld").values():
1210 for cp
in vld
.get("internal-connection-point").values():
1211 if cp
.get("id-ref") == iface
.get("internal-connection-point-ref"):
1213 raise KeyError("is referenced by more than one 'internal-vld'")
1217 raise KeyError("is not referenced by any 'internal-vld'")
1219 db_interface
["net_id"] = net_id2uuid
[icp_vld
.get("id")]
1220 if str(icp_descriptor
.get("port-security-enabled")).lower() == "false":
1221 db_interface
["port_security"] = 0
1222 elif str(icp_descriptor
.get("port-security-enabled")).lower() == "true":
1223 db_interface
["port_security"] = 1
1224 if icp
.get("ip-address"):
1225 if not icp_vld
.get("ip-profile-ref"):
1227 db_interface
["ip_address"] = str(icp
.get("ip-address"))
1228 except KeyError as e
:
1229 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1230 "'interface[{iface}]':'internal-connection-point-ref':'{cp}'"
1232 vnf
=vnfd_id
, vdu
=vdu_id
, iface
=iface
["name"],
1233 cp
=iface
.get("internal-connection-point-ref"), msg
=str(e
)),
1234 httperrors
.Bad_Request
)
1235 if iface
.get("position"):
1236 db_interface
["created_at"] = int(iface
.get("position")) * 50
1237 if iface
.get("mac-address"):
1238 db_interface
["mac"] = str(iface
.get("mac-address"))
1239 db_interfaces
.append(db_interface
)
1243 "name": get_str(vdu
, "name", 250) + "-flv",
1244 "vcpus": int(vdu
["vm-flavor"].get("vcpu-count", 1)),
1245 "ram": int(vdu
["vm-flavor"].get("memory-mb", 1)),
1246 "disk": int(vdu
["vm-flavor"].get("storage-gb", 0)),
1248 # TODO revise the case of several numa-node-policy node
1252 extended
["devices"] = devices
1253 if flavor_epa_interfaces
:
1254 numa
["interfaces"] = flavor_epa_interfaces
1255 if vdu
.get("guest-epa"): # TODO or dedicated_int:
1256 epa_vcpu_set
= False
1257 if vdu
["guest-epa"].get("numa-node-policy"): # TODO or dedicated_int:
1258 numa_node_policy
= vdu
["guest-epa"].get("numa-node-policy")
1259 if numa_node_policy
.get("node"):
1260 numa_node
= next(iter(numa_node_policy
["node"].values()))
1261 if numa_node
.get("num-cores"):
1262 numa
["cores"] = numa_node
["num-cores"]
1264 if numa_node
.get("paired-threads"):
1265 if numa_node
["paired-threads"].get("num-paired-threads"):
1266 numa
["paired-threads"] = int(numa_node
["paired-threads"]["num-paired-threads"])
1268 if len(numa_node
["paired-threads"].get("paired-thread-ids")):
1269 numa
["paired-threads-id"] = []
1270 for pair
in numa_node
["paired-threads"]["paired-thread-ids"].values():
1271 numa
["paired-threads-id"].append(
1272 (str(pair
["thread-a"]), str(pair
["thread-b"]))
1274 if numa_node
.get("num-threads"):
1275 numa
["threads"] = int(numa_node
["num-threads"])
1277 if numa_node
.get("memory-mb"):
1278 numa
["memory"] = max(int(numa_node
["memory-mb"] / 1024), 1)
1279 if vdu
["guest-epa"].get("mempage-size"):
1280 if vdu
["guest-epa"]["mempage-size"] != "SMALL":
1281 numa
["memory"] = max(int(db_flavor
["ram"] / 1024), 1)
1282 if vdu
["guest-epa"].get("cpu-pinning-policy") and not epa_vcpu_set
:
1283 if vdu
["guest-epa"]["cpu-pinning-policy"] == "DEDICATED":
1284 if vdu
["guest-epa"].get("cpu-thread-pinning-policy") and \
1285 vdu
["guest-epa"]["cpu-thread-pinning-policy"] != "PREFER":
1286 numa
["cores"] = max(db_flavor
["vcpus"], 1)
1288 numa
["threads"] = max(db_flavor
["vcpus"], 1)
1290 if vdu
["guest-epa"].get("cpu-quota") and not epa_vcpu_set
:
1291 cpuquota
= get_resource_allocation_params(vdu
["guest-epa"].get("cpu-quota"))
1293 extended
["cpu-quota"] = cpuquota
1294 if vdu
["guest-epa"].get("mem-quota"):
1295 vduquota
= get_resource_allocation_params(vdu
["guest-epa"].get("mem-quota"))
1297 extended
["mem-quota"] = vduquota
1298 if vdu
["guest-epa"].get("disk-io-quota"):
1299 diskioquota
= get_resource_allocation_params(vdu
["guest-epa"].get("disk-io-quota"))
1301 extended
["disk-io-quota"] = diskioquota
1302 if vdu
["guest-epa"].get("vif-quota"):
1303 vifquota
= get_resource_allocation_params(vdu
["guest-epa"].get("vif-quota"))
1305 extended
["vif-quota"] = vifquota
1307 extended
["numas"] = [numa
]
1309 extended_text
= yaml
.safe_dump(extended
, default_flow_style
=True, width
=256)
1310 db_flavor
["extended"] = extended_text
1311 # look if flavor exist
1312 temp_flavor_dict
= {'disk': db_flavor
.get('disk', 0),
1313 'ram': db_flavor
.get('ram'),
1314 'vcpus': db_flavor
.get('vcpus'),
1315 'extended': db_flavor
.get('extended')
1317 existing_flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
1318 if existing_flavors
:
1319 flavor_uuid
= existing_flavors
[0]["uuid"]
1321 flavor_uuid
= str(uuid4())
1322 uuid_list
.append(flavor_uuid
)
1323 db_flavor
["uuid"] = flavor_uuid
1324 db_flavors
.append(db_flavor
)
1325 db_vm
["flavor_id"] = flavor_uuid
1327 # VNF affinity and antiaffinity
1328 for pg
in vnfd
.get("placement-groups").values():
1329 pg_name
= get_str(pg
, "name", 255)
1330 for vdu
in pg
.get("member-vdus").values():
1331 vdu_id
= get_str(vdu
, "member-vdu-ref", 255)
1332 if vdu_id
not in vdu_id2db_table_index
:
1333 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'placement-groups[{pg}]':"
1334 "'member-vdus':'{vdu}'. Reference to a non-existing vdu".format(
1335 vnf
=vnfd_id
, pg
=pg_name
, vdu
=vdu_id
),
1336 httperrors
.Bad_Request
)
1337 db_vms
[vdu_id2db_table_index
[vdu_id
]]["availability_zone"] = pg_name
1338 # TODO consider the case of isolation and not colocation
1339 # if pg.get("strategy") == "ISOLATION":
1341 # VNF mgmt configuration
1342 if vnfd
["mgmt-interface"].get("vdu-id"):
1343 mgmt_vdu_id
= get_str(vnfd
["mgmt-interface"], "vdu-id", 255)
1344 if mgmt_vdu_id
not in vdu_id2uuid
:
1345 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'vdu-id':"
1346 "'{vdu}'. Reference to a non-existing vdu".format(
1347 vnf
=vnfd_id
, vdu
=mgmt_vdu_id
),
1348 httperrors
.Bad_Request
)
1349 mgmt_access
["vm_id"] = vdu_id2uuid
[mgmt_vdu_id
]
1350 mgmt_access
["vdu-id"] = mgmt_vdu_id
1351 # if only one cp is defined by this VDU, mark this interface as of type "mgmt"
1352 if vdu_id2cp_name
.get(mgmt_vdu_id
):
1353 if cp_name2db_interface
[vdu_id2cp_name
[mgmt_vdu_id
]]:
1354 cp_name2db_interface
[vdu_id2cp_name
[mgmt_vdu_id
]]["type"] = "mgmt"
1356 if vnfd
["mgmt-interface"].get("ip-address"):
1357 mgmt_access
["ip-address"] = str(vnfd
["mgmt-interface"].get("ip-address"))
1358 if vnfd
["mgmt-interface"].get("cp") and vnfd
.get("vdu"):
1359 if vnfd
["mgmt-interface"]["cp"] not in cp_name2iface_uuid
:
1360 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'cp'['{cp}']. "
1361 "Reference to a non-existing connection-point".format(
1362 vnf
=vnfd_id
, cp
=vnfd
["mgmt-interface"]["cp"]),
1363 httperrors
.Bad_Request
)
1364 mgmt_access
["vm_id"] = cp_name2vm_uuid
[vnfd
["mgmt-interface"]["cp"]]
1365 mgmt_access
["interface_id"] = cp_name2iface_uuid
[vnfd
["mgmt-interface"]["cp"]]
1366 mgmt_access
["vdu-id"] = cp_name2vdu_id
[vnfd
["mgmt-interface"]["cp"]]
1367 # mark this interface as of type mgmt
1368 if cp_name2db_interface
[vnfd
["mgmt-interface"]["cp"]]:
1369 cp_name2db_interface
[vnfd
["mgmt-interface"]["cp"]]["type"] = "mgmt"
1371 default_user
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1374 mgmt_access
["default_user"] = default_user
1376 required
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1379 mgmt_access
["required"] = required
1381 password_
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}),
1384 mgmt_access
["password"] = password_
1387 db_vnf
["mgmt_access"] = yaml
.safe_dump(mgmt_access
, default_flow_style
=True, width
=256)
1389 db_vnfs
.append(db_vnf
)
1393 {"images": db_images
},
1394 {"flavors": db_flavors
},
1395 {"ip_profiles": db_ip_profiles
},
1397 {"interfaces": db_interfaces
},
1400 logger
.debug("create_vnf Deployment done vnfDict: %s",
1401 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
1402 mydb
.new_rows(db_tables
, uuid_list
)
1403 return vnfd_uuid_list
1404 except NfvoException
:
1406 except Exception as e
:
1407 logger
.error("Exception {}".format(e
))
1408 raise # NfvoException("Exception {}".format(e), httperrors.Bad_Request)
1411 @deprecated("Use new_vnfd_v3")
1412 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
1413 global global_config
1415 # Step 1. Check the VNF descriptor
1416 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
1417 # Step 2. Check tenant exist
1419 if tenant_id
!= "any":
1420 check_tenant(mydb
, tenant_id
)
1421 if "tenant_id" in vnf_descriptor
["vnf"]:
1422 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1423 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1424 httperrors
.Unauthorized
)
1426 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1427 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1428 if global_config
["auto_push_VNF_to_VIMs"]:
1429 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1431 # Step 4. Review the descriptor and add missing fields
1432 #print vnf_descriptor
1433 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1434 vnf_name
= vnf_descriptor
['vnf']['name']
1435 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1436 if "physical" in vnf_descriptor
['vnf']:
1437 del vnf_descriptor
['vnf']['physical']
1438 #print vnf_descriptor
1440 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1441 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1442 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1444 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1445 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1446 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1448 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1449 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1451 VNFCitem
["name"] = vnfc
['name']
1452 VNFCitem
["availability_zone"] = vnfc
.get('availability_zone')
1453 VNFCitem
["description"] = vnfc
.get("description", 'VM {} of the VNF {}'.format(vnfc
['name'],vnf_name
))
1455 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1458 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1459 myflavorDict
["description"] = VNFCitem
["description"]
1460 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1461 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1462 myflavorDict
["disk"] = vnfc
.get("disk", 0)
1463 myflavorDict
["extended"] = {}
1465 devices
= vnfc
.get("devices")
1467 myflavorDict
["extended"]["devices"] = devices
1470 # Mapping from processor models to rankings should be available somehow in the NFVO. They could be taken from VIM or directly from a new database table
1471 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1473 # Previous code has been commented
1474 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1475 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1476 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1477 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1479 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1481 # print "Error creating flavor: unknown processor model. Rollback successful."
1482 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1484 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1485 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1487 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1488 myflavorDict
['extended']['numas'] = vnfc
['numas']
1492 # Step 6.2 New flavors are created in the VIM
1493 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1495 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1496 VNFCitem
["flavor_id"] = flavor_id
1497 VNFCDict
[vnfc
['name']] = VNFCitem
1499 logger
.debug("Creating new images in the VIM for each VNFC")
1500 # Step 6.3 New images are created in the VIM
1501 #For each VNFC, we must create the appropriate image.
1502 #This "for" loop might be integrated with the previous one
1503 #In case this integration is made, the VNFCDict might become a VNFClist.
1504 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1505 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1507 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1508 image_dict
['universal_name']=vnfc
.get('image name')
1509 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1510 image_dict
['location']=vnfc
.get('VNFC image')
1511 #image_dict['new_location']=vnfc.get('image location')
1512 image_dict
['checksum']=vnfc
.get('image checksum')
1513 image_metadata_dict
= vnfc
.get('image metadata', None)
1514 image_metadata_str
= None
1515 if image_metadata_dict
is not None:
1516 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1517 image_dict
['metadata']=image_metadata_str
1518 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1519 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1520 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1521 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1522 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1523 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1524 if vnfc
.get("boot-data"):
1525 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1528 # Step 7. Storing the VNF descriptor in the repository
1529 if "descriptor" not in vnf_descriptor
["vnf"]:
1530 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1532 # Step 8. Adding the VNF to the NFVO DB
1533 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1535 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1536 _
, message
= rollback(mydb
, vims
, rollback_list
)
1537 if isinstance(e
, db_base_Exception
):
1538 error_text
= "Exception at database"
1539 elif isinstance(e
, KeyError):
1540 error_text
= "KeyError exception "
1541 e
.http_code
= httperrors
.Internal_Server_Error
1543 error_text
= "Exception at VIM"
1544 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1545 #logger.error("start_scenario %s", error_text)
1546 raise NfvoException(error_text
, e
.http_code
)
1549 @deprecated("Use new_vnfd_v3")
1550 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
1551 global global_config
1553 # Step 1. Check the VNF descriptor
1554 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
1555 # Step 2. Check tenant exist
1557 if tenant_id
!= "any":
1558 check_tenant(mydb
, tenant_id
)
1559 if "tenant_id" in vnf_descriptor
["vnf"]:
1560 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1561 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1562 httperrors
.Unauthorized
)
1564 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1565 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1566 if global_config
["auto_push_VNF_to_VIMs"]:
1567 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1569 # Step 4. Review the descriptor and add missing fields
1570 #print vnf_descriptor
1571 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1572 vnf_name
= vnf_descriptor
['vnf']['name']
1573 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1574 if "physical" in vnf_descriptor
['vnf']:
1575 del vnf_descriptor
['vnf']['physical']
1576 #print vnf_descriptor
1578 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1579 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1580 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1582 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1583 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1584 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1586 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1587 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1589 VNFCitem
["name"] = vnfc
['name']
1590 VNFCitem
["description"] = vnfc
.get("description", 'VM {} of the VNF {}'.format(vnfc
['name'],vnf_name
))
1592 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1595 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1596 myflavorDict
["description"] = VNFCitem
["description"]
1597 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1598 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1599 myflavorDict
["disk"] = vnfc
.get("disk", 0)
1600 myflavorDict
["extended"] = {}
1602 devices
= vnfc
.get("devices")
1604 myflavorDict
["extended"]["devices"] = devices
1607 # Mapping from processor models to rankings should be available somehow in the NFVO. They could be taken from VIM or directly from a new database table
1608 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1610 # Previous code has been commented
1611 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1612 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1613 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1614 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1616 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1618 # print "Error creating flavor: unknown processor model. Rollback successful."
1619 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1621 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1622 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1624 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1625 myflavorDict
['extended']['numas'] = vnfc
['numas']
1629 # Step 6.2 New flavors are created in the VIM
1630 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1632 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1633 VNFCitem
["flavor_id"] = flavor_id
1634 VNFCDict
[vnfc
['name']] = VNFCitem
1636 logger
.debug("Creating new images in the VIM for each VNFC")
1637 # Step 6.3 New images are created in the VIM
1638 #For each VNFC, we must create the appropriate image.
1639 #This "for" loop might be integrated with the previous one
1640 #In case this integration is made, the VNFCDict might become a VNFClist.
1641 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1642 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1644 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1645 image_dict
['universal_name']=vnfc
.get('image name')
1646 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1647 image_dict
['location']=vnfc
.get('VNFC image')
1648 #image_dict['new_location']=vnfc.get('image location')
1649 image_dict
['checksum']=vnfc
.get('image checksum')
1650 image_metadata_dict
= vnfc
.get('image metadata', None)
1651 image_metadata_str
= None
1652 if image_metadata_dict
is not None:
1653 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1654 image_dict
['metadata']=image_metadata_str
1655 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1656 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1657 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1658 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1659 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1660 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1661 if vnfc
.get("boot-data"):
1662 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1664 # Step 7. Storing the VNF descriptor in the repository
1665 if "descriptor" not in vnf_descriptor
["vnf"]:
1666 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1668 # Step 8. Adding the VNF to the NFVO DB
1669 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1671 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1672 _
, message
= rollback(mydb
, vims
, rollback_list
)
1673 if isinstance(e
, db_base_Exception
):
1674 error_text
= "Exception at database"
1675 elif isinstance(e
, KeyError):
1676 error_text
= "KeyError exception "
1677 e
.http_code
= httperrors
.Internal_Server_Error
1679 error_text
= "Exception at VIM"
1680 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1681 #logger.error("start_scenario %s", error_text)
1682 raise NfvoException(error_text
, e
.http_code
)
1685 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
1686 #check valid tenant_id
1687 check_tenant(mydb
, tenant_id
)
1690 if tenant_id
!= "any":
1691 where_or
["tenant_id"] = tenant_id
1692 where_or
["public"] = True
1693 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1695 vnf_id
= vnf
["uuid"]
1696 filter_keys
= ('uuid', 'name', 'description', 'public', "tenant_id", "osm_id", "created_at")
1697 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.items() if k
in filter_keys
)
1698 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
1699 data
={'vnf' : filtered_content
}
1701 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
1702 SELECT
=('vms.uuid as uuid', 'vms.osm_id as osm_id', 'vms.name as name', 'vms.description as description',
1704 WHERE
={'vnfs.uuid': vnf_id
} )
1705 if len(content
) != 0:
1706 #raise NfvoException("vnf '{}' not found".format(vnf_id), httperrors.Not_Found)
1707 # change boot_data into boot-data
1709 if vm
.get("boot_data"):
1710 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
1713 data
['vnf']['VNFC'] = content
1714 #TODO: GET all the information from a VNFC and include it in the output.
1717 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
1718 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
1719 WHERE
={'vnfs.uuid': vnf_id
} )
1720 data
['vnf']['nets'] = content
1722 #GET ip-profile for each net
1723 for net
in data
['vnf']['nets']:
1724 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1725 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1726 WHERE
={'net_id': net
["uuid"]} )
1727 if len(ipprofiles
)==1:
1728 net
["ip_profile"] = ipprofiles
[0]
1729 elif len(ipprofiles
)>1:
1730 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), httperrors
.Bad_Request
)
1733 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1735 #GET External Interfaces
1736 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1737 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1738 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1739 WHERE
={'vnfs.uuid': vnf_id
, 'interfaces.external_name<>': None} )
1741 data
['vnf']['external-connections'] = content
1746 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1747 # Check tenant exist
1748 if tenant_id
!= "any":
1749 check_tenant(mydb
, tenant_id
)
1750 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1751 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1755 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1757 if tenant_id
!= "any":
1758 where_or
["tenant_id"] = tenant_id
1759 where_or
["public"] = True
1760 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1761 vnf_id
= vnf
["uuid"]
1763 # "Getting the list of flavors and tenants of the VNF"
1764 flavorList
= get_flavorlist(mydb
, vnf_id
)
1765 if len(flavorList
)==0:
1766 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1768 imageList
= get_imagelist(mydb
, vnf_id
)
1769 if len(imageList
)==0:
1770 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1772 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1774 raise NfvoException("vnf '{}' not found".format(vnf_id
), httperrors
.Not_Found
)
1777 for flavor
in flavorList
:
1778 #check if flavor is used by other vnf
1780 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1782 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1784 #flavor not used, must be deleted
1786 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id': flavor
})
1787 for flavor_vim
in c
:
1788 if not flavor_vim
['created']: # skip this flavor because not created by openmano
1792 for vim
in vims
.values():
1793 if vim
["config"]["datacenter_tenant_id"] == flavor_vim
["datacenter_vim_id"]:
1799 myvim
.delete_flavor(flavor_vim
["vim_id"])
1800 except vimconn
.vimconnNotFoundException
:
1801 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"],
1802 flavor_vim
["datacenter_vim_id"] )
1803 except vimconn
.vimconnException
as e
:
1804 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1805 flavor_vim
["vim_id"], flavor_vim
["datacenter_vim_id"], type(e
).__name
__, str(e
))
1806 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"],
1807 flavor_vim
["datacenter_vim_id"]))
1808 # delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1809 mydb
.delete_row_by_id('flavors', flavor
)
1810 except db_base_Exception
as e
:
1811 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1812 undeletedItems
.append("flavor {}".format(flavor
))
1815 for image
in imageList
:
1817 #check if image is used by other vnf
1818 c
= mydb
.get_rows(FROM
='vms', WHERE
=[{'image_id': image
}, {'image_list LIKE ': '%' + image
+ '%'}])
1820 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1822 #image not used, must be deleted
1824 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1826 if image_vim
["datacenter_vim_id"] not in vims
: # TODO change to datacenter_tenant_id
1828 if image_vim
['created']=='false': #skip this image because not created by openmano
1830 myvim
=vims
[ image_vim
["datacenter_id"] ]
1832 myvim
.delete_image(image_vim
["vim_id"])
1833 except vimconn
.vimconnNotFoundException
as e
:
1834 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1835 except vimconn
.vimconnException
as e
:
1836 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1837 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1838 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1839 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1840 mydb
.delete_row_by_id('images', image
)
1841 except db_base_Exception
as e
:
1842 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1843 undeletedItems
.append("image {}".format(image
))
1845 return vnf_id
+ " " + vnf
["name"]
1847 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1850 @deprecated("Not used")
1851 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1852 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1856 return -httperrors
.Not_Found
, "datacenter '{}' not found".format(datacenter_name
)
1857 myvim
= next(iter(vims
.values()))
1858 result
,servers
= myvim
.get_hosts_info()
1860 return result
, servers
1861 topology
= {'name':myvim
['name'] , 'servers': servers
}
1862 return result
, topology
1865 def get_hosts(mydb
, nfvo_tenant_id
):
1866 vims
= get_vim(mydb
, nfvo_tenant_id
)
1868 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), httperrors
.Not_Found
)
1870 #print "nfvo.datacenter_action() error. Several datacenters found"
1871 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
1872 myvim
= next(iter(vims
.values()))
1874 hosts
= myvim
.get_hosts()
1875 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1877 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1879 server
={'name':host
['name'], 'vms':[]}
1880 for vm
in host
['instances']:
1881 #get internal name and model
1883 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1884 WHERE
={'vim_vm_id':vm
['id']} )
1886 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1888 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1890 except db_base_Exception
as e
:
1891 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1892 datacenter
['Datacenters'][0]['servers'].append(server
)
1893 #return -400, "en construccion"
1895 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1897 except vimconn
.vimconnException
as e
:
1898 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1901 @deprecated("Use new_nsd_v3")
1902 def new_scenario(mydb
, tenant_id
, topo
):
1904 # result, vims = get_vim(mydb, tenant_id)
1906 # return result, vims
1908 if tenant_id
!= "any":
1909 check_tenant(mydb
, tenant_id
)
1910 if "tenant_id" in topo
:
1911 if topo
["tenant_id"] != tenant_id
:
1912 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1913 httperrors
.Unauthorized
)
1917 #1.1: get VNFs and external_networks (other_nets).
1919 other_nets
={} #external_networks, bridge_networks and data_networkds
1920 nodes
= topo
['topology']['nodes']
1921 for k
in nodes
.keys():
1922 if nodes
[k
]['type'] == 'VNF':
1924 vnfs
[k
]['ifaces'] = {}
1925 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1926 other_nets
[k
] = nodes
[k
]
1927 other_nets
[k
]['external']=True
1928 elif nodes
[k
]['type'] == 'network':
1929 other_nets
[k
] = nodes
[k
]
1930 other_nets
[k
]['external']=False
1933 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1934 for name
,vnf
in vnfs
.items():
1935 where
= {"OR": {"tenant_id": tenant_id
, 'public': "true"}}
1937 error_pos
= "'topology':'nodes':'" + name
+ "'"
1939 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1940 where
['uuid'] = vnf
['vnf_id']
1941 if 'VNF model' in vnf
:
1942 error_text
+= " 'VNF model' " + vnf
['VNF model']
1943 where
['name'] = vnf
['VNF model']
1945 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, httperrors
.Bad_Request
)
1947 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1951 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, httperrors
.Not_Found
)
1953 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", httperrors
.Conflict
)
1954 vnf
['uuid']=vnf_db
[0]['uuid']
1955 vnf
['description']=vnf_db
[0]['description']
1956 #get external interfaces
1957 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1958 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1959 WHERE
={'vnfs.uuid':vnf
['uuid'], 'external_name<>': None} )
1960 for ext_iface
in ext_ifaces
:
1961 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1963 #1.4 get list of connections
1964 conections
= topo
['topology']['connections']
1965 conections_list
= []
1966 conections_list_name
= []
1967 for k
in conections
.keys():
1968 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1969 ifaces_list
= conections
[k
]['nodes'].items()
1970 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1972 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1973 for k2
in conection_pair_list
:
1976 con_type
= conections
[k
].get("type", "link")
1977 if con_type
!= "link":
1979 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), httperrors
.Bad_Request
)
1980 other_nets
[k
] = {'external': False}
1981 if conections
[k
].get("graph"):
1982 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1983 ifaces_list
.append( (k
, None) )
1986 if con_type
== "external_network":
1987 other_nets
[k
]['external'] = True
1988 if conections
[k
].get("model"):
1989 other_nets
[k
]["model"] = conections
[k
]["model"]
1991 other_nets
[k
]["model"] = k
1992 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1993 other_nets
[k
]["model"] = con_type
1995 conections_list_name
.append(k
)
1996 conections_list
.append(set(ifaces_list
)) #from list to set to operate as a set (this conversion removes elements that are repeated in a list)
1997 #print set(ifaces_list)
1998 #check valid VNF and iface names
1999 for iface
in ifaces_list
:
2000 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
2001 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
2002 str(k
), iface
[0]), httperrors
.Not_Found
)
2003 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
2004 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
2005 str(k
), iface
[0], iface
[1]), httperrors
.Not_Found
)
2007 #1.5 unify connections from the pair list to a consolidated list
2009 while index
< len(conections_list
):
2011 while index2
< len(conections_list
):
2012 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
2013 conections_list
[index
] |
= conections_list
[index2
]
2014 del conections_list
[index2
]
2015 del conections_list_name
[index2
]
2018 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
2020 #for k in conections_list:
2025 #1.6 Delete non external nets
2026 # for k in other_nets.keys():
2027 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
2028 # for con in conections_list:
2030 # for index in range(0,len(con)):
2031 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
2032 # for index in delete_indexes:
2035 #1.7: Check external_ports are present at database table datacenter_nets
2036 for k
,net
in other_nets
.items():
2037 error_pos
= "'topology':'nodes':'" + k
+ "'"
2038 if net
['external']==False:
2039 if 'name' not in net
:
2041 if 'model' not in net
:
2042 raise NfvoException("needed a 'model' at " + error_pos
, httperrors
.Bad_Request
)
2043 if net
['model']=='bridge_net':
2044 net
['type']='bridge';
2045 elif net
['model']=='dataplane_net':
2048 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, httperrors
.Not_Found
)
2050 #IF we do not want to check that external network exist at datacenter
2055 # if 'net_id' in net:
2056 # error_text += " 'net_id' " + net['net_id']
2057 # WHERE_['uuid'] = net['net_id']
2058 # if 'model' in net:
2059 # error_text += " 'model' " + net['model']
2060 # WHERE_['name'] = net['model']
2061 # if len(WHERE_) == 0:
2062 # return -httperrors.Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
2063 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
2064 # FROM='datacenter_nets', WHERE=WHERE_ )
2066 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
2068 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
2069 # return -httperrors.Bad_Request, "unknown " +error_text+ " at " + error_pos
2071 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
2072 # return -httperrors.Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
2073 # other_nets[k].update(net_db[0])
2076 net_nb
=0 #Number of nets
2077 for con
in conections_list
:
2078 #check if this is connected to a external net
2082 for index
in range(0,len(con
)):
2083 #check if this is connected to a external net
2084 for net_key
in other_nets
.keys():
2085 if con
[index
][0]==net_key
:
2086 if other_net_index
>=0:
2087 error_text
= "There is some interface connected both to net '{}' and net '{}'".format(
2088 con
[other_net_index
][0], net_key
)
2089 #print "nfvo.new_scenario " + error_text
2090 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2092 other_net_index
= index
2093 net_target
= net_key
2095 #print "other_net_index", other_net_index
2097 if other_net_index
>=0:
2098 del con
[other_net_index
]
2099 #IF we do not want to check that external network exist at datacenter
2100 if other_nets
[net_target
]['external'] :
2101 if "name" not in other_nets
[net_target
]:
2102 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
2103 if other_nets
[net_target
]["type"] == "external_network":
2104 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
2105 other_nets
[net_target
]["type"] = "data"
2107 other_nets
[net_target
]["type"] = "bridge"
2109 # if other_nets[net_target]['external'] :
2110 # type_='data' if len(con)>1 else 'ptp' #an external net is connected to a external port, so it is ptp if only one connection is done to this net
2111 # if type_=='data' and other_nets[net_target]['type']=="ptp":
2112 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
2113 # print "nfvo.new_scenario " + error_text
2114 # return -httperrors.Bad_Request, error_text
2117 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
2120 net_type_bridge
=False
2122 net_target
= "__-__net"+str(net_nb
)
2123 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
2124 'description':"net-{} in scenario {}".format(net_nb
,topo
['name']),
2127 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
2128 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
2129 if iface_type
=='mgmt' or iface_type
=='bridge':
2130 net_type_bridge
= True
2132 net_type_data
= True
2133 if net_type_bridge
and net_type_data
:
2134 error_text
= "Error connection interfaces of bridge type with data type. Firs node {}, iface {}".format(iface
[0], iface
[1])
2135 #print "nfvo.new_scenario " + error_text
2136 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2137 elif net_type_bridge
:
2140 type_
='data' if len(con
)>2 else 'ptp'
2141 net_list
[net_target
]['type'] = type_
2144 error_text
= "Error connection node {} : {} does not match any VNF or interface".format(iface
[0], iface
[1])
2145 #print "nfvo.new_scenario " + error_text
2147 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2149 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
2150 #1.8.1 obtain management net
2151 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
2152 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
2153 #1.8.2 check all interfaces from all vnfs
2155 add_mgmt_net
= False
2156 for vnf
in vnfs
.values():
2157 for iface
in vnf
['ifaces'].values():
2158 if iface
['type']=='mgmt' and 'net_key' not in iface
:
2159 #iface not connected
2160 iface
['net_key'] = 'mgmt'
2162 if add_mgmt_net
and 'mgmt' not in net_list
:
2163 net_list
['mgmt']=mgmt_net
[0]
2164 net_list
['mgmt']['external']=True
2165 net_list
['mgmt']['graph']={'visible':False}
2167 net_list
.update(other_nets
)
2169 #print 'net_list', net_list
2174 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
2175 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
2176 'tenant_id':tenant_id
, 'name':topo
['name'],
2177 'description':topo
.get('description',topo
['name']),
2178 'public': topo
.get('public', False)
2184 @deprecated("Use new_nsd_v3")
2185 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
2186 """ This creates a new scenario for version 0.2 and 0.3"""
2187 scenario
= scenario_dict
["scenario"]
2188 if tenant_id
!= "any":
2189 check_tenant(mydb
, tenant_id
)
2190 if "tenant_id" in scenario
:
2191 if scenario
["tenant_id"] != tenant_id
:
2192 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
2193 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
2194 scenario
["tenant_id"], tenant_id
), httperrors
.Unauthorized
)
2198 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
2199 for name
,vnf
in scenario
["vnfs"].items():
2200 where
= {"OR": {"tenant_id": tenant_id
, 'public': "true"}}
2202 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
2204 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
2205 where
['uuid'] = vnf
['vnf_id']
2206 if 'vnf_name' in vnf
:
2207 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
2208 where
['name'] = vnf
['vnf_name']
2210 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, httperrors
.Bad_Request
)
2211 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
2214 if len(vnf_db
) == 0:
2215 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, httperrors
.Not_Found
)
2216 elif len(vnf_db
) > 1:
2217 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", httperrors
.Conflict
)
2218 vnf
['uuid'] = vnf_db
[0]['uuid']
2219 vnf
['description'] = vnf_db
[0]['description']
2221 # get external interfaces
2222 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
2223 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
2224 WHERE
={'vnfs.uuid':vnf
['uuid'], 'external_name<>': None} )
2225 for ext_iface
in ext_ifaces
:
2226 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
2227 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
2229 # 2: Insert net_key and ip_address at every vnf interface
2230 for net_name
, net
in scenario
["networks"].items():
2231 net_type_bridge
= False
2232 net_type_data
= False
2233 for iface_dict
in net
["interfaces"]:
2234 if version
== "0.2":
2235 temp_dict
= iface_dict
2237 elif version
== "0.3":
2238 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
2239 ip_address
= iface_dict
.get('ip_address', None)
2240 for vnf
, iface
in temp_dict
.items():
2241 if vnf
not in scenario
["vnfs"]:
2242 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
2244 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2245 raise NfvoException(error_text
, httperrors
.Not_Found
)
2246 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
2247 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
2248 .format(net_name
, iface
)
2249 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2250 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2251 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
2252 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
2253 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
2254 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2255 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2256 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
2257 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
2258 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
2259 if iface_type
== 'mgmt' or iface_type
== 'bridge':
2260 net_type_bridge
= True
2262 net_type_data
= True
2264 if net_type_bridge
and net_type_data
:
2265 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
2267 # logger.debug("nfvo.new_scenario " + error_text)
2268 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2269 elif net_type_bridge
:
2272 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
2274 if net
.get("implementation"): # for v0.3
2275 if type_
== "bridge" and net
["implementation"] == "underlay":
2276 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
2277 "'network':'{}'".format(net_name
)
2278 # logger.debug(error_text)
2279 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2280 elif type_
!= "bridge" and net
["implementation"] == "overlay":
2281 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
2282 "'network':'{}'".format(net_name
)
2283 # logger.debug(error_text)
2284 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2285 net
.pop("implementation")
2286 if "type" in net
and version
== "0.3": # for v0.3
2287 if type_
== "data" and net
["type"] == "e-line":
2288 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
2289 "'e-line' at 'network':'{}'".format(net_name
)
2290 # logger.debug(error_text)
2291 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2292 elif type_
== "ptp" and net
["type"] == "e-lan":
2296 net
['name'] = net_name
2297 net
['external'] = net
.get('external', False)
2299 # 3: insert at database
2300 scenario
["nets"] = scenario
["networks"]
2301 scenario
['tenant_id'] = tenant_id
2302 scenario_id
= mydb
.new_scenario(scenario
)
2306 def new_nsd_v3(mydb
, tenant_id
, nsd_descriptor
):
2308 Parses an OSM IM nsd_catalog and insert at DB
2311 :param nsd_descriptor:
2312 :return: The list of created NSD ids
2315 mynsd
= nsd_catalog
.nsd()
2317 pybindJSONDecoder
.load_ietf_json(nsd_descriptor
, None, None, obj
=mynsd
, skip_unknown
=True)
2318 except Exception as e
:
2319 raise NfvoException("Error. Invalid NS descriptor format: " + str(e
), httperrors
.Bad_Request
)
2323 db_sce_interfaces
= []
2326 db_sce_rsp_hops
= []
2327 db_sce_classifiers
= []
2328 db_sce_classifier_matches
= []
2330 db_ip_profiles_index
= 0
2333 for nsd_yang
in mynsd
.nsd_catalog
.nsd
.values():
2334 nsd
= nsd_yang
.get()
2337 scenario_uuid
= str(uuid4())
2338 uuid_list
.append(scenario_uuid
)
2339 nsd_uuid_list
.append(scenario_uuid
)
2341 "uuid": scenario_uuid
,
2342 "osm_id": get_str(nsd
, "id", 255),
2343 "name": get_str(nsd
, "name", 255),
2344 "description": get_str(nsd
, "description", 255),
2345 "tenant_id": tenant_id
,
2346 "vendor": get_str(nsd
, "vendor", 255),
2347 "short_name": get_str(nsd
, "short-name", 255),
2348 "descriptor": str(nsd_descriptor
)[:60000],
2350 db_scenarios
.append(db_scenario
)
2352 # table sce_vnfs (constituent-vnfd)
2353 vnf_index2scevnf_uuid
= {}
2354 vnf_index2vnf_uuid
= {}
2355 for vnf
in nsd
.get("constituent-vnfd").values():
2356 existing_vnf
= mydb
.get_rows(FROM
="vnfs", WHERE
={'osm_id': str(vnf
["vnfd-id-ref"])[:255],
2357 'tenant_id': tenant_id
})
2358 if not existing_vnf
:
2359 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'constituent-vnfd':'vnfd-id-ref':"
2360 "'{}'. Reference to a non-existing VNFD in the catalog".format(
2361 str(nsd
["id"]), str(vnf
["vnfd-id-ref"])[:255]),
2362 httperrors
.Bad_Request
)
2363 sce_vnf_uuid
= str(uuid4())
2364 uuid_list
.append(sce_vnf_uuid
)
2366 "uuid": sce_vnf_uuid
,
2367 "scenario_id": scenario_uuid
,
2368 # "name": get_str(vnf, "member-vnf-index", 255),
2369 "name": existing_vnf
[0]["name"][:200] + "." + get_str(vnf
, "member-vnf-index", 50),
2370 "vnf_id": existing_vnf
[0]["uuid"],
2371 "member_vnf_index": str(vnf
["member-vnf-index"]),
2372 # TODO 'start-by-default': True
2374 vnf_index2scevnf_uuid
[str(vnf
['member-vnf-index'])] = sce_vnf_uuid
2375 vnf_index2vnf_uuid
[str(vnf
['member-vnf-index'])] = existing_vnf
[0]["uuid"]
2376 db_sce_vnfs
.append(db_sce_vnf
)
2378 # table ip_profiles (ip-profiles)
2379 ip_profile_name2db_table_index
= {}
2380 for ip_profile
in nsd
.get("ip-profiles").values():
2382 "ip_version": str(ip_profile
["ip-profile-params"].get("ip-version", "ipv4")),
2383 "subnet_address": str(ip_profile
["ip-profile-params"].get("subnet-address")),
2384 "gateway_address": str(ip_profile
["ip-profile-params"].get("gateway-address")),
2385 "dhcp_enabled": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("enabled", True)),
2386 "dhcp_start_address": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("start-address")),
2387 "dhcp_count": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("count")),
2390 for dns
in ip_profile
["ip-profile-params"]["dns-server"].values():
2391 dns_list
.append(str(dns
.get("address")))
2392 db_ip_profile
["dns_address"] = ";".join(dns_list
)
2393 if ip_profile
["ip-profile-params"].get('security-group'):
2394 db_ip_profile
["security_group"] = ip_profile
["ip-profile-params"]['security-group']
2395 ip_profile_name2db_table_index
[str(ip_profile
["name"])] = db_ip_profiles_index
2396 db_ip_profiles_index
+= 1
2397 db_ip_profiles
.append(db_ip_profile
)
2399 # table sce_nets (internal-vld)
2400 for vld
in nsd
.get("vld").values():
2401 sce_net_uuid
= str(uuid4())
2402 uuid_list
.append(sce_net_uuid
)
2404 "uuid": sce_net_uuid
,
2405 "name": get_str(vld
, "name", 255),
2406 "scenario_id": scenario_uuid
,
2408 "multipoint": not vld
.get("type") == "ELINE",
2409 "osm_id": get_str(vld
, "id", 255),
2411 "description": get_str(vld
, "description", 255),
2413 # guess type of network
2414 if vld
.get("mgmt-network"):
2415 db_sce_net
["type"] = "bridge"
2416 db_sce_net
["external"] = True
2417 elif vld
.get("provider-network").get("overlay-type") == "VLAN":
2418 db_sce_net
["type"] = "data"
2420 # later on it will be fixed to bridge or data depending on the type of interfaces attached to it
2421 db_sce_net
["type"] = None
2422 db_sce_nets
.append(db_sce_net
)
2424 # ip-profile, link db_ip_profile with db_sce_net
2425 if vld
.get("ip-profile-ref"):
2426 ip_profile_name
= vld
.get("ip-profile-ref")
2427 if ip_profile_name
not in ip_profile_name2db_table_index
:
2428 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'ip-profile-ref':'{}'."
2429 " Reference to a non-existing 'ip_profiles'".format(
2430 str(nsd
["id"]), str(vld
["id"]), str(vld
["ip-profile-ref"])),
2431 httperrors
.Bad_Request
)
2432 db_ip_profiles
[ip_profile_name2db_table_index
[ip_profile_name
]]["sce_net_id"] = sce_net_uuid
2433 elif vld
.get("vim-network-name"):
2434 db_sce_net
["vim_network_name"] = get_str(vld
, "vim-network-name", 255)
2437 # table sce_interfaces (vld:vnfd-connection-point-ref)
2438 for iface
in vld
.get("vnfd-connection-point-ref").values():
2439 # Check if there are VDUs in the descriptor
2440 vnf_index
= str(iface
['member-vnf-index-ref'])
2441 existing_vdus
= mydb
.get_rows(SELECT
=('vms.uuid'), FROM
="vms", WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
]})
2443 # check correct parameters
2444 if vnf_index
not in vnf_index2vnf_uuid
:
2445 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2446 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2447 "'nsd':'constituent-vnfd'".format(
2448 str(nsd
["id"]), str(vld
["id"]), str(iface
["member-vnf-index-ref"])),
2449 httperrors
.Bad_Request
)
2451 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid', 'i.type as iface_type'),
2452 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2453 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2454 'external_name': get_str(iface
, "vnfd-connection-point-ref",
2456 if not existing_ifaces
:
2457 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2458 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2459 "connection-point name at VNFD '{}'".format(
2460 str(nsd
["id"]), str(vld
["id"]), str(iface
["vnfd-connection-point-ref"]),
2461 str(iface
.get("vnfd-id-ref"))[:255]),
2462 httperrors
.Bad_Request
)
2463 interface_uuid
= existing_ifaces
[0]["uuid"]
2464 if existing_ifaces
[0]["iface_type"] == "data":
2465 db_sce_net
["type"] = "data"
2466 sce_interface_uuid
= str(uuid4())
2467 uuid_list
.append(sce_net_uuid
)
2468 iface_ip_address
= None
2469 if iface
.get("ip-address"):
2470 iface_ip_address
= str(iface
.get("ip-address"))
2471 db_sce_interface
= {
2472 "uuid": sce_interface_uuid
,
2473 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2474 "sce_net_id": sce_net_uuid
,
2475 "interface_id": interface_uuid
,
2476 "ip_address": iface_ip_address
,
2478 db_sce_interfaces
.append(db_sce_interface
)
2479 if not db_sce_net
["type"]:
2480 db_sce_net
["type"] = "bridge"
2482 # table sce_vnffgs (vnffgd)
2483 for vnffg
in nsd
.get("vnffgd").values():
2484 sce_vnffg_uuid
= str(uuid4())
2485 uuid_list
.append(sce_vnffg_uuid
)
2487 "uuid": sce_vnffg_uuid
,
2488 "name": get_str(vnffg
, "name", 255),
2489 "scenario_id": scenario_uuid
,
2490 "vendor": get_str(vnffg
, "vendor", 255),
2491 "description": get_str(vld
, "description", 255),
2493 db_sce_vnffgs
.append(db_sce_vnffg
)
2496 for rsp
in vnffg
.get("rsp").values():
2497 sce_rsp_uuid
= str(uuid4())
2498 uuid_list
.append(sce_rsp_uuid
)
2500 "uuid": sce_rsp_uuid
,
2501 "name": get_str(rsp
, "name", 255),
2502 "sce_vnffg_id": sce_vnffg_uuid
,
2503 "id": get_str(rsp
, "id", 255), # only useful to link with classifiers; will be removed later in the code
2505 db_sce_rsps
.append(db_sce_rsp
)
2506 for iface
in rsp
.get("vnfd-connection-point-ref").values():
2507 vnf_index
= str(iface
['member-vnf-index-ref'])
2508 if_order
= int(iface
['order'])
2509 # check correct parameters
2510 if vnf_index
not in vnf_index2vnf_uuid
:
2511 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2512 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2513 "'nsd':'constituent-vnfd'".format(
2514 str(nsd
["id"]), str(rsp
["id"]), str(iface
["member-vnf-index-ref"])),
2515 httperrors
.Bad_Request
)
2517 ingress_existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2518 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2520 'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2521 'external_name': get_str(iface
, "vnfd-ingress-connection-point-ref",
2523 if not ingress_existing_ifaces
:
2524 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2525 "-ref':'vnfd-ingress-connection-point-ref':'{}'. Reference to a non-existing "
2526 "connection-point name at VNFD '{}'".format(
2527 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-ingress-connection-point-ref"]),
2528 str(iface
.get("vnfd-id-ref"))[:255]), httperrors
.Bad_Request
)
2530 egress_existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2531 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2533 'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2534 'external_name': get_str(iface
, "vnfd-egress-connection-point-ref",
2536 if not egress_existing_ifaces
:
2537 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2538 "-ref':'vnfd-egress-connection-point-ref':'{}'. Reference to a non-existing "
2539 "connection-point name at VNFD '{}'".format(
2540 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-egress-connection-point-ref"]),
2541 str(iface
.get("vnfd-id-ref"))[:255]), HTTP_Bad_Request
)
2543 ingress_interface_uuid
= ingress_existing_ifaces
[0]["uuid"]
2544 egress_interface_uuid
= egress_existing_ifaces
[0]["uuid"]
2545 sce_rsp_hop_uuid
= str(uuid4())
2546 uuid_list
.append(sce_rsp_hop_uuid
)
2548 "uuid": sce_rsp_hop_uuid
,
2549 "if_order": if_order
,
2550 "ingress_interface_id": ingress_interface_uuid
,
2551 "egress_interface_id": egress_interface_uuid
,
2552 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2553 "sce_rsp_id": sce_rsp_uuid
,
2555 db_sce_rsp_hops
.append(db_sce_rsp_hop
)
2557 # deal with classifiers
2558 for classifier
in vnffg
.get("classifier").values():
2559 sce_classifier_uuid
= str(uuid4())
2560 uuid_list
.append(sce_classifier_uuid
)
2563 vnf_index
= str(classifier
['member-vnf-index-ref'])
2564 if vnf_index
not in vnf_index2vnf_uuid
:
2565 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'classifier[{}]':'vnfd-connection-point"
2566 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2567 "'nsd':'constituent-vnfd'".format(
2568 str(nsd
["id"]), str(classifier
["id"]), str(classifier
["member-vnf-index-ref"])),
2569 httperrors
.Bad_Request
)
2570 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2571 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2572 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2573 'external_name': get_str(classifier
, "vnfd-connection-point-ref",
2575 if not existing_ifaces
:
2576 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2577 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2578 "connection-point name at VNFD '{}'".format(
2579 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-connection-point-ref"]),
2580 str(iface
.get("vnfd-id-ref"))[:255]),
2581 httperrors
.Bad_Request
)
2582 interface_uuid
= existing_ifaces
[0]["uuid"]
2584 db_sce_classifier
= {
2585 "uuid": sce_classifier_uuid
,
2586 "name": get_str(classifier
, "name", 255),
2587 "sce_vnffg_id": sce_vnffg_uuid
,
2588 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2589 "interface_id": interface_uuid
,
2591 rsp_id
= get_str(classifier
, "rsp-id-ref", 255)
2592 rsp
= next((item
for item
in db_sce_rsps
if item
["id"] == rsp_id
), None)
2593 db_sce_classifier
["sce_rsp_id"] = rsp
["uuid"]
2594 db_sce_classifiers
.append(db_sce_classifier
)
2596 for match
in classifier
.get("match-attributes").values():
2597 sce_classifier_match_uuid
= str(uuid4())
2598 uuid_list
.append(sce_classifier_match_uuid
)
2599 db_sce_classifier_match
= {
2600 "uuid": sce_classifier_match_uuid
,
2601 "ip_proto": get_str(match
, "ip-proto", 2),
2602 "source_ip": get_str(match
, "source-ip-address", 16),
2603 "destination_ip": get_str(match
, "destination-ip-address", 16),
2604 "source_port": get_str(match
, "source-port", 5),
2605 "destination_port": get_str(match
, "destination-port", 5),
2606 "sce_classifier_id": sce_classifier_uuid
,
2608 db_sce_classifier_matches
.append(db_sce_classifier_match
)
2611 # remove unneeded id's in sce_rsps
2612 for rsp
in db_sce_rsps
:
2616 {"scenarios": db_scenarios
},
2617 {"sce_nets": db_sce_nets
},
2618 {"ip_profiles": db_ip_profiles
},
2619 {"sce_vnfs": db_sce_vnfs
},
2620 {"sce_interfaces": db_sce_interfaces
},
2621 {"sce_vnffgs": db_sce_vnffgs
},
2622 {"sce_rsps": db_sce_rsps
},
2623 {"sce_rsp_hops": db_sce_rsp_hops
},
2624 {"sce_classifiers": db_sce_classifiers
},
2625 {"sce_classifier_matches": db_sce_classifier_matches
},
2628 logger
.debug("new_nsd_v3 done: %s",
2629 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
2630 mydb
.new_rows(db_tables
, uuid_list
)
2631 return nsd_uuid_list
2632 except NfvoException
:
2634 except Exception as e
:
2635 logger
.error("Exception {}".format(e
))
2636 raise # NfvoException("Exception {}".format(e), httperrors.Bad_Request)
2639 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
2640 data
["uuid"] = scenario_id
2641 data
["tenant_id"] = tenant_id
2642 c
= mydb
.edit_scenario( data
)
2646 @deprecated("Use create_instance")
2647 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
2648 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2649 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
2650 vims
= {datacenter_id
: myvim
}
2651 myvim_tenant
= myvim
['tenant_id']
2652 datacenter_name
= myvim
['name']
2656 #print "Checking that the scenario_id exists and getting the scenario dictionary"
2657 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
=datacenter_id
)
2658 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
2659 scenarioDict
['datacenter_id'] = datacenter_id
2660 #print '================scenarioDict======================='
2661 #print json.dumps(scenarioDict, indent=4)
2662 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
2664 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
2665 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2667 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
2668 auxNetDict
['scenario'] = {}
2670 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
2671 for sce_net
in scenarioDict
['nets']:
2672 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
2674 myNetName
= "{}.{}".format(instance_scenario_name
, sce_net
['name'])
2675 myNetName
= myNetName
[0:255] #limit length
2676 myNetType
= sce_net
['type']
2678 myNetDict
["name"] = myNetName
2679 myNetDict
["type"] = myNetType
2680 myNetDict
["tenant_id"] = myvim_tenant
2681 myNetIPProfile
= sce_net
.get('ip_profile', None)
2682 myProviderNetwork
= sce_net
.get('provider_network', None)
2684 #We should use the dictionary as input parameter for new_network
2686 if not sce_net
["external"]:
2687 network_id
, _
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
, provider_network_profile
=myProviderNetwork
)
2688 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
2689 sce_net
['vim_id'] = network_id
2690 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
2691 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2692 sce_net
["created"] = True
2694 if sce_net
['vim_id'] == None:
2695 error_text
= "Error, datacenter '{}' does not have external network '{}'.".format(
2696 datacenter_name
, sce_net
['name'])
2697 _
, message
= rollback(mydb
, vims
, rollbackList
)
2698 logger
.error("nfvo.start_scenario: %s", error_text
)
2699 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2700 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
2701 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
2703 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
2704 #For each vnf net, we create it and we add it to instanceNetlist.
2706 for sce_vnf
in scenarioDict
['vnfs']:
2707 for net
in sce_vnf
['nets']:
2708 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
2710 myNetName
= "{}.{}".format(instance_scenario_name
,net
['name'])
2711 myNetName
= myNetName
[0:255] #limit length
2712 myNetType
= net
['type']
2714 myNetDict
["name"] = myNetName
2715 myNetDict
["type"] = myNetType
2716 myNetDict
["tenant_id"] = myvim_tenant
2717 myNetIPProfile
= net
.get('ip_profile', None)
2718 myProviderNetwork
= sce_net
.get('provider_network', None)
2721 #We should use the dictionary as input parameter for new_network
2722 network_id
, _
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
, provider_network_profile
=myProviderNetwork
)
2723 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
2724 net
['vim_id'] = network_id
2725 if sce_vnf
['uuid'] not in auxNetDict
:
2726 auxNetDict
[sce_vnf
['uuid']] = {}
2727 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
2728 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2729 net
["created"] = True
2731 #print "auxNetDict:"
2732 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2734 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
2735 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2737 for sce_vnf
in scenarioDict
['vnfs']:
2738 vnf_availability_zones
= []
2739 for vm
in sce_vnf
['vms']:
2740 vm_av
= vm
.get('availability_zone')
2741 if vm_av
and vm_av
not in vnf_availability_zones
:
2742 vnf_availability_zones
.append(vm_av
)
2744 # check if there is enough availability zones available at vim level.
2745 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
2746 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
2747 raise NfvoException('No enough availability zones at VIM for this deployment', httperrors
.Bad_Request
)
2749 for vm
in sce_vnf
['vms']:
2752 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
2753 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
2754 #myVMDict['description'] = vm['description']
2755 myVMDict
['description'] = myVMDict
['name'][0:99]
2757 myVMDict
['start'] = "no"
2758 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2759 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
2761 #create image at vim in case it not exist
2762 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2763 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
2764 vm
['vim_image_id'] = image_id
2766 #create flavor at vim in case it not exist
2767 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2768 if flavor_dict
['extended']!=None:
2769 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'], Loader
=yaml
.Loader
)
2770 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
2771 vm
['vim_flavor_id'] = flavor_id
2774 myVMDict
['imageRef'] = vm
['vim_image_id']
2775 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2776 myVMDict
['networks'] = []
2777 for iface
in vm
['interfaces']:
2779 if iface
['type']=="data":
2780 netDict
['type'] = iface
['model']
2781 elif "model" in iface
and iface
["model"]!=None:
2782 netDict
['model']=iface
['model']
2783 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2784 #discover type of interface looking at flavor
2785 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2786 for flavor_iface
in numa
.get('interfaces',[]):
2787 if flavor_iface
.get('name') == iface
['internal_name']:
2788 if flavor_iface
['dedicated'] == 'yes':
2789 netDict
['type']="PF" #passthrough
2790 elif flavor_iface
['dedicated'] == 'no':
2791 netDict
['type']="VF" #siov
2792 elif flavor_iface
['dedicated'] == 'yes:sriov':
2793 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2794 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2796 netDict
["use"]=iface
['type']
2797 if netDict
["use"]=="data" and not netDict
.get("type"):
2798 #print "netDict", netDict
2799 #print "iface", iface
2800 e_text
= "Cannot determine the interface type PF or VF of VNF '{}' VM '{}' iface '{}'".format(
2801 sce_vnf
['name'], vm
['name'], iface
['internal_name'])
2802 if flavor_dict
.get('extended')==None:
2803 raise NfvoException(e_text
+ "After database migration some information is not available. \
2804 Try to delete and create the scenarios and VNFs again", httperrors
.Conflict
)
2806 raise NfvoException(e_text
, httperrors
.Internal_Server_Error
)
2807 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2808 netDict
["type"]="virtual"
2809 if "vpci" in iface
and iface
["vpci"] is not None:
2810 netDict
['vpci'] = iface
['vpci']
2811 if "mac" in iface
and iface
["mac"] is not None:
2812 netDict
['mac_address'] = iface
['mac']
2813 if "port-security" in iface
and iface
["port-security"] is not None:
2814 netDict
['port_security'] = iface
['port-security']
2815 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2816 netDict
['floating_ip'] = iface
['floating-ip']
2817 netDict
['name'] = iface
['internal_name']
2818 if iface
['net_id'] is None:
2819 for vnf_iface
in sce_vnf
["interfaces"]:
2822 if vnf_iface
['interface_id']==iface
['uuid']:
2823 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
2826 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2827 #skip bridge ifaces not connected to any net
2828 #if 'net_id' not in netDict or netDict['net_id']==None:
2830 myVMDict
['networks'].append(netDict
)
2831 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2832 #print myVMDict['name']
2833 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2834 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2835 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2837 if 'availability_zone' in myVMDict
:
2838 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
2842 vm_id
, _
= myvim
.new_vminstance(myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2843 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2844 availability_zone_index
=av_index
,
2845 availability_zone_list
=vnf_availability_zones
)
2846 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
2847 vm
['vim_id'] = vm_id
2848 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2849 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2850 for net
in myVMDict
['networks']:
2852 for iface
in vm
['interfaces']:
2853 if net
["name"]==iface
["internal_name"]:
2854 iface
["vim_id"]=net
["vim_id"]
2857 logger
.debug("start scenario Deployment done")
2858 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2859 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
2860 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
2861 return mydb
.get_instance_scenario(instance_id
)
2863 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
2864 _
, message
= rollback(mydb
, vims
, rollbackList
)
2865 if isinstance(e
, db_base_Exception
):
2866 error_text
= "Exception at database"
2868 error_text
= "Exception at VIM"
2869 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2870 #logger.error("start_scenario %s", error_text)
2871 raise NfvoException(error_text
, e
.http_code
)
2873 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
2874 """ join the cloud config information into cloud_config_preserve.
2875 In case of conflict cloud_config_preserve preserves
2878 if not cloud_config_preserve
and not cloud_config
:
2881 new_cloud_config
= {"key-pairs":[], "users":[]}
2883 if cloud_config_preserve
:
2884 for key
in cloud_config_preserve
.get("key-pairs", () ):
2885 if key
not in new_cloud_config
["key-pairs"]:
2886 new_cloud_config
["key-pairs"].append(key
)
2888 for key
in cloud_config
.get("key-pairs", () ):
2889 if key
not in new_cloud_config
["key-pairs"]:
2890 new_cloud_config
["key-pairs"].append(key
)
2891 if not new_cloud_config
["key-pairs"]:
2892 del new_cloud_config
["key-pairs"]
2896 new_cloud_config
["users"] += cloud_config
.get("users", () )
2897 if cloud_config_preserve
:
2898 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
2899 index_to_delete
= []
2900 users
= new_cloud_config
.get("users", [])
2901 for index0
in range(0,len(users
)):
2902 if index0
in index_to_delete
:
2904 for index1
in range(index0
+1,len(users
)):
2905 if index1
in index_to_delete
:
2907 if users
[index0
]["name"] == users
[index1
]["name"]:
2908 index_to_delete
.append(index1
)
2909 for key
in users
[index1
].get("key-pairs",()):
2910 if "key-pairs" not in users
[index0
]:
2911 users
[index0
]["key-pairs"] = [key
]
2912 elif key
not in users
[index0
]["key-pairs"]:
2913 users
[index0
]["key-pairs"].append(key
)
2914 index_to_delete
.sort(reverse
=True)
2915 for index
in index_to_delete
:
2917 if not new_cloud_config
["users"]:
2918 del new_cloud_config
["users"]
2921 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
2922 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
2923 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
2924 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
2927 new_cloud_config
["user-data"] = []
2928 if cloud_config
and cloud_config
.get("user-data"):
2929 if isinstance(cloud_config
["user-data"], list):
2930 new_cloud_config
["user-data"] += cloud_config
["user-data"]
2932 new_cloud_config
["user-data"].append(cloud_config
["user-data"])
2933 if cloud_config_preserve
and cloud_config_preserve
.get("user-data"):
2934 if isinstance(cloud_config_preserve
["user-data"], list):
2935 new_cloud_config
["user-data"] += cloud_config_preserve
["user-data"]
2937 new_cloud_config
["user-data"].append(cloud_config_preserve
["user-data"])
2938 if not new_cloud_config
["user-data"]:
2939 del new_cloud_config
["user-data"]
2942 new_cloud_config
["config-files"] = []
2943 if cloud_config
and cloud_config
.get("config-files") != None:
2944 new_cloud_config
["config-files"] += cloud_config
["config-files"]
2945 if cloud_config_preserve
:
2946 for file in cloud_config_preserve
.get("config-files", ()):
2947 for index
in range(0, len(new_cloud_config
["config-files"])):
2948 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
2949 new_cloud_config
["config-files"][index
] = file
2952 new_cloud_config
["config-files"].append(file)
2953 if not new_cloud_config
["config-files"]:
2954 del new_cloud_config
["config-files"]
2955 return new_cloud_config
2958 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
2959 datacenter_id
= None
2960 datacenter_name
= None
2963 if datacenter_tenant_id
:
2964 thread_id
= datacenter_tenant_id
2965 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
2967 where_
={"td.nfvo_tenant_id": tenant_id
}
2968 if datacenter_id_name
:
2969 if utils
.check_valid_uuid(datacenter_id_name
):
2970 datacenter_id
= datacenter_id_name
2971 where_
["dt.datacenter_id"] = datacenter_id
2973 datacenter_name
= datacenter_id_name
2974 where_
["d.name"] = datacenter_name
2975 if datacenter_tenant_id
:
2976 where_
["dt.uuid"] = datacenter_tenant_id
2977 datacenters
= mydb
.get_rows(
2978 SELECT
=("dt.uuid as datacenter_tenant_id",),
2979 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
2980 "join datacenters as d on d.uuid=dt.datacenter_id",
2982 if len(datacenters
) > 1:
2983 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
2985 thread_id
= datacenters
[0]["datacenter_tenant_id"]
2986 thread
= vim_threads
["running"].get(thread_id
)
2988 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
2989 return thread_id
, thread
2990 except db_base_Exception
as e
:
2991 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
2994 def get_datacenter_uuid(mydb
, tenant_id
, datacenter_id_name
):
2996 if utils
.check_valid_uuid(datacenter_id_name
):
2997 WHERE_dict
['d.uuid'] = datacenter_id_name
2999 WHERE_dict
['d.name'] = datacenter_id_name
3002 WHERE_dict
['nfvo_tenant_id'] = tenant_id
3003 from_
= "tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join datacenter_tenants as" \
3004 " dt on td.datacenter_tenant_id=dt.uuid"
3006 from_
= 'datacenters as d'
3007 vimaccounts
= mydb
.get_rows(FROM
=from_
, SELECT
=("d.uuid as uuid, d.name as name",), WHERE
=WHERE_dict
)
3008 if len(vimaccounts
) == 0:
3009 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
3010 elif len(vimaccounts
)>1:
3011 #print "nfvo.datacenter_action() error. Several datacenters found"
3012 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
3013 return vimaccounts
[0]["uuid"], vimaccounts
[0]["name"]
3016 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
3017 datacenter_id
= None
3018 datacenter_name
= None
3019 if datacenter_id_name
:
3020 if utils
.check_valid_uuid(datacenter_id_name
):
3021 datacenter_id
= datacenter_id_name
3023 datacenter_name
= datacenter_id_name
3024 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
3026 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
3028 #print "nfvo.datacenter_action() error. Several datacenters found"
3029 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
3030 for vim_id
, vim_content
in vims
.items():
3031 return vim_id
, vim_content
3035 """Takes dict d and updates it with the values in dict u.
3036 It merges all depth levels"""
3037 for k
, v
in u
.items():
3038 if isinstance(v
, collections
.Mapping
):
3039 r
= update(d
.get(k
, {}), v
)
3046 def _get_wim(db
, wim_account_id
):
3047 # get wim from wim_account
3048 wim_accounts
= db
.get_rows(FROM
='wim_accounts', WHERE
={"uuid": wim_account_id
})
3049 if not wim_accounts
:
3050 raise NfvoException("Not found sdn id={}".format(wim_account_id
), http_code
=httperrors
.Not_Found
)
3051 return wim_accounts
[0]["wim_id"]
3054 def create_instance(mydb
, tenant_id
, instance_dict
):
3055 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
3056 # logger.debug("Creating instance...")
3058 scenario
= instance_dict
["scenario"]
3060 # find main datacenter
3062 myvim_threads_id
= {}
3063 datacenter
= instance_dict
.get("datacenter")
3064 default_wim_account
= instance_dict
.get("wim_account")
3065 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3066 myvims
[default_datacenter_id
] = vim
3067 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
3068 tenant
= mydb
.get_rows_by_id('nfvo_tenants', tenant_id
)
3069 # myvim_tenant = myvim['tenant_id']
3072 # print "Checking that the scenario exists and getting the scenario dictionary"
3073 if isinstance(scenario
, str):
3074 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, datacenter_vim_id
=myvim_threads_id
[default_datacenter_id
],
3075 datacenter_id
=default_datacenter_id
)
3077 scenarioDict
= scenario
3078 scenarioDict
["uuid"] = None
3080 # logger.debug(">>>>>> Dictionaries before merging")
3081 # logger.debug(">>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
3082 # logger.debug(">>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
3084 db_instance_vnfs
= []
3085 db_instance_vms
= []
3086 db_instance_interfaces
= []
3087 db_instance_sfis
= []
3088 db_instance_sfs
= []
3089 db_instance_classifications
= []
3090 db_instance_sfps
= []
3095 instance_name
= instance_dict
["name"]
3096 instance_uuid
= str(uuid4())
3097 uuid_list
.append(instance_uuid
)
3098 db_instance_scenario
= {
3099 "uuid": instance_uuid
,
3100 "name": instance_name
,
3101 "tenant_id": tenant_id
,
3102 "scenario_id": scenarioDict
['uuid'],
3103 "datacenter_id": default_datacenter_id
,
3104 # filled bellow 'datacenter_tenant_id'
3105 "description": instance_dict
.get("description"),
3107 if scenarioDict
.get("cloud-config"):
3108 db_instance_scenario
["cloud_config"] = yaml
.safe_dump(scenarioDict
["cloud-config"],
3109 default_flow_style
=True, width
=256)
3110 instance_action_id
= get_task_id()
3111 db_instance_action
= {
3112 "uuid": instance_action_id
, # same uuid for the instance and the action on create
3113 "tenant_id": tenant_id
,
3114 "instance_id": instance_uuid
,
3115 "description": "CREATE",
3118 # Auxiliary dictionaries from x to y
3119 sce_net2wim_instance
= {}
3120 sce_net2instance
= {}
3121 net2task_id
= {'scenario': {}}
3122 # Mapping between local networks and WIMs
3125 def ip_profile_IM2RO(ip_profile_im
):
3126 # translate from input format to database format
3128 if 'subnet-address' in ip_profile_im
:
3129 ip_profile_ro
['subnet_address'] = ip_profile_im
['subnet-address']
3130 if 'ip-version' in ip_profile_im
:
3131 ip_profile_ro
['ip_version'] = ip_profile_im
['ip-version']
3132 if 'gateway-address' in ip_profile_im
:
3133 ip_profile_ro
['gateway_address'] = ip_profile_im
['gateway-address']
3134 if 'dns-address' in ip_profile_im
:
3135 ip_profile_ro
['dns_address'] = ip_profile_im
['dns-address']
3136 if isinstance(ip_profile_ro
['dns_address'], (list, tuple)):
3137 ip_profile_ro
['dns_address'] = ";".join(ip_profile_ro
['dns_address'])
3138 if 'dhcp' in ip_profile_im
:
3139 ip_profile_ro
['dhcp_start_address'] = ip_profile_im
['dhcp'].get('start-address')
3140 ip_profile_ro
['dhcp_enabled'] = ip_profile_im
['dhcp'].get('enabled', True)
3141 ip_profile_ro
['dhcp_count'] = ip_profile_im
['dhcp'].get('count')
3142 return ip_profile_ro
3144 # logger.debug("Creating instance from scenario-dict:\n%s",
3145 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
3147 # 0 check correct parameters
3148 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).items():
3149 for scenario_net
in scenarioDict
['nets']:
3150 if net_name
== scenario_net
.get("name") or net_name
== scenario_net
.get("osm_id") or net_name
== scenario_net
.get("uuid"):
3153 raise NfvoException("Invalid scenario network name or id '{}' at instance:networks".format(net_name
),
3154 httperrors
.Bad_Request
)
3155 if "sites" not in net_instance_desc
:
3156 net_instance_desc
["sites"] = [ {} ]
3157 site_without_datacenter_field
= False
3158 for site
in net_instance_desc
["sites"]:
3159 if site
.get("datacenter"):
3160 site
["datacenter"], _
= get_datacenter_uuid(mydb
, tenant_id
, site
["datacenter"])
3161 if site
["datacenter"] not in myvims
:
3162 # Add this datacenter to myvims
3163 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
3165 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
3166 site
["datacenter"] = d
# change name to id
3168 if site_without_datacenter_field
:
3169 raise NfvoException("Found more than one entries without datacenter field at "
3170 "instance:networks:{}:sites".format(net_name
), httperrors
.Bad_Request
)
3171 site_without_datacenter_field
= True
3172 site
["datacenter"] = default_datacenter_id
# change name to id
3174 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).items():
3175 for scenario_vnf
in scenarioDict
['vnfs']:
3176 if vnf_name
== scenario_vnf
['member_vnf_index'] or vnf_name
== scenario_vnf
['uuid'] or vnf_name
== scenario_vnf
['name']:
3179 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_name
), httperrors
.Bad_Request
)
3180 if "datacenter" in vnf_instance_desc
:
3181 # Add this datacenter to myvims
3182 vnf_instance_desc
["datacenter"], _
= get_datacenter_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3183 if vnf_instance_desc
["datacenter"] not in myvims
:
3184 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3186 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3187 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
3189 for net_id
, net_instance_desc
in vnf_instance_desc
.get("networks", {}).items():
3190 for scenario_net
in scenario_vnf
['nets']:
3191 if net_id
== scenario_net
['osm_id'] or net_id
== scenario_net
['uuid'] or net_id
== scenario_net
["name"]:
3194 raise NfvoException("Invalid net id or name '{}' at instance:vnfs:networks".format(net_id
), httperrors
.Bad_Request
)
3195 if net_instance_desc
.get("vim-network-name"):
3196 scenario_net
["vim-network-name"] = net_instance_desc
["vim-network-name"]
3197 if net_instance_desc
.get("vim-network-id"):
3198 scenario_net
["vim-network-id"] = net_instance_desc
["vim-network-id"]
3199 if net_instance_desc
.get("name"):
3200 scenario_net
["name"] = net_instance_desc
["name"]
3201 if 'ip-profile' in net_instance_desc
:
3202 ipprofile_db
= ip_profile_IM2RO(net_instance_desc
['ip-profile'])
3203 if 'ip_profile' not in scenario_net
:
3204 scenario_net
['ip_profile'] = ipprofile_db
3206 update(scenario_net
['ip_profile'], ipprofile_db
)
3208 if 'provider-network' in net_instance_desc
:
3209 provider_network_db
= net_instance_desc
['provider-network']
3210 if 'provider-network' not in scenario_net
:
3211 scenario_net
['provider-network'] = provider_network_db
3213 update(scenario_net
['provider-network'], provider_network_db
)
3215 for vdu_id
, vdu_instance_desc
in vnf_instance_desc
.get("vdus", {}).items():
3216 for scenario_vm
in scenario_vnf
['vms']:
3217 if vdu_id
== scenario_vm
['osm_id'] or vdu_id
== scenario_vm
["name"]:
3220 raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id
), httperrors
.Bad_Request
)
3221 scenario_vm
["instance_parameters"] = vdu_instance_desc
3222 for iface_id
, iface_instance_desc
in vdu_instance_desc
.get("interfaces", {}).items():
3223 for scenario_interface
in scenario_vm
['interfaces']:
3224 if iface_id
== scenario_interface
['internal_name'] or iface_id
== scenario_interface
["external_name"]:
3225 scenario_interface
.update(iface_instance_desc
)
3228 raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id
), httperrors
.Bad_Request
)
3230 # 0.1 parse cloud-config parameters
3231 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
3233 # 0.2 merge instance information into scenario
3234 # Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
3235 # However, this is not possible yet.
3236 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).items():
3237 for scenario_net
in scenarioDict
['nets']:
3238 if net_name
== scenario_net
.get("name") or net_name
== scenario_net
.get("osm_id") or net_name
== scenario_net
.get("uuid"):
3239 if "wim_account" in net_instance_desc
and net_instance_desc
["wim_account"] is not None:
3240 scenario_net
["wim_account"] = net_instance_desc
["wim_account"]
3241 if 'ip-profile' in net_instance_desc
:
3242 ipprofile_db
= ip_profile_IM2RO(net_instance_desc
['ip-profile'])
3243 if 'ip_profile' not in scenario_net
:
3244 scenario_net
['ip_profile'] = ipprofile_db
3246 update(scenario_net
['ip_profile'], ipprofile_db
)
3247 if 'provider-network' in net_instance_desc
:
3248 provider_network_db
= net_instance_desc
['provider-network']
3250 if 'provider-network' not in scenario_net
:
3251 scenario_net
['provider_network'] = provider_network_db
3253 update(scenario_net
['provider-network'], provider_network_db
)
3255 for interface
in net_instance_desc
.get('interfaces', ()):
3256 if 'ip_address' in interface
:
3257 for vnf
in scenarioDict
['vnfs']:
3258 if interface
['vnf'] == vnf
['name']:
3259 for vnf_interface
in vnf
['interfaces']:
3260 if interface
['vnf_interface'] == vnf_interface
['external_name']:
3261 vnf_interface
['ip_address'] = interface
['ip_address']
3263 # logger.debug(">>>>>>>> Merged dictionary")
3264 # logger.debug("Creating instance scenario-dict MERGED:\n%s",
3265 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
3268 # 1. Creating new nets (sce_nets) in the VIM"
3269 number_mgmt_networks
= 0
3270 db_instance_nets
= []
3271 db_instance_wim_nets
= []
3272 for sce_net
in scenarioDict
['nets']:
3274 sce_net_uuid
= sce_net
.get('uuid', sce_net
["name"])
3275 # get involved datacenters where this network need to be created
3276 involved_datacenters
= []
3277 for sce_vnf
in scenarioDict
.get("vnfs", ()):
3278 vnf_datacenter
= sce_vnf
.get("datacenter", default_datacenter_id
)
3279 if vnf_datacenter
in involved_datacenters
:
3281 if sce_vnf
.get("interfaces"):
3282 for sce_vnf_ifaces
in sce_vnf
["interfaces"]:
3283 if sce_vnf_ifaces
.get("sce_net_id") == sce_net
["uuid"]:
3284 involved_datacenters
.append(vnf_datacenter
)
3286 if not involved_datacenters
:
3287 involved_datacenters
.append(default_datacenter_id
)
3288 target_wim_account
= sce_net
.get("wim_account", default_wim_account
)
3291 # TODO: use this information during network creation
3292 wim_account_id
= wim_account_name
= None
3293 if len(involved_datacenters
) > 1 and 'uuid' in sce_net
:
3294 if target_wim_account
is None or target_wim_account
is True: # automatic selection of WIM
3295 # OBS: sce_net without uuid are used internally to VNFs
3296 # and the assumption is that VNFs will not be split among
3297 # different datacenters
3298 wim_account
= wim_engine
.find_suitable_wim_account(
3299 involved_datacenters
, tenant_id
)
3300 wim_account_id
= wim_account
['uuid']
3301 wim_account_name
= wim_account
['name']
3302 wim_usage
[sce_net
['uuid']] = wim_account_id
3303 elif isinstance(target_wim_account
, str): # manual selection of WIM
3304 wim_account
.persist
.get_wim_account_by(target_wim_account
, tenant_id
)
3305 wim_account_id
= wim_account
['uuid']
3306 wim_account_name
= wim_account
['name']
3307 wim_usage
[sce_net
['uuid']] = wim_account_id
3308 else: # not WIM usage
3309 wim_usage
[sce_net
['uuid']] = False
3313 if instance_dict
.get("networks"):
3314 if sce_net
.get("uuid") in instance_dict
["networks"]:
3315 descriptor_net
= instance_dict
["networks"][sce_net
["uuid"]]
3316 descriptor_net_name
= sce_net
["uuid"]
3317 elif sce_net
.get("osm_id") in instance_dict
["networks"]:
3318 descriptor_net
= instance_dict
["networks"][sce_net
["osm_id"]]
3319 descriptor_net_name
= sce_net
["osm_id"]
3320 elif sce_net
["name"] in instance_dict
["networks"]:
3321 descriptor_net
= instance_dict
["networks"][sce_net
["name"]]
3322 descriptor_net_name
= sce_net
["name"]
3323 net_name
= descriptor_net
.get("vim-network-name")
3324 # add datacenters from instantiation parameters
3325 if descriptor_net
.get("sites"):
3326 for site
in descriptor_net
["sites"]:
3327 if site
.get("datacenter") and site
["datacenter"] not in involved_datacenters
:
3328 involved_datacenters
.append(site
["datacenter"])
3329 sce_net2instance
[sce_net_uuid
] = {}
3330 sce_net2wim_instance
[sce_net_uuid
] = {}
3331 net2task_id
['scenario'][sce_net_uuid
] = {}
3334 related_network
= None
3335 if descriptor_net
.get("use-network"):
3336 target_instance_nets
= mydb
.get_rows(
3338 FROM
="instance_nets",
3339 WHERE
={"instance_scenario_id": descriptor_net
["use-network"]["instance_scenario_id"],
3340 "osm_id": descriptor_net
["use-network"]["osm_id"]},
3342 if not target_instance_nets
:
3343 raise NfvoException(
3344 "Cannot find the target network at instance:networks[{}]:use-network".format(descriptor_net_name
),
3345 httperrors
.Bad_Request
)
3347 use_network
= target_instance_nets
[0]["related"]
3349 if sce_net
["external"]:
3350 number_mgmt_networks
+= 1
3352 for datacenter_id
in involved_datacenters
:
3354 netmap_create
= None
3355 if descriptor_net
.get("sites"):
3356 for site
in descriptor_net
["sites"]:
3357 if site
.get("datacenter") == datacenter_id
:
3358 netmap_use
= site
.get("netmap-use")
3359 netmap_create
= site
.get("netmap-create")
3362 vim
= myvims
[datacenter_id
]
3363 myvim_thread_id
= myvim_threads_id
[datacenter_id
]
3365 net_type
= sce_net
['type']
3367 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} # 'shared': True
3370 if sce_net
["external"]:
3371 net_name
= sce_net
["name"]
3373 net_name
= "{}-{}".format(instance_name
, sce_net
["name"])
3374 net_name
= net_name
[:255] # limit length
3376 if netmap_use
or netmap_create
:
3377 create_network
= False
3378 lookfor_network
= False
3380 lookfor_network
= True
3381 if utils
.check_valid_uuid(netmap_use
):
3382 lookfor_filter
["id"] = netmap_use
3384 lookfor_filter
["name"] = netmap_use
3386 create_network
= True
3387 net_vim_name
= net_name
3388 if isinstance(netmap_create
, str):
3389 net_vim_name
= netmap_create
3390 elif sce_net
.get("vim_network_name"):
3391 create_network
= False
3392 lookfor_network
= True
3393 lookfor_filter
["name"] = sce_net
.get("vim_network_name")
3394 elif sce_net
["external"]:
3395 if sce_net
.get('vim_id'):
3396 # there is a netmap at datacenter_nets database # TODO REVISE!!!!
3397 create_network
= False
3398 lookfor_network
= True
3399 lookfor_filter
["id"] = sce_net
['vim_id']
3400 elif vim
["config"].get("management_network_id") or vim
["config"].get("management_network_name"):
3401 if number_mgmt_networks
> 1:
3402 raise NfvoException("Found several VLD of type mgmt. "
3403 "You must concrete what vim-network must be use for each one",
3404 httperrors
.Bad_Request
)
3405 create_network
= False
3406 lookfor_network
= True
3407 if vim
["config"].get("management_network_id"):
3408 lookfor_filter
["id"] = vim
["config"]["management_network_id"]
3410 lookfor_filter
["name"] = vim
["config"]["management_network_name"]
3412 # There is not a netmap, look at datacenter for a net with this name and create if not found
3413 create_network
= True
3414 lookfor_network
= True
3415 lookfor_filter
["name"] = sce_net
["name"]
3416 net_vim_name
= sce_net
["name"]
3418 net_vim_name
= net_name
3419 create_network
= True
3420 lookfor_network
= False
3424 task_action
= "CREATE"
3425 task_extra
["params"] = (net_vim_name
, net_type
, sce_net
.get('ip_profile', None), False,
3426 sce_net
.get('provider_network', None), wim_account_name
)
3429 task_extra
["find"] = (lookfor_filter
,)
3430 elif lookfor_network
:
3431 task_action
= "FIND"
3432 task_extra
["params"] = (lookfor_filter
,)
3434 # fill database content
3435 net_uuid
= str(uuid4())
3436 uuid_list
.append(net_uuid
)
3437 sce_net2instance
[sce_net_uuid
][datacenter_id
] = net_uuid
3438 if not related_network
: # all db_instance_nets will have same related
3439 related_network
= use_network
or net_uuid
3441 sdn_controller
= vim
.config
.get('sdn-controller')
3442 sce_net2wim_instance
[sce_net_uuid
][datacenter_id
] = None
3443 if sdn_controller
and net_type
in ("data", "ptp"):
3444 wim_id
= _get_wim(mydb
, sdn_controller
)
3445 sdn_net_id
= str(uuid4())
3446 sce_net2wim_instance
[sce_net_uuid
][datacenter_id
] = sdn_net_id
3447 task_extra
["sdn_net_id"] = sdn_net_id
3448 db_instance_wim_nets
.append({
3450 "instance_scenario_id": instance_uuid
,
3451 "sce_net_id": sce_net
.get("uuid"),
3453 "wim_account_id": sdn_controller
,
3454 'status': 'BUILD', # if create_network else "ACTIVE"
3455 "related": related_network
,
3456 'multipoint': True if net_type
=="data" else False,
3457 "created": create_network
, # TODO py3
3460 task_wim_extra
= {"params": [net_type
, wim_account_name
]}
3462 "instance_action_id": instance_action_id
,
3463 "status": "SCHEDULED",
3464 "task_index": task_index
,
3465 # "datacenter_vim_id": myvim_thread_id,
3466 "wim_account_id": sdn_controller
,
3467 "action": task_action
,
3468 "item": "instance_wim_nets",
3469 "item_id": sdn_net_id
,
3470 "related": related_network
,
3471 "extra": yaml
.safe_dump(task_wim_extra
, default_flow_style
=True, width
=256)
3474 db_vim_actions
.append(db_vim_action
)
3477 "osm_id": sce_net
.get("osm_id") or sce_net
["name"],
3478 "related": related_network
,
3480 "vim_name": net_vim_name
,
3481 "instance_scenario_id": instance_uuid
,
3482 "sce_net_id": sce_net
.get("uuid"),
3483 "created": create_network
,
3484 'datacenter_id': datacenter_id
,
3485 'datacenter_tenant_id': myvim_thread_id
,
3486 'status': 'BUILD', # if create_network else "ACTIVE"
3487 'sdn_net_id': sdn_net_id
,
3489 db_instance_nets
.append(db_net
)
3491 "instance_action_id": instance_action_id
,
3492 "status": "SCHEDULED",
3493 "task_index": task_index
,
3494 "datacenter_vim_id": myvim_thread_id
,
3495 "action": task_action
,
3496 "item": "instance_nets",
3497 "item_id": net_uuid
,
3498 "related": related_network
,
3499 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
3501 net2task_id
['scenario'][sce_net_uuid
][datacenter_id
] = task_index
3503 db_vim_actions
.append(db_vim_action
)
3505 if 'ip_profile' in sce_net
:
3507 'instance_net_id': net_uuid
,
3508 'ip_version': sce_net
['ip_profile']['ip_version'],
3509 'subnet_address': sce_net
['ip_profile']['subnet_address'],
3510 'gateway_address': sce_net
['ip_profile']['gateway_address'],
3511 'dns_address': sce_net
['ip_profile']['dns_address'],
3512 'dhcp_enabled': sce_net
['ip_profile']['dhcp_enabled'],
3513 'dhcp_start_address': sce_net
['ip_profile']['dhcp_start_address'],
3514 'dhcp_count': sce_net
['ip_profile']['dhcp_count'],
3516 db_ip_profiles
.append(db_ip_profile
)
3520 "default_datacenter_id": default_datacenter_id
,
3521 "myvim_threads_id": myvim_threads_id
,
3522 "instance_uuid": instance_uuid
,
3523 "instance_name": instance_name
,
3524 "instance_action_id": instance_action_id
,
3526 "cloud_config": cloud_config
,
3527 "RO_pub_key": tenant
[0].get('RO_pub_key'),
3528 "instance_parameters": instance_dict
,
3531 "task_index": task_index
,
3532 "uuid_list": uuid_list
,
3533 "db_instance_nets": db_instance_nets
,
3534 "db_instance_wim_nets": db_instance_wim_nets
,
3535 "db_vim_actions": db_vim_actions
,
3536 "db_ip_profiles": db_ip_profiles
,
3537 "db_instance_vnfs": db_instance_vnfs
,
3538 "db_instance_vms": db_instance_vms
,
3539 "db_instance_interfaces": db_instance_interfaces
,
3540 "net2task_id": net2task_id
,
3541 "sce_net2instance": sce_net2instance
,
3542 "sce_net2wim_instance": sce_net2wim_instance
,
3544 # sce_vnf_list = sorted(scenarioDict['vnfs'], key=lambda k: k['name'])
3545 for sce_vnf
in scenarioDict
.get('vnfs', ()): # sce_vnf_list:
3546 instantiate_vnf(mydb
, sce_vnf
, vnf_params
, vnf_params_out
, rollbackList
)
3547 task_index
= vnf_params_out
["task_index"]
3548 uuid_list
= vnf_params_out
["uuid_list"]
3551 # task_depends_on = []
3552 for vnffg
in scenarioDict
.get('vnffgs', ()):
3553 for rsp
in vnffg
['rsps']:
3555 for cp
in rsp
['connection_points']:
3556 count
= mydb
.get_rows(
3558 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_rsp_hops as h "
3559 "on interfaces.uuid=h.ingress_interface_id",
3560 WHERE
={'h.uuid': cp
['uuid']})[0]['count']
3561 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == cp
['sce_vnf_id']), None)
3562 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3564 for instance_vm
in instance_vms
:
3565 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3567 dependencies
.append(action
['task_index'])
3568 # TODO: throw exception if count != len(instance_vms)
3569 # TODO: and action shouldn't ever be None
3571 for i
in range(count
):
3573 sfi_uuid
= str(uuid4())
3575 "ingress_interface_id": cp
["ingress_interface_id"],
3576 "egress_interface_id": cp
["egress_interface_id"]
3578 uuid_list
.append(sfi_uuid
)
3581 "related": sfi_uuid
,
3582 "instance_scenario_id": instance_uuid
,
3583 'sce_rsp_hop_id': cp
['uuid'],
3584 'datacenter_id': datacenter_id
,
3585 'datacenter_tenant_id': myvim_thread_id
,
3586 "vim_sfi_id": None, # vim thread will populate
3588 db_instance_sfis
.append(db_sfi
)
3590 "instance_action_id": instance_action_id
,
3591 "task_index": task_index
,
3592 "datacenter_vim_id": myvim_thread_id
,
3594 "status": "SCHEDULED",
3595 "item": "instance_sfis",
3596 "item_id": sfi_uuid
,
3597 "related": sfi_uuid
,
3598 "extra": yaml
.safe_dump({"params": extra_params
, "depends_on": [dependencies
[i
]]},
3599 default_flow_style
=True, width
=256)
3601 sfis_created
.append(task_index
)
3603 db_vim_actions
.append(db_vim_action
)
3605 sf_uuid
= str(uuid4())
3606 uuid_list
.append(sf_uuid
)
3610 "instance_scenario_id": instance_uuid
,
3611 'sce_rsp_hop_id': cp
['uuid'],
3612 'datacenter_id': datacenter_id
,
3613 'datacenter_tenant_id': myvim_thread_id
,
3614 "vim_sf_id": None, # vim thread will populate
3616 db_instance_sfs
.append(db_sf
)
3618 "instance_action_id": instance_action_id
,
3619 "task_index": task_index
,
3620 "datacenter_vim_id": myvim_thread_id
,
3622 "status": "SCHEDULED",
3623 "item": "instance_sfs",
3626 "extra": yaml
.safe_dump({"params": "", "depends_on": sfis_created
},
3627 default_flow_style
=True, width
=256)
3629 sfs_created
.append(task_index
)
3631 db_vim_actions
.append(db_vim_action
)
3632 classifier
= rsp
['classifier']
3634 # TODO the following ~13 lines can be reused for the sfi case
3635 count
= mydb
.get_rows(
3636 SELECT
=('vms.count'),
3637 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_classifiers as c on interfaces.uuid=c.interface_id",
3638 WHERE
={'c.uuid': classifier
['uuid']})[0]['count']
3639 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == classifier
['sce_vnf_id']), None)
3640 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3642 for instance_vm
in instance_vms
:
3643 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3645 dependencies
.append(action
['task_index'])
3646 # TODO: throw exception if count != len(instance_vms)
3647 # TODO: and action shouldn't ever be None
3648 classifications_created
= []
3649 for i
in range(count
):
3650 for match
in classifier
['matches']:
3651 # create classifications
3652 classification_uuid
= str(uuid4())
3653 uuid_list
.append(classification_uuid
)
3654 db_classification
= {
3655 "uuid": classification_uuid
,
3656 "related": classification_uuid
,
3657 "instance_scenario_id": instance_uuid
,
3658 'sce_classifier_match_id': match
['uuid'],
3659 'datacenter_id': datacenter_id
,
3660 'datacenter_tenant_id': myvim_thread_id
,
3661 "vim_classification_id": None, # vim thread will populate
3663 db_instance_classifications
.append(db_classification
)
3664 classification_params
= {
3665 "ip_proto": match
["ip_proto"],
3666 "source_ip": match
["source_ip"],
3667 "destination_ip": match
["destination_ip"],
3668 "source_port": match
["source_port"],
3669 "destination_port": match
["destination_port"],
3670 "logical_source_port": classifier
["interface_id"]
3673 "instance_action_id": instance_action_id
,
3674 "task_index": task_index
,
3675 "datacenter_vim_id": myvim_thread_id
,
3677 "status": "SCHEDULED",
3678 "item": "instance_classifications",
3679 "item_id": classification_uuid
,
3680 "related": classification_uuid
,
3681 "extra": yaml
.safe_dump({"params": classification_params
, "depends_on": [dependencies
[i
]]},
3682 default_flow_style
=True, width
=256)
3684 classifications_created
.append(task_index
)
3686 db_vim_actions
.append(db_vim_action
)
3689 sfp_uuid
= str(uuid4())
3690 uuid_list
.append(sfp_uuid
)
3693 "related": sfp_uuid
,
3694 "instance_scenario_id": instance_uuid
,
3695 'sce_rsp_id': rsp
['uuid'],
3696 'datacenter_id': datacenter_id
,
3697 'datacenter_tenant_id': myvim_thread_id
,
3698 "vim_sfp_id": None, # vim thread will populate
3700 db_instance_sfps
.append(db_sfp
)
3702 "instance_action_id": instance_action_id
,
3703 "task_index": task_index
,
3704 "datacenter_vim_id": myvim_thread_id
,
3706 "status": "SCHEDULED",
3707 "item": "instance_sfps",
3708 "item_id": sfp_uuid
,
3709 "related": sfp_uuid
,
3710 "extra": yaml
.safe_dump({"params": "", "depends_on": sfs_created
+ classifications_created
},
3711 default_flow_style
=True, width
=256)
3714 db_vim_actions
.append(db_vim_action
)
3715 db_instance_action
["number_tasks"] = task_index
3718 logger
.debug('wim_usage:\n%s\n\n', pformat(wim_usage
))
3719 wan_links
= wim_engine
.derive_wan_links(wim_usage
, db_instance_nets
, tenant_id
)
3720 wim_actions
= wim_engine
.create_actions(wan_links
)
3721 wim_actions
, db_instance_action
= (
3722 wim_engine
.incorporate_actions(wim_actions
, db_instance_action
))
3725 scenarioDict
["datacenter2tenant"] = myvim_threads_id
3727 db_instance_scenario
['datacenter_tenant_id'] = myvim_threads_id
[default_datacenter_id
]
3728 db_instance_scenario
['datacenter_id'] = default_datacenter_id
3730 {"instance_scenarios": db_instance_scenario
},
3731 {"instance_vnfs": db_instance_vnfs
},
3732 {"instance_nets": db_instance_nets
},
3733 {"ip_profiles": db_ip_profiles
},
3734 {"instance_vms": db_instance_vms
},
3735 {"instance_interfaces": db_instance_interfaces
},
3736 {"instance_actions": db_instance_action
},
3737 {"instance_sfis": db_instance_sfis
},
3738 {"instance_sfs": db_instance_sfs
},
3739 {"instance_classifications": db_instance_classifications
},
3740 {"instance_sfps": db_instance_sfps
},
3741 {"instance_wim_nets": db_instance_wim_nets
+ wan_links
},
3742 {"vim_wim_actions": db_vim_actions
+ wim_actions
}
3745 logger
.debug("create_instance done DB tables: %s",
3746 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
3747 mydb
.new_rows(db_tables
, uuid_list
)
3748 for myvim_thread_id
in myvim_threads_id
.values():
3749 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
3751 wim_engine
.dispatch(wim_actions
)
3753 returned_instance
= mydb
.get_instance_scenario(instance_uuid
)
3754 returned_instance
["action_id"] = instance_action_id
3755 return returned_instance
3756 except (NfvoException
, vimconn
.vimconnException
, sdnconn
.SdnConnectorError
, db_base_Exception
) as e
:
3757 message
= rollback(mydb
, myvims
, rollbackList
)
3758 if isinstance(e
, db_base_Exception
):
3759 error_text
= "database Exception"
3760 elif isinstance(e
, vimconn
.vimconnException
):
3761 error_text
= "VIM Exception"
3762 elif isinstance(e
, sdnconn
.SdnConnectorError
):
3763 error_text
= "WIM Exception"
3765 error_text
= "Exception"
3766 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
3767 # logger.error("create_instance: %s", error_text)
3769 raise NfvoException(error_text
, e
.http_code
)
3772 def instantiate_vnf(mydb
, sce_vnf
, params
, params_out
, rollbackList
):
3773 default_datacenter_id
= params
["default_datacenter_id"]
3774 myvim_threads_id
= params
["myvim_threads_id"]
3775 instance_uuid
= params
["instance_uuid"]
3776 instance_name
= params
["instance_name"]
3777 instance_action_id
= params
["instance_action_id"]
3778 myvims
= params
["myvims"]
3779 cloud_config
= params
["cloud_config"]
3780 RO_pub_key
= params
["RO_pub_key"]
3782 task_index
= params_out
["task_index"]
3783 uuid_list
= params_out
["uuid_list"]
3784 db_instance_nets
= params_out
["db_instance_nets"]
3785 db_instance_wim_nets
= params_out
["db_instance_wim_nets"]
3786 db_vim_actions
= params_out
["db_vim_actions"]
3787 db_ip_profiles
= params_out
["db_ip_profiles"]
3788 db_instance_vnfs
= params_out
["db_instance_vnfs"]
3789 db_instance_vms
= params_out
["db_instance_vms"]
3790 db_instance_interfaces
= params_out
["db_instance_interfaces"]
3791 net2task_id
= params_out
["net2task_id"]
3792 sce_net2instance
= params_out
["sce_net2instance"]
3793 sce_net2wim_instance
= params_out
["sce_net2wim_instance"]
3795 vnf_net2instance
= {}
3797 # 2. Creating new nets (vnf internal nets) in the VIM"
3798 # For each vnf net, we create it and we add it to instanceNetlist.
3799 if sce_vnf
.get("datacenter"):
3800 vim
= myvims
[sce_vnf
["datacenter"]]
3801 datacenter_id
= sce_vnf
["datacenter"]
3802 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
3804 vim
= myvims
[default_datacenter_id
]
3805 datacenter_id
= default_datacenter_id
3806 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
3807 for net
in sce_vnf
['nets']:
3809 # descriptor_net = instance_dict.get("vnfs", {}).get(sce_vnf["name"], {})
3810 # net_name = descriptor_net.get("name")
3813 net_name
= "{}-{}".format(instance_name
, net
["name"])
3814 net_name
= net_name
[:255] # limit length
3815 net_type
= net
['type']
3817 if sce_vnf
['uuid'] not in vnf_net2instance
:
3818 vnf_net2instance
[sce_vnf
['uuid']] = {}
3819 if sce_vnf
['uuid'] not in net2task_id
:
3820 net2task_id
[sce_vnf
['uuid']] = {}
3822 # fill database content
3823 net_uuid
= str(uuid4())
3824 uuid_list
.append(net_uuid
)
3825 vnf_net2instance
[sce_vnf
['uuid']][net
['uuid']] = net_uuid
3827 sdn_controller
= vim
.config
.get('sdn-controller')
3829 if sdn_controller
and net_type
in ("data", "ptp"):
3830 wim_id
= _get_wim(mydb
, sdn_controller
)
3831 sdn_net_id
= str(uuid4())
3832 db_instance_wim_nets
.append({
3834 "instance_scenario_id": instance_uuid
,
3836 "wim_account_id": sdn_controller
,
3837 'status': 'BUILD', # if create_network else "ACTIVE"
3838 "related": net_uuid
,
3839 'multipoint': True if net_type
== "data" else False,
3840 "created": True, # TODO py3
3846 "related": net_uuid
,
3848 "vim_name": net_name
,
3849 "instance_scenario_id": instance_uuid
,
3850 "net_id": net
["uuid"],
3852 'datacenter_id': datacenter_id
,
3853 'datacenter_tenant_id': myvim_thread_id
,
3854 'sdn_net_id': sdn_net_id
,
3856 db_instance_nets
.append(db_net
)
3859 if net
.get("vim-network-name"):
3860 lookfor_filter
["name"] = net
["vim-network-name"]
3861 if net
.get("vim-network-id"):
3862 lookfor_filter
["id"] = net
["vim-network-id"]
3864 task_action
= "FIND"
3865 task_extra
= {"params": (lookfor_filter
,)}
3867 task_action
= "CREATE"
3868 task_extra
= {"params": (net_name
, net_type
, net
.get('ip_profile', None))}
3870 task_extra
["sdn_net_id"] = sdn_net_id
3873 task_wim_extra
= {"params": [net_type
, None]}
3875 "instance_action_id": instance_action_id
,
3876 "status": "SCHEDULED",
3877 "task_index": task_index
,
3878 # "datacenter_vim_id": myvim_thread_id,
3879 "wim_account_id": sdn_controller
,
3880 "action": task_action
,
3881 "item": "instance_wim_nets",
3882 "item_id": sdn_net_id
,
3883 "related": net_uuid
,
3884 "extra": yaml
.safe_dump(task_wim_extra
, default_flow_style
=True, width
=256)
3887 db_vim_actions
.append(db_vim_action
)
3889 "instance_action_id": instance_action_id
,
3890 "task_index": task_index
,
3891 "datacenter_vim_id": myvim_thread_id
,
3892 "status": "SCHEDULED",
3893 "action": task_action
,
3894 "item": "instance_nets",
3895 "item_id": net_uuid
,
3896 "related": net_uuid
,
3897 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
3899 net2task_id
[sce_vnf
['uuid']][net
['uuid']] = task_index
3901 db_vim_actions
.append(db_vim_action
)
3903 if 'ip_profile' in net
:
3905 'instance_net_id': net_uuid
,
3906 'ip_version': net
['ip_profile']['ip_version'],
3907 'subnet_address': net
['ip_profile']['subnet_address'],
3908 'gateway_address': net
['ip_profile']['gateway_address'],
3909 'dns_address': net
['ip_profile']['dns_address'],
3910 'dhcp_enabled': net
['ip_profile']['dhcp_enabled'],
3911 'dhcp_start_address': net
['ip_profile']['dhcp_start_address'],
3912 'dhcp_count': net
['ip_profile']['dhcp_count'],
3914 db_ip_profiles
.append(db_ip_profile
)
3916 # print "vnf_net2instance:"
3917 # print yaml.safe_dump(vnf_net2instance, indent=4, default_flow_style=False)
3919 # 3. Creating new vm instances in the VIM
3920 # myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
3922 if sce_vnf
.get('mgmt_access'):
3923 ssh_access
= sce_vnf
['mgmt_access'].get('config-access', {}).get('ssh-access')
3924 vnf_availability_zones
= []
3925 for vm
in sce_vnf
.get('vms'):
3926 vm_av
= vm
.get('availability_zone')
3927 if vm_av
and vm_av
not in vnf_availability_zones
:
3928 vnf_availability_zones
.append(vm_av
)
3930 # check if there is enough availability zones available at vim level.
3931 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
3932 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
3933 raise NfvoException('No enough availability zones at VIM for this deployment', httperrors
.Bad_Request
)
3935 if sce_vnf
.get("datacenter"):
3936 vim
= myvims
[sce_vnf
["datacenter"]]
3937 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
3938 datacenter_id
= sce_vnf
["datacenter"]
3940 vim
= myvims
[default_datacenter_id
]
3941 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
3942 datacenter_id
= default_datacenter_id
3943 sce_vnf
["datacenter_id"] = datacenter_id
3946 vnf_uuid
= str(uuid4())
3947 uuid_list
.append(vnf_uuid
)
3950 'instance_scenario_id': instance_uuid
,
3951 'vnf_id': sce_vnf
['vnf_id'],
3952 'sce_vnf_id': sce_vnf
['uuid'],
3953 'datacenter_id': datacenter_id
,
3954 'datacenter_tenant_id': myvim_thread_id
,
3956 db_instance_vnfs
.append(db_instance_vnf
)
3958 for vm
in sce_vnf
['vms']:
3960 if vm
.get("pdu_type"):
3964 sce_vnf_name
= sce_vnf
['member_vnf_index'] if sce_vnf
['member_vnf_index'] else sce_vnf
['name']
3965 myVMDict
['name'] = "{}-{}-{}".format(instance_name
[:64], sce_vnf_name
[:64], vm
["name"][:64])
3966 myVMDict
['description'] = myVMDict
['name'][0:99]
3968 # myVMDict['start'] = "no"
3969 if vm
.get("instance_parameters") and vm
["instance_parameters"].get("name"):
3970 myVMDict
['name'] = vm
["instance_parameters"].get("name")
3971 myVMDict
['name'] = myVMDict
['name'][0:255] # limit name length
3972 # create image at vim in case it not exist
3973 image_uuid
= vm
['image_id']
3974 if vm
.get("image_list"):
3975 for alternative_image
in vm
["image_list"]:
3976 if alternative_image
["vim_type"] == vim
["config"]["_vim_type_internal"]:
3977 image_uuid
= alternative_image
['image_id']
3979 image_dict
= mydb
.get_table_by_uuid_name("images", image_uuid
)
3980 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
3981 vm
['vim_image_id'] = image_id
3983 # create flavor at vim in case it not exist
3984 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
3985 if flavor_dict
['extended'] != None:
3986 flavor_dict
['extended'] = yaml
.load(flavor_dict
['extended'], Loader
=yaml
.Loader
)
3987 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
3989 # Obtain information for additional disks
3990 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',),
3991 WHERE
={'vim_id': flavor_id
})
3992 if not extended_flavor_dict
:
3993 raise NfvoException("flavor '{}' not found".format(flavor_id
), httperrors
.Not_Found
)
3995 # extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0], Loader=yaml.Loader)
3996 myVMDict
['disks'] = None
3997 extended_info
= extended_flavor_dict
[0]['extended']
3998 if extended_info
!= None:
3999 extended_flavor_dict_yaml
= yaml
.load(extended_info
, Loader
=yaml
.Loader
)
4000 if 'disks' in extended_flavor_dict_yaml
:
4001 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
4002 if vm
.get("instance_parameters") and vm
["instance_parameters"].get("devices"):
4003 for disk
in myVMDict
['disks']:
4004 if disk
.get("name") in vm
["instance_parameters"]["devices"]:
4005 disk
.update(vm
["instance_parameters"]["devices"][disk
.get("name")])
4007 vm
['vim_flavor_id'] = flavor_id
4008 myVMDict
['imageRef'] = vm
['vim_image_id']
4009 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
4010 myVMDict
['availability_zone'] = vm
.get('availability_zone')
4011 myVMDict
['networks'] = []
4012 task_depends_on
= []
4013 # TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
4014 is_management_vm
= False
4016 for iface
in vm
['interfaces']:
4018 if iface
['type'] == "data":
4019 netDict
['type'] = iface
['model']
4020 elif "model" in iface
and iface
["model"] != None:
4021 netDict
['model'] = iface
['model']
4022 # TODO in future, remove this because mac_address will not be set, and the type of PV,VF
4023 # is obtained from iterface table model
4024 # discover type of interface looking at flavor
4025 for numa
in flavor_dict
.get('extended', {}).get('numas', []):
4026 for flavor_iface
in numa
.get('interfaces', []):
4027 if flavor_iface
.get('name') == iface
['internal_name']:
4028 if flavor_iface
['dedicated'] == 'yes':
4029 netDict
['type'] = "PF" # passthrough
4030 elif flavor_iface
['dedicated'] == 'no':
4031 netDict
['type'] = "VF" # siov
4032 elif flavor_iface
['dedicated'] == 'yes:sriov':
4033 netDict
['type'] = "VFnotShared" # sriov but only one sriov on the PF
4034 netDict
["mac_address"] = flavor_iface
.get("mac_address")
4036 netDict
["use"] = iface
['type']
4037 if netDict
["use"] == "data" and not netDict
.get("type"):
4038 # print "netDict", netDict
4039 # print "iface", iface
4040 e_text
= "Cannot determine the interface type PF or VF of VNF '{}' VM '{}' iface '{}'".fromat(
4041 sce_vnf
['name'], vm
['name'], iface
['internal_name'])
4042 if flavor_dict
.get('extended') == None:
4043 raise NfvoException(e_text
+ "After database migration some information is not available. \
4044 Try to delete and create the scenarios and VNFs again", httperrors
.Conflict
)
4046 raise NfvoException(e_text
, httperrors
.Internal_Server_Error
)
4047 if netDict
["use"] == "mgmt":
4048 is_management_vm
= True
4049 netDict
["type"] = "virtual"
4050 if netDict
["use"] == "bridge":
4051 netDict
["type"] = "virtual"
4052 if iface
.get("vpci"):
4053 netDict
['vpci'] = iface
['vpci']
4054 if iface
.get("mac"):
4055 netDict
['mac_address'] = iface
['mac']
4056 if iface
.get("mac_address"):
4057 netDict
['mac_address'] = iface
['mac_address']
4058 if iface
.get("ip_address"):
4059 netDict
['ip_address'] = iface
['ip_address']
4060 if iface
.get("port-security") is not None:
4061 netDict
['port_security'] = iface
['port-security']
4062 if iface
.get("floating-ip") is not None:
4063 netDict
['floating_ip'] = iface
['floating-ip']
4064 netDict
['name'] = iface
['internal_name']
4065 if iface
['net_id'] is None:
4066 for vnf_iface
in sce_vnf
["interfaces"]:
4069 if vnf_iface
['interface_id'] == iface
['uuid']:
4070 netDict
['net_id'] = "TASK-{}".format(
4071 net2task_id
['scenario'][vnf_iface
['sce_net_id']][datacenter_id
])
4072 instance_net_id
= sce_net2instance
[vnf_iface
['sce_net_id']][datacenter_id
]
4073 instance_wim_net_id
= sce_net2wim_instance
[vnf_iface
['sce_net_id']][datacenter_id
]
4074 task_depends_on
.append(net2task_id
['scenario'][vnf_iface
['sce_net_id']][datacenter_id
])
4077 netDict
['net_id'] = "TASK-{}".format(net2task_id
[sce_vnf
['uuid']][iface
['net_id']])
4078 instance_net_id
= vnf_net2instance
[sce_vnf
['uuid']][iface
['net_id']]
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
):
5758 wim_id
= ovim
.new_of_controller(sdn_controller
)
5760 thread_name
= get_non_used_vim_name(sdn_controller
['name'], wim_id
, wim_id
, None)
5761 new_thread
= vim_thread(task_lock
, plugins
, thread_name
, wim_id
, None, db
=db
)
5764 vim_threads
["running"][thread_id
] = new_thread
5765 logger
.debug('New SDN controller created with uuid {}'.format(wim_id
))
5768 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
5769 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
5770 msg
= 'SDN controller {} updated'.format(data
)
5771 vim_threads
["running"][controller_id
].insert_task("reload")
5775 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
5776 if controller_id
== None:
5777 data
= ovim
.get_of_controllers()
5779 data
= ovim
.show_of_controller(controller_id
)
5781 msg
= 'SDN controller list:\n {}'.format(data
)
5785 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
5786 select_
= ('uuid', 'config')
5787 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
5788 for datacenter
in datacenters
:
5789 if datacenter
['config']:
5790 config
= yaml
.load(datacenter
['config'], Loader
=yaml
.Loader
)
5791 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
5792 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), httperrors
.Conflict
)
5794 data
= ovim
.delete_of_controller(controller_id
)
5795 msg
= 'SDN controller {} deleted'.format(data
)
5799 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
5800 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
5801 if len(controller
) < 1:
5802 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), httperrors
.Not_Found
)
5805 sdn_controller_id
= yaml
.load(controller
[0]["config"], Loader
=yaml
.Loader
)["sdn-controller"]
5807 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), httperrors
.Bad_Request
)
5809 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
5810 switch_dpid
= sdn_controller
["dpid"]
5813 for compute_node
in sdn_port_mapping
:
5814 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
5816 element
["compute_node"] = compute_node
["compute_node"]
5817 if compute_node
["ports"]:
5818 for port
in compute_node
["ports"]:
5819 pci
= port
.get("pci")
5820 element
["switch_port"] = port
.get("switch_port")
5821 element
["switch_mac"] = port
.get("switch_mac")
5822 if not element
["switch_port"] and not element
["switch_mac"]:
5823 raise NfvoException ("The mapping must contain 'switch_port' or 'switch_mac'", httperrors
.Bad_Request
)
5824 for pci_expanded
in utils
.expand_brackets(pci
):
5825 element
["pci"] = pci_expanded
5826 maps
.append(dict(element
))
5828 out
= ovim
.set_of_port_mapping(maps
, sdn_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, vim_id
=datacenter_id
)
5829 vim_threads
["running"][sdn_controller_id
].insert_task("reload")
5832 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
5833 maps
= ovim
.get_of_port_mappings(db_filter
={"datacenter_id": datacenter_id
})
5836 "sdn-controller": None,
5837 "datacenter-id": datacenter_id
,
5839 "ports_mapping": list()
5842 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
5843 if datacenter
['config']:
5844 config
= yaml
.load(datacenter
['config'], Loader
=yaml
.Loader
)
5845 if 'sdn-controller' in config
:
5846 controller_id
= config
['sdn-controller']
5847 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
5848 result
["sdn-controller"] = controller_id
5849 result
["dpid"] = sdn_controller
["dpid"]
5851 if result
["sdn-controller"] == None:
5852 raise NfvoException("SDN controller is not defined for datacenter {}".format(datacenter_id
), httperrors
.Bad_Request
)
5853 if result
["dpid"] == None:
5854 raise NfvoException("It was not possible to determine DPID for SDN controller {}".format(result
["sdn-controller"]),
5855 httperrors
.Internal_Server_Error
)
5860 ports_correspondence_dict
= dict()
5862 if result
["sdn-controller"] != link
["wim_id"]:
5863 raise NfvoException("The sdn-controller specified for different port mappings differ", httperrors
.Internal_Server_Error
)
5864 if result
["dpid"] != link
["switch_dpid"]:
5865 raise NfvoException("The dpid specified for different port mappings differ", httperrors
.Internal_Server_Error
)
5866 link_config
= link
["service_mapping_info"]
5868 element
["pci"] = link
.get("device_interface_id")
5869 if link
["switch_port"]:
5870 element
["switch_port"] = link
["switch_port"]
5871 if link_config
["switch_mac"]:
5872 element
["switch_mac"] = link_config
.get("switch_mac")
5874 if not link
.get("interface_id") in ports_correspondence_dict
:
5876 content
["compute_node"] = link
.get("interface_id")
5877 content
["ports"] = list()
5878 ports_correspondence_dict
[link
.get("interface_id")] = content
5880 ports_correspondence_dict
[link
["interface_id"]]["ports"].append(element
)
5882 for key
in sorted(ports_correspondence_dict
):
5883 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
5887 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
5888 return ovim
.clear_of_port_mapping(db_filter
={"datacenter_id":datacenter_id
})
5890 def create_RO_keypair(tenant_id
):
5892 Creates a public / private keys for a RO tenant and returns their values
5894 tenant_id: ID of the tenant
5896 public_key: Public key for the RO tenant
5897 private_key: Encrypted private key for RO tenant
5901 key
= RSA
.generate(bits
)
5903 public_key
= key
.publickey().exportKey('OpenSSH')
5904 if isinstance(public_key
, ValueError):
5905 raise NfvoException("Unable to create public key: {}".format(public_key
), httperrors
.Internal_Server_Error
)
5906 private_key
= key
.exportKey(passphrase
=tenant_id
, pkcs
=8)
5907 except (ValueError, NameError) as e
:
5908 raise NfvoException("Unable to create private key: {}".format(e
), httperrors
.Internal_Server_Error
)
5909 if isinstance(public_key
, bytes
):
5910 public_key
= public_key
.decode(encoding
='UTF-8')
5911 if isinstance(private_key
, bytes
):
5912 private_key
= private_key
.decode(encoding
='UTF-8')
5913 return public_key
, private_key
5915 def decrypt_key (key
, tenant_id
):
5917 Decrypts an encrypted RSA key
5919 key: Private key to be decrypted
5920 tenant_id: ID of the tenant
5922 unencrypted_key: Unencrypted private key for RO tenant
5925 key
= RSA
.importKey(key
,tenant_id
)
5926 unencrypted_key
= key
.exportKey('PEM')
5927 if isinstance(unencrypted_key
, ValueError):
5928 raise NfvoException("Unable to decrypt the private key: {}".format(unencrypted_key
), httperrors
.Internal_Server_Error
)
5929 if isinstance(unencrypted_key
, bytes
):
5930 unencrypted_key
= unencrypted_key
.decode(encoding
='UTF-8')
5931 except ValueError as e
:
5932 raise NfvoException("Unable to decrypt the private key: {}".format(e
), httperrors
.Internal_Server_Error
)
5933 return unencrypted_key