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$"
34 from utils
import deprecated
36 import console_proxy_thread
as cli
41 from uuid
import uuid4
42 from db_base
import db_base_Exception
45 from threading
import Lock
47 from lib_osm_openvim
import ovim
as ovim_module
48 from lib_osm_openvim
.ovim
import ovimException
49 from Crypto
.PublicKey
import RSA
51 import osm_im
.vnfd
as vnfd_catalog
52 import osm_im
.nsd
as nsd_catalog
53 from pyangbind
.lib
.serialise
import pybindJSONDecoder
54 from copy
import deepcopy
58 import wim
.wimconn
as wimconn
59 import wim
.wim_thread
as wim_thread
60 from .http_tools
import errors
as httperrors
61 from .wim
.engine
import WimEngine
62 from .wim
.persistence
import WimPersistence
63 from copy
import deepcopy
64 from pprint
import pformat
68 global vimconn_imported
72 global wimconn_imported
75 global default_volume_size
76 default_volume_size
= '5' #size in GB
81 vimconn_imported
= {} # dictionary with VIM type as key, loaded module as value
82 vim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-VIMs
83 vim_persistent_info
= {}
85 wimconn_imported
= {} # dictionary with WIM type as key, loaded module as value
86 wim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-WIMs
87 wim_persistent_info
= {}
90 logger
= logging
.getLogger('openmano.nfvo')
97 class NfvoException(httperrors
.HttpMappedError
):
98 """Common Class for NFVO errors"""
104 if task_id
<= last_task_id
:
105 task_id
= last_task_id
+ 0.000001
106 last_task_id
= task_id
107 return "ACTION-{:.6f}".format(task_id
)
108 # return (t.strftime("%Y%m%dT%H%M%S.{}%Z", t.localtime(task_id))).format(int((task_id % 1)*1e6))
111 def new_task(name
, params
, depends
=None):
113 task_id
= get_task_id()
114 task
= {"status": "enqueued", "id": task_id
, "name": name
, "params": params
}
116 task
["depends"] = depends
121 return True if id[:5] == "TASK-" else False
124 def get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_name
, tenant_id
):
125 name
= datacenter_name
[:16]
126 if name
not in vim_threads
["names"]:
127 vim_threads
["names"].append(name
)
129 name
= datacenter_name
[:16] + "." + tenant_name
[:16]
130 if name
not in vim_threads
["names"]:
131 vim_threads
["names"].append(name
)
133 name
= datacenter_id
+ "-" + tenant_id
134 vim_threads
["names"].append(name
)
138 def get_non_used_wim_name(wim_name
, wim_id
, tenant_name
, tenant_id
):
140 if name
not in wim_threads
["names"]:
141 wim_threads
["names"].append(name
)
143 name
= wim_name
[:16] + "." + tenant_name
[:16]
144 if name
not in wim_threads
["names"]:
145 wim_threads
["names"].append(name
)
147 name
= wim_id
+ "-" + tenant_id
148 wim_threads
["names"].append(name
)
152 def start_service(mydb
, persistence
=None, wim
=None):
153 global db
, global_config
154 db
= nfvo_db
.nfvo_db(lock
=db_lock
)
156 db
.connect(global_config
['db_host'], global_config
['db_user'], global_config
['db_passwd'], global_config
['db_name'])
159 persistence
= persistence
or WimPersistence(db
)
161 # Initialize openvim for SDN control
162 # TODO: Avoid static configuration by adding new parameters to openmanod.cfg
163 # TODO: review ovim.py to delete not needed configuration
164 ovim_configuration
= {
165 'logger_name': 'openmano.ovim',
166 'network_vlan_range_start': 1000,
167 'network_vlan_range_end': 4096,
168 'db_name': global_config
["db_ovim_name"],
169 'db_host': global_config
["db_ovim_host"],
170 'db_user': global_config
["db_ovim_user"],
171 'db_passwd': global_config
["db_ovim_passwd"],
174 'network_type': 'bridge',
175 #TODO: log_level_of should not be needed. To be modified in ovim
176 'log_level_of': 'DEBUG'
179 # starts ovim library
180 ovim
= ovim_module
.ovim(ovim_configuration
)
183 wim_engine
= wim
or WimEngine(persistence
)
184 wim_engine
.ovim
= ovim
188 #delete old unneeded vim_wim_actions
192 from_
= 'tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join '\
193 'datacenter_tenants as dt on td.datacenter_tenant_id=dt.uuid'
194 select_
= ('type', 'd.config as config', 'd.uuid as datacenter_id', 'vim_url', 'vim_url_admin',
195 'd.name as datacenter_name', 'dt.uuid as datacenter_tenant_id',
196 'dt.vim_tenant_name as vim_tenant_name', 'dt.vim_tenant_id as vim_tenant_id',
197 'user', 'passwd', 'dt.config as dt_config', 'nfvo_tenant_id')
198 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
)
200 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
201 'datacenter_id': vim
.get('datacenter_id')}
203 extra
.update(yaml
.load(vim
["config"]))
204 if vim
.get('dt_config'):
205 extra
.update(yaml
.load(vim
["dt_config"]))
206 if vim
["type"] not in vimconn_imported
:
209 module
= "vimconn_" + vim
["type"]
210 pkg
= __import__("osm_ro." + module
)
211 vim_conn
= getattr(pkg
, module
)
212 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
213 # vim_conn = imp.load_module(vim["type"], *module_info)
214 vimconn_imported
[vim
["type"]] = vim_conn
215 except (IOError, ImportError) as e
:
216 # if module_info and module_info[0]:
217 # file.close(module_info[0])
218 raise NfvoException("Unknown vim type '{}'. Cannot open file '{}.py'; {}: {}".format(
219 vim
["type"], module
, type(e
).__name
__, str(e
)), httperrors
.Bad_Request
)
221 thread_id
= vim
['datacenter_tenant_id']
222 vim_persistent_info
[thread_id
] = {}
225 # return -httperrors.Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
226 myvim
= vimconn_imported
[ vim
["type"] ].vimconnector(
227 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
228 tenant_id
=vim
['vim_tenant_id'], tenant_name
=vim
['vim_tenant_name'],
229 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
230 user
=vim
['user'], passwd
=vim
['passwd'],
231 config
=extra
, persistent_info
=vim_persistent_info
[thread_id
]
233 except vimconn
.vimconnException
as e
:
235 logger
.error("Cannot launch thread for VIM {} '{}': {}".format(vim
['datacenter_name'],
236 vim
['datacenter_id'], e
))
237 except Exception as 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
['vim_tenant_id'], vim
['vim_tenant_name'],
241 vim
['vim_tenant_id'])
242 new_thread
= vim_thread
.vim_thread(task_lock
, thread_name
, vim
['datacenter_name'],
243 vim
['datacenter_tenant_id'], db
=db
, db_lock
=db_lock
, ovim
=ovim
)
245 vim_threads
["running"][thread_id
] = new_thread
247 wim_engine
.start_threads()
248 except db_base_Exception
as e
:
249 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
250 except ovim_module
.ovimException
as e
:
252 if message
[:22] == "DATABASE wrong version":
253 message
= "DATABASE wrong version of lib_osm_openvim {msg} -d{dbname} -u{dbuser} -p{dbpass} {ver}' "\
254 "at host {dbhost}".format(
255 msg
=message
[22:-3], dbname
=global_config
["db_ovim_name"],
256 dbuser
=global_config
["db_ovim_user"], dbpass
=global_config
["db_ovim_passwd"],
257 ver
=message
[-3:-1], dbhost
=global_config
["db_ovim_host"])
258 raise NfvoException(message
, httperrors
.Bad_Request
)
262 global ovim
, global_config
265 for thread_id
, thread
in vim_threads
["running"].items():
266 thread
.insert_task("exit")
267 vim_threads
["deleting"][thread_id
] = thread
268 vim_threads
["running"] = {}
271 wim_engine
.stop_threads()
273 if global_config
and global_config
.get("console_thread"):
274 for thread
in global_config
["console_thread"]:
275 thread
.terminate
= True
278 return ("openmanod version {} {}\n(c) Copyright Telefonica".format(global_config
["version"],
279 global_config
["version_date"] ))
283 Clean unused or old entries at database to avoid unlimited growing
284 :param mydb: database connector
287 # get and delete unused vim_wim_actions: all elements deleted, one week before, instance not present
288 now
= t
.time()-3600*24*7
289 instance_action_id
= None
292 actions_to_delete
= mydb
.get_rows(
293 SELECT
=("item", "item_id", "instance_action_id"),
294 FROM
="vim_wim_actions as va join instance_actions as ia on va.instance_action_id=ia.uuid "
295 "left join instance_scenarios as i on ia.instance_id=i.uuid",
296 WHERE
={"va.action": "DELETE", "va.modified_at<": now
, "i.uuid": None,
297 "va.status": ("DONE", "SUPERSEDED")},
300 for to_delete
in actions_to_delete
:
301 mydb
.delete_row(FROM
="vim_wim_actions", WHERE
=to_delete
)
302 if instance_action_id
!= to_delete
["instance_action_id"]:
303 instance_action_id
= to_delete
["instance_action_id"]
304 mydb
.delete_row(FROM
="instance_actions", WHERE
={"uuid": instance_action_id
})
305 nb_deleted
+= len(actions_to_delete
)
306 if len(actions_to_delete
) < 100:
309 logger
.debug("Removed {} unused vim_wim_actions".format(nb_deleted
))
312 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
314 return result, content:
315 <0, error_text upon error
316 nb_records, flavor_list on success
319 WHERE_dict
['vnf_id'] = vnf_id
320 if nfvo_tenant
is not None:
321 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
323 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
324 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
325 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
326 #print "get_flavor_list result:", result
327 #print "get_flavor_list content:", content
329 for flavor
in flavors
:
330 flavorList
.append(flavor
['flavor_id'])
334 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
336 Get used images of all vms belonging to this VNFD
337 :param mydb: database conector
338 :param vnf_id: vnfd uuid
339 :param nfvo_tenant: tenant, not used
340 :return: The list of image uuid used
343 vms
= mydb
.get_rows(SELECT
=('image_id','image_list'), FROM
='vms', WHERE
={'vnf_id': vnf_id
})
345 if vm
["image_id"] and vm
["image_id"] not in image_list
:
346 image_list
.append(vm
["image_id"])
348 vm_image_list
= yaml
.load(vm
["image_list"])
349 for image_dict
in vm_image_list
:
350 if image_dict
["image_id"] not in image_list
:
351 image_list
.append(image_dict
["image_id"])
355 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
356 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None, ignore_errors
=False):
357 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
358 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
359 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
360 raise exception upon error
363 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
364 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
365 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
366 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
367 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
368 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
369 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
370 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'
371 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
372 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
373 'user','passwd', 'dt.config as dt_config')
375 from_
= 'datacenters as d'
376 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
378 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
381 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
382 'datacenter_id': vim
.get('datacenter_id'),
383 '_vim_type_internal': vim
.get('type')}
385 extra
.update(yaml
.load(vim
["config"]))
386 if vim
.get('dt_config'):
387 extra
.update(yaml
.load(vim
["dt_config"]))
388 if vim
["type"] not in vimconn_imported
:
391 module
= "vimconn_" + vim
["type"]
392 pkg
= __import__("osm_ro." + module
)
393 vim_conn
= getattr(pkg
, module
)
394 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
395 # vim_conn = imp.load_module(vim["type"], *module_info)
396 vimconn_imported
[vim
["type"]] = vim_conn
397 except (IOError, ImportError) as e
:
398 # if module_info and module_info[0]:
399 # file.close(module_info[0])
401 logger
.error("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
402 vim
["type"], module
, type(e
).__name
__, str(e
)))
404 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
405 vim
["type"], module
, type(e
).__name
__, str(e
)), httperrors
.Bad_Request
)
408 if 'datacenter_tenant_id' in vim
:
409 thread_id
= vim
["datacenter_tenant_id"]
410 if thread_id
not in vim_persistent_info
:
411 vim_persistent_info
[thread_id
] = {}
412 persistent_info
= vim_persistent_info
[thread_id
]
416 # return -httperrors.Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
417 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
418 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
419 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
),
420 tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
421 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
422 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
423 config
=extra
, persistent_info
=persistent_info
425 except Exception as e
:
427 logger
.error("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)))
429 http_code
= httperrors
.Internal_Server_Error
430 if isinstance(e
, vimconn
.vimconnException
):
431 http_code
= e
.http_code
432 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), http_code
)
434 except db_base_Exception
as e
:
435 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
438 def rollback(mydb
, vims
, rollback_list
):
440 #delete things by reverse order
441 for i
in range(len(rollback_list
)-1, -1, -1):
442 item
= rollback_list
[i
]
443 if item
["where"]=="vim":
444 if item
["vim_id"] not in vims
:
446 if is_task_id(item
["uuid"]):
448 vim
= vims
[item
["vim_id"]]
450 if item
["what"]=="image":
451 vim
.delete_image(item
["uuid"])
452 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_vim_id": vim
["id"], "vim_id":item
["uuid"]})
453 elif item
["what"]=="flavor":
454 vim
.delete_flavor(item
["uuid"])
455 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_vim_id": vim
["id"], "vim_id":item
["uuid"]})
456 elif item
["what"]=="network":
457 vim
.delete_network(item
["uuid"])
458 elif item
["what"]=="vm":
459 vim
.delete_vminstance(item
["uuid"])
460 except vimconn
.vimconnException
as e
:
461 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
462 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
463 except db_base_Exception
as e
:
464 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
468 if item
["what"]=="image":
469 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
470 elif item
["what"]=="flavor":
471 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
472 except db_base_Exception
as e
:
473 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
474 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
475 if len(undeleted_items
)==0:
476 return True," Rollback successful."
478 return False," Rollback fails to delete: " + str(undeleted_items
)
481 def check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1):
483 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
485 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
487 #dataplane interfaces
488 for numa
in vnfc
.get("numas",() ):
489 for interface
in numa
.get("interfaces",()):
490 if interface
["name"] in name_dict
:
492 "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
493 vnfc
["name"], interface
["name"]),
494 httperrors
.Bad_Request
)
495 name_dict
[ interface
["name"] ] = "underlay"
497 for interface
in vnfc
.get("bridge-ifaces",() ):
498 if interface
["name"] in name_dict
:
500 "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
501 vnfc
["name"], interface
["name"]),
502 httperrors
.Bad_Request
)
503 name_dict
[ interface
["name"] ] = "overlay"
504 vnfc_interfaces
[ vnfc
["name"] ] = name_dict
505 # check bood-data info
506 # if "boot-data" in vnfc:
507 # # check that user-data is incompatible with users and config-files
508 # if (vnfc["boot-data"].get("users") or vnfc["boot-data"].get("config-files")) and vnfc["boot-data"].get("user-data"):
509 # raise NfvoException(
510 # "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
511 # httperrors.Bad_Request)
513 #check if the info in external_connections matches with the one in the vnfcs
515 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
516 if external_connection
["name"] in name_list
:
518 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
519 external_connection
["name"]),
520 httperrors
.Bad_Request
)
521 name_list
.append(external_connection
["name"])
522 if external_connection
["VNFC"] not in vnfc_interfaces
:
524 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
525 external_connection
["name"], external_connection
["VNFC"]),
526 httperrors
.Bad_Request
)
528 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
530 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
531 external_connection
["name"],
532 external_connection
["local_iface_name"]),
533 httperrors
.Bad_Request
)
535 #check if the info in internal_connections matches with the one in the vnfcs
537 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
538 if internal_connection
["name"] in name_list
:
540 "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection".format(
541 internal_connection
["name"]),
542 httperrors
.Bad_Request
)
543 name_list
.append(internal_connection
["name"])
544 #We should check that internal-connections of type "ptp" have only 2 elements
546 if len(internal_connection
["elements"])>2 and (internal_connection
.get("type") == "ptp" or internal_connection
.get("type") == "e-line"):
548 "Error at 'vnf:internal-connections[name:'{}']:elements', size must be 2 for a '{}' type. Consider change it to '{}' type".format(
549 internal_connection
["name"],
550 'ptp' if vnf_descriptor_version
==1 else 'e-line',
551 'data' if vnf_descriptor_version
==1 else "e-lan"),
552 httperrors
.Bad_Request
)
553 for port
in internal_connection
["elements"]:
555 iface
= port
["local_iface_name"]
556 if vnf
not in vnfc_interfaces
:
558 "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
559 internal_connection
["name"], vnf
),
560 httperrors
.Bad_Request
)
561 if iface
not in vnfc_interfaces
[ vnf
]:
563 "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
564 internal_connection
["name"], iface
),
565 httperrors
.Bad_Request
)
566 return -httperrors
.Bad_Request
,
567 if vnf_descriptor_version
==1 and "type" not in internal_connection
:
568 if vnfc_interfaces
[vnf
][iface
] == "overlay":
569 internal_connection
["type"] = "bridge"
571 internal_connection
["type"] = "data"
572 if vnf_descriptor_version
==2 and "implementation" not in internal_connection
:
573 if vnfc_interfaces
[vnf
][iface
] == "overlay":
574 internal_connection
["implementation"] = "overlay"
576 internal_connection
["implementation"] = "underlay"
577 if (internal_connection
.get("type") == "data" or internal_connection
.get("type") == "ptp" or \
578 internal_connection
.get("implementation") == "underlay") and vnfc_interfaces
[vnf
][iface
] == "overlay":
580 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
581 internal_connection
["name"],
582 iface
, 'bridge' if vnf_descriptor_version
==1 else 'overlay',
583 'data' if vnf_descriptor_version
==1 else 'underlay'),
584 httperrors
.Bad_Request
)
585 if (internal_connection
.get("type") == "bridge" or internal_connection
.get("implementation") == "overlay") and \
586 vnfc_interfaces
[vnf
][iface
] == "underlay":
588 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
589 internal_connection
["name"], iface
,
590 'data' if vnf_descriptor_version
==1 else 'underlay',
591 'bridge' if vnf_descriptor_version
==1 else 'overlay'),
592 httperrors
.Bad_Request
)
595 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=None):
597 if only_create_at_vim
:
598 image_mano_id
= image_dict
['uuid']
599 if return_on_error
== None:
600 return_on_error
= True
602 if image_dict
['location']:
603 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
605 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
607 image_mano_id
= images
[0]['uuid']
609 #create image in MANO DB
610 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
611 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
612 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
614 #temp_image_dict['location'] = image_dict.get('new_location') if image_dict['location'] is None
615 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
616 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
617 #create image at every vim
618 for vim_id
,vim
in vims
.iteritems():
619 datacenter_vim_id
= vim
["config"]["datacenter_tenant_id"]
620 image_created
="false"
622 image_db
= mydb
.get_rows(FROM
="datacenters_images",
623 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'image_id': image_mano_id
})
624 #look at VIM if this image exist
626 if image_dict
['location'] is not None:
627 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
630 filter_dict
['name'] = image_dict
['universal_name']
631 if image_dict
.get('checksum') != None:
632 filter_dict
['checksum'] = image_dict
['checksum']
633 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
634 vim_images
= vim
.get_image_list(filter_dict
)
635 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
636 if len(vim_images
) > 1:
637 raise vimconn
.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict
)), httperrors
.Conflict
)
638 elif len(vim_images
) == 0:
639 raise vimconn
.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict
)))
641 #logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
642 image_vim_id
= vim_images
[0]['id']
644 except vimconn
.vimconnNotFoundException
as e
:
645 #Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
647 #image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
648 if image_dict
['location']:
649 image_vim_id
= vim
.new_image(image_dict
)
650 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
653 #If we reach this point, then the image has image name, and optionally checksum, and could not be found
654 raise vimconn
.vimconnException(str(e
))
655 except vimconn
.vimconnException
as e
:
657 logger
.error("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
660 logger
.warn("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
662 except vimconn
.vimconnException
as e
:
664 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
666 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
669 #if we reach here, the image has been created or existed
671 #add new vim_id at datacenters_images
672 mydb
.new_row('datacenters_images', {'datacenter_vim_id': datacenter_vim_id
,
673 'image_id':image_mano_id
,
674 'vim_id': image_vim_id
,
675 'created':image_created
})
676 elif image_db
[0]["vim_id"]!=image_vim_id
:
677 #modify existing vim_id at datacenters_images
678 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_vim_id':vim_id
, 'image_id':image_mano_id
})
680 return image_vim_id
if only_create_at_vim
else image_mano_id
683 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
684 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',0),
685 'ram':flavor_dict
.get('ram'),
686 'vcpus':flavor_dict
.get('vcpus'),
688 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
689 del flavor_dict
['extended']
690 if 'extended' in flavor_dict
:
691 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
693 #look if flavor exist
694 if only_create_at_vim
:
695 flavor_mano_id
= flavor_dict
['uuid']
696 if return_on_error
== None:
697 return_on_error
= True
699 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
701 flavor_mano_id
= flavors
[0]['uuid']
704 #create one by one the images of aditional disks
705 dev_image_list
=[] #list of images
706 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
708 for device
in flavor_dict
['extended'].get('devices',[]):
709 if "image" not in device
and "image name" not in device
:
712 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
713 image_dict
['universal_name']=device
.get('image name')
714 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
715 image_dict
['location']=device
.get('image')
716 #image_dict['new_location']=vnfc.get('image location')
717 image_dict
['checksum']=device
.get('image checksum')
718 image_metadata_dict
= device
.get('image metadata', None)
719 image_metadata_str
= None
720 if image_metadata_dict
!= None:
721 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
722 image_dict
['metadata']=image_metadata_str
723 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
724 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
725 dev_image_list
.append(image_id
)
727 temp_flavor_dict
['name'] = flavor_dict
['name']
728 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
729 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
730 flavor_mano_id
= content
731 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
732 #create flavor at every vim
733 if 'uuid' in flavor_dict
:
734 del flavor_dict
['uuid']
736 for vim_id
,vim
in vims
.items():
737 datacenter_vim_id
= vim
["config"]["datacenter_tenant_id"]
738 flavor_created
="false"
740 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors",
741 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
})
742 #look at VIM if this flavor exist SKIPPED
743 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
745 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
749 # Create the flavor in VIM
750 # Translate images at devices from MANO id to VIM id
752 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
753 # make a copy of original devices
756 for device
in flavor_dict
["extended"].get("devices",[]):
759 devices_original
.append(dev
)
760 if 'image' in device
:
762 if 'image metadata' in device
:
763 del device
['image metadata']
764 if 'image checksum' in device
:
765 del device
['image checksum']
767 for index
in range(0,len(devices_original
)) :
768 device
=devices_original
[index
]
769 if "image" not in device
and "image name" not in device
:
770 # if 'size' in device:
771 disk_list
.append({'size': device
.get('size', default_volume_size
), 'name': device
.get('name')})
774 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
775 image_dict
['universal_name']=device
.get('image name')
776 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
777 image_dict
['location']=device
.get('image')
778 # image_dict['new_location']=device.get('image location')
779 image_dict
['checksum']=device
.get('image checksum')
780 image_metadata_dict
= device
.get('image metadata', None)
781 image_metadata_str
= None
782 if image_metadata_dict
!= None:
783 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
784 image_dict
['metadata']=image_metadata_str
785 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
786 image_dict
["uuid"]=image_mano_id
787 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
789 #save disk information (image must be based on and size
790 disk_list
.append({'image_id': image_vim_id
, 'size': device
.get('size', default_volume_size
)})
792 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
795 #check that this vim_id exist in VIM, if not create
796 flavor_vim_id
=flavor_db
[0]["vim_id"]
798 vim
.get_flavor(flavor_vim_id
)
799 continue #flavor exist
800 except vimconn
.vimconnException
:
802 #create flavor at vim
803 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
806 flavor_vim_id
=vim
.get_flavor_id_from_data(flavor_dict
)
807 flavor_create
="false"
808 except vimconn
.vimconnException
as e
:
811 if not flavor_vim_id
:
812 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
813 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
814 flavor_created
="true"
815 except vimconn
.vimconnException
as e
:
817 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
819 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
822 #if reach here the flavor has been create or exist
823 if len(flavor_db
)==0:
824 #add new vim_id at datacenters_flavors
825 extended_devices_yaml
= None
826 if len(disk_list
) > 0:
827 extended_devices
= dict()
828 extended_devices
['disks'] = disk_list
829 extended_devices_yaml
= yaml
.safe_dump(extended_devices
,default_flow_style
=True,width
=256)
830 mydb
.new_row('datacenters_flavors',
831 {'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
, 'vim_id': flavor_vim_id
,
832 'created': flavor_created
, 'extended': extended_devices_yaml
})
833 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
834 #modify existing vim_id at datacenters_flavors
835 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
},
836 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
})
838 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
841 def get_str(obj
, field
, length
):
843 Obtain the str value,
848 value
= obj
.get(field
)
849 if value
is not None:
850 value
= str(value
)[:length
]
853 def _lookfor_or_create_image(db_image
, mydb
, descriptor
):
855 fill image content at db_image dictionary. Check if the image with this image and checksum exist
856 :param db_image: dictionary to insert data
857 :param mydb: database connector
858 :param descriptor: yang descriptor
859 :return: uuid if the image exist at DB, or None if a new image must be created with the data filled at db_image
862 db_image
["name"] = get_str(descriptor
, "image", 255)
863 db_image
["checksum"] = get_str(descriptor
, "image-checksum", 32)
864 if not db_image
["checksum"]: # Ensure that if empty string, None is stored
865 db_image
["checksum"] = None
866 if db_image
["name"].startswith("/"):
867 db_image
["location"] = db_image
["name"]
868 existing_images
= mydb
.get_rows(FROM
="images", WHERE
={'location': db_image
["location"]})
870 db_image
["universal_name"] = db_image
["name"]
871 existing_images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name': db_image
['universal_name'],
872 'checksum': db_image
['checksum']})
874 return existing_images
[0]["uuid"]
876 image_uuid
= str(uuid4())
877 db_image
["uuid"] = image_uuid
880 def get_resource_allocation_params(quota_descriptor
):
882 read the quota_descriptor from vnfd and fetch the resource allocation properties from the descriptor object
883 :param quota_descriptor: cpu/mem/vif/disk-io quota descriptor
884 :return: quota params for limit, reserve, shares from the descriptor object
887 if quota_descriptor
.get("limit"):
888 quota
["limit"] = int(quota_descriptor
["limit"])
889 if quota_descriptor
.get("reserve"):
890 quota
["reserve"] = int(quota_descriptor
["reserve"])
891 if quota_descriptor
.get("shares"):
892 quota
["shares"] = int(quota_descriptor
["shares"])
895 def new_vnfd_v3(mydb
, tenant_id
, vnf_descriptor
):
897 Parses an OSM IM vnfd_catalog and insert at DB
900 :param vnf_descriptor:
901 :return: The list of cretated vnf ids
904 myvnfd
= vnfd_catalog
.vnfd()
906 pybindJSONDecoder
.load_ietf_json(vnf_descriptor
, None, None, obj
=myvnfd
, path_helper
=True,
908 except Exception as e
:
909 raise NfvoException("Error. Invalid VNF descriptor format " + str(e
), httperrors
.Bad_Request
)
917 db_ip_profiles_index
= 0
921 vnfd_catalog_descriptor
= vnf_descriptor
.get("vnfd:vnfd-catalog")
922 if not vnfd_catalog_descriptor
:
923 vnfd_catalog_descriptor
= vnf_descriptor
.get("vnfd-catalog")
924 vnfd_descriptor_list
= vnfd_catalog_descriptor
.get("vnfd")
925 if not vnfd_descriptor_list
:
926 vnfd_descriptor_list
= vnfd_catalog_descriptor
.get("vnfd:vnfd")
927 for vnfd_yang
in myvnfd
.vnfd_catalog
.vnfd
.itervalues():
928 vnfd
= vnfd_yang
.get()
931 vnf_uuid
= str(uuid4())
932 uuid_list
.append(vnf_uuid
)
933 vnfd_uuid_list
.append(vnf_uuid
)
934 vnfd_id
= get_str(vnfd
, "id", 255)
938 "name": get_str(vnfd
, "name", 255),
939 "description": get_str(vnfd
, "description", 255),
940 "tenant_id": tenant_id
,
941 "vendor": get_str(vnfd
, "vendor", 255),
942 "short_name": get_str(vnfd
, "short-name", 255),
943 "descriptor": str(vnf_descriptor
)[:60000]
946 for vnfd_descriptor
in vnfd_descriptor_list
:
947 if vnfd_descriptor
["id"] == str(vnfd
["id"]):
950 # table ip_profiles (ip-profiles)
951 ip_profile_name2db_table_index
= {}
952 for ip_profile
in vnfd
.get("ip-profiles").itervalues():
954 "ip_version": str(ip_profile
["ip-profile-params"].get("ip-version", "ipv4")),
955 "subnet_address": str(ip_profile
["ip-profile-params"].get("subnet-address")),
956 "gateway_address": str(ip_profile
["ip-profile-params"].get("gateway-address")),
957 "dhcp_enabled": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("enabled", True)),
958 "dhcp_start_address": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("start-address")),
959 "dhcp_count": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("count")),
962 for dns
in ip_profile
["ip-profile-params"]["dns-server"].itervalues():
963 dns_list
.append(str(dns
.get("address")))
964 db_ip_profile
["dns_address"] = ";".join(dns_list
)
965 if ip_profile
["ip-profile-params"].get('security-group'):
966 db_ip_profile
["security_group"] = ip_profile
["ip-profile-params"]['security-group']
967 ip_profile_name2db_table_index
[str(ip_profile
["name"])] = db_ip_profiles_index
968 db_ip_profiles_index
+= 1
969 db_ip_profiles
.append(db_ip_profile
)
971 # table nets (internal-vld)
972 net_id2uuid
= {} # for mapping interface with network
973 for vld
in vnfd
.get("internal-vld").itervalues():
974 net_uuid
= str(uuid4())
975 uuid_list
.append(net_uuid
)
977 "name": get_str(vld
, "name", 255),
980 "description": get_str(vld
, "description", 255),
981 "osm_id": get_str(vld
, "id", 255),
982 "type": "bridge", # TODO adjust depending on connection point type
984 net_id2uuid
[vld
.get("id")] = net_uuid
985 db_nets
.append(db_net
)
986 # ip-profile, link db_ip_profile with db_sce_net
987 if vld
.get("ip-profile-ref"):
988 ip_profile_name
= vld
.get("ip-profile-ref")
989 if ip_profile_name
not in ip_profile_name2db_table_index
:
990 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vld[{}]':'ip-profile-ref':"
991 "'{}'. Reference to a non-existing 'ip_profiles'".format(
992 str(vnfd
["id"]), str(vld
["id"]), str(vld
["ip-profile-ref"])),
993 httperrors
.Bad_Request
)
994 db_ip_profiles
[ip_profile_name2db_table_index
[ip_profile_name
]]["net_id"] = net_uuid
995 else: #check no ip-address has been defined
996 for icp
in vld
.get("internal-connection-point").itervalues():
997 if icp
.get("ip-address"):
998 raise NfvoException("Error at 'vnfd[{}]':'vld[{}]':'internal-connection-point[{}]' "
999 "contains an ip-address but no ip-profile has been defined at VLD".format(
1000 str(vnfd
["id"]), str(vld
["id"]), str(icp
["id"])),
1001 httperrors
.Bad_Request
)
1003 # connection points vaiable declaration
1004 cp_name2iface_uuid
= {}
1005 cp_name2vm_uuid
= {}
1006 cp_name2db_interface
= {}
1007 vdu_id2cp_name
= {} # stored only when one external connection point is presented at this VDU
1011 vdu_id2db_table_index
= {}
1012 for vdu
in vnfd
.get("vdu").itervalues():
1014 for vdu_descriptor
in vnfd_descriptor
["vdu"]:
1015 if vdu_descriptor
["id"] == str(vdu
["id"]):
1017 vm_uuid
= str(uuid4())
1018 uuid_list
.append(vm_uuid
)
1019 vdu_id
= get_str(vdu
, "id", 255)
1023 "name": get_str(vdu
, "name", 255),
1024 "description": get_str(vdu
, "description", 255),
1025 "pdu_type": get_str(vdu
, "pdu-type", 255),
1028 vdu_id2uuid
[db_vm
["osm_id"]] = vm_uuid
1029 vdu_id2db_table_index
[db_vm
["osm_id"]] = db_vms_index
1030 if vdu
.get("count"):
1031 db_vm
["count"] = int(vdu
["count"])
1034 image_present
= False
1035 if vdu
.get("image"):
1036 image_present
= True
1038 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, vdu
)
1040 image_uuid
= db_image
["uuid"]
1041 db_images
.append(db_image
)
1042 db_vm
["image_id"] = image_uuid
1043 if vdu
.get("alternative-images"):
1044 vm_alternative_images
= []
1045 for alt_image
in vdu
.get("alternative-images").itervalues():
1047 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, alt_image
)
1049 image_uuid
= db_image
["uuid"]
1050 db_images
.append(db_image
)
1051 vm_alternative_images
.append({
1052 "image_id": image_uuid
,
1053 "vim_type": str(alt_image
["vim-type"]),
1054 # "universal_name": str(alt_image["image"]),
1055 # "checksum": str(alt_image["image-checksum"]) if alt_image.get("image-checksum") else None
1058 db_vm
["image_list"] = yaml
.safe_dump(vm_alternative_images
, default_flow_style
=True, width
=256)
1062 if vdu
.get("volumes"):
1063 for volume_key
in vdu
["volumes"]:
1064 volume
= vdu
["volumes"][volume_key
]
1065 if not image_present
:
1066 # Convert the first volume to vnfc.image
1067 image_present
= True
1069 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, volume
)
1071 image_uuid
= db_image
["uuid"]
1072 db_images
.append(db_image
)
1073 db_vm
["image_id"] = image_uuid
1075 # Add Openmano devices
1076 device
= {"name": str(volume
.get("name"))}
1077 device
["type"] = str(volume
.get("device-type"))
1078 if volume
.get("size"):
1079 device
["size"] = int(volume
["size"])
1080 if volume
.get("image"):
1081 device
["image name"] = str(volume
["image"])
1082 if volume
.get("image-checksum"):
1083 device
["image checksum"] = str(volume
["image-checksum"])
1085 devices
.append(device
)
1087 if not db_vm
.get("image_id"):
1088 if not db_vm
["pdu_type"]:
1089 raise NfvoException("Not defined image for VDU")
1090 # create a fake image
1094 if vdu
.get("cloud-init"):
1095 boot_data
["user-data"] = str(vdu
["cloud-init"])
1096 elif vdu
.get("cloud-init-file"):
1097 # TODO Where this file content is present???
1098 # boot_data["user-data"] = vnfd_yang.files[vdu["cloud-init-file"]]
1099 boot_data
["user-data"] = str(vdu
["cloud-init-file"])
1101 if vdu
.get("supplemental-boot-data"):
1102 if vdu
["supplemental-boot-data"].get('boot-data-drive'):
1103 boot_data
['boot-data-drive'] = True
1104 if vdu
["supplemental-boot-data"].get('config-file'):
1105 om_cfgfile_list
= list()
1106 for custom_config_file
in vdu
["supplemental-boot-data"]['config-file'].itervalues():
1107 # TODO Where this file content is present???
1108 cfg_source
= str(custom_config_file
["source"])
1109 om_cfgfile_list
.append({"dest": custom_config_file
["dest"],
1110 "content": cfg_source
})
1111 boot_data
['config-files'] = om_cfgfile_list
1113 db_vm
["boot_data"] = yaml
.safe_dump(boot_data
, default_flow_style
=True, width
=256)
1115 db_vms
.append(db_vm
)
1118 # table interfaces (internal/external interfaces)
1119 flavor_epa_interfaces
= []
1120 # for iface in chain(vdu.get("internal-interface").itervalues(), vdu.get("external-interface").itervalues()):
1121 for iface
in vdu
.get("interface").itervalues():
1122 flavor_epa_interface
= {}
1123 iface_uuid
= str(uuid4())
1124 uuid_list
.append(iface_uuid
)
1127 "internal_name": get_str(iface
, "name", 255),
1130 flavor_epa_interface
["name"] = db_interface
["internal_name"]
1131 if iface
.get("virtual-interface").get("vpci"):
1132 db_interface
["vpci"] = get_str(iface
.get("virtual-interface"), "vpci", 12)
1133 flavor_epa_interface
["vpci"] = db_interface
["vpci"]
1135 if iface
.get("virtual-interface").get("bandwidth"):
1136 bps
= int(iface
.get("virtual-interface").get("bandwidth"))
1137 db_interface
["bw"] = int(math
.ceil(bps
/1000000.0))
1138 flavor_epa_interface
["bandwidth"] = "{} Mbps".format(db_interface
["bw"])
1140 if iface
.get("virtual-interface").get("type") == "OM-MGMT":
1141 db_interface
["type"] = "mgmt"
1142 elif iface
.get("virtual-interface").get("type") in ("VIRTIO", "E1000", "PARAVIRT"):
1143 db_interface
["type"] = "bridge"
1144 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1145 elif iface
.get("virtual-interface").get("type") in ("SR-IOV", "PCI-PASSTHROUGH"):
1146 db_interface
["type"] = "data"
1147 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1148 flavor_epa_interface
["dedicated"] = "no" if iface
["virtual-interface"]["type"] == "SR-IOV" \
1150 flavor_epa_interfaces
.append(flavor_epa_interface
)
1152 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vdu[{}]':'interface':'virtual"
1153 "-interface':'type':'{}'. Interface type is not supported".format(
1154 vnfd_id
, vdu_id
, iface
.get("virtual-interface").get("type")),
1155 httperrors
.Bad_Request
)
1157 if iface
.get("mgmt-interface"):
1158 db_interface
["type"] = "mgmt"
1160 if iface
.get("external-connection-point-ref"):
1162 cp
= vnfd
.get("connection-point")[iface
.get("external-connection-point-ref")]
1163 db_interface
["external_name"] = get_str(cp
, "name", 255)
1164 cp_name2iface_uuid
[db_interface
["external_name"]] = iface_uuid
1165 cp_name2vm_uuid
[db_interface
["external_name"]] = vm_uuid
1166 cp_name2db_interface
[db_interface
["external_name"]] = db_interface
1167 for cp_descriptor
in vnfd_descriptor
["connection-point"]:
1168 if cp_descriptor
["name"] == db_interface
["external_name"]:
1173 if vdu_id
in vdu_id2cp_name
:
1174 vdu_id2cp_name
[vdu_id
] = None # more than two connecdtion point for this VDU
1176 vdu_id2cp_name
[vdu_id
] = db_interface
["external_name"]
1179 if str(cp_descriptor
.get("port-security-enabled")).lower() == "false":
1180 db_interface
["port_security"] = 0
1181 elif str(cp_descriptor
.get("port-security-enabled")).lower() == "true":
1182 db_interface
["port_security"] = 1
1184 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1185 "'interface[{iface}]':'vnfd-connection-point-ref':'{cp}' is not present"
1186 " at connection-point".format(
1187 vnf
=vnfd_id
, vdu
=vdu_id
, iface
=iface
["name"],
1188 cp
=iface
.get("vnfd-connection-point-ref")),
1189 httperrors
.Bad_Request
)
1190 elif iface
.get("internal-connection-point-ref"):
1192 for icp_descriptor
in vdu_descriptor
["internal-connection-point"]:
1193 if icp_descriptor
["id"] == str(iface
.get("internal-connection-point-ref")):
1196 raise KeyError("does not exist at vdu:internal-connection-point")
1199 for vld
in vnfd
.get("internal-vld").itervalues():
1200 for cp
in vld
.get("internal-connection-point").itervalues():
1201 if cp
.get("id-ref") == iface
.get("internal-connection-point-ref"):
1203 raise KeyError("is referenced by more than one 'internal-vld'")
1207 raise KeyError("is not referenced by any 'internal-vld'")
1209 db_interface
["net_id"] = net_id2uuid
[icp_vld
.get("id")]
1210 if str(icp_descriptor
.get("port-security-enabled")).lower() == "false":
1211 db_interface
["port_security"] = 0
1212 elif str(icp_descriptor
.get("port-security-enabled")).lower() == "true":
1213 db_interface
["port_security"] = 1
1214 if icp
.get("ip-address"):
1215 if not icp_vld
.get("ip-profile-ref"):
1217 db_interface
["ip_address"] = str(icp
.get("ip-address"))
1218 except KeyError as e
:
1219 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1220 "'interface[{iface}]':'internal-connection-point-ref':'{cp}'"
1222 vnf
=vnfd_id
, vdu
=vdu_id
, iface
=iface
["name"],
1223 cp
=iface
.get("internal-connection-point-ref"), msg
=str(e
)),
1224 httperrors
.Bad_Request
)
1225 if iface
.get("position"):
1226 db_interface
["created_at"] = int(iface
.get("position")) * 50
1227 if iface
.get("mac-address"):
1228 db_interface
["mac"] = str(iface
.get("mac-address"))
1229 db_interfaces
.append(db_interface
)
1233 "name": get_str(vdu
, "name", 250) + "-flv",
1234 "vcpus": int(vdu
["vm-flavor"].get("vcpu-count", 1)),
1235 "ram": int(vdu
["vm-flavor"].get("memory-mb", 1)),
1236 "disk": int(vdu
["vm-flavor"].get("storage-gb", 0)),
1238 # TODO revise the case of several numa-node-policy node
1242 extended
["devices"] = devices
1243 if flavor_epa_interfaces
:
1244 numa
["interfaces"] = flavor_epa_interfaces
1245 if vdu
.get("guest-epa"): # TODO or dedicated_int:
1246 epa_vcpu_set
= False
1247 if vdu
["guest-epa"].get("numa-node-policy"): # TODO or dedicated_int:
1248 numa_node_policy
= vdu
["guest-epa"].get("numa-node-policy")
1249 if numa_node_policy
.get("node"):
1250 numa_node
= numa_node_policy
["node"].values()[0]
1251 if numa_node
.get("num-cores"):
1252 numa
["cores"] = numa_node
["num-cores"]
1254 if numa_node
.get("paired-threads"):
1255 if numa_node
["paired-threads"].get("num-paired-threads"):
1256 numa
["paired-threads"] = int(numa_node
["paired-threads"]["num-paired-threads"])
1258 if len(numa_node
["paired-threads"].get("paired-thread-ids")):
1259 numa
["paired-threads-id"] = []
1260 for pair
in numa_node
["paired-threads"]["paired-thread-ids"].itervalues():
1261 numa
["paired-threads-id"].append(
1262 (str(pair
["thread-a"]), str(pair
["thread-b"]))
1264 if numa_node
.get("num-threads"):
1265 numa
["threads"] = int(numa_node
["num-threads"])
1267 if numa_node
.get("memory-mb"):
1268 numa
["memory"] = max(int(numa_node
["memory-mb"] / 1024), 1)
1269 if vdu
["guest-epa"].get("mempage-size"):
1270 if vdu
["guest-epa"]["mempage-size"] != "SMALL":
1271 numa
["memory"] = max(int(db_flavor
["ram"] / 1024), 1)
1272 if vdu
["guest-epa"].get("cpu-pinning-policy") and not epa_vcpu_set
:
1273 if vdu
["guest-epa"]["cpu-pinning-policy"] == "DEDICATED":
1274 if vdu
["guest-epa"].get("cpu-thread-pinning-policy") and \
1275 vdu
["guest-epa"]["cpu-thread-pinning-policy"] != "PREFER":
1276 numa
["cores"] = max(db_flavor
["vcpus"], 1)
1278 numa
["threads"] = max(db_flavor
["vcpus"], 1)
1280 if vdu
["guest-epa"].get("cpu-quota") and not epa_vcpu_set
:
1281 extended
["cpu-quota"] = get_resource_allocation_params(vdu
["guest-epa"].get("cpu-quota"))
1282 if vdu
["guest-epa"].get("mem-quota"):
1283 extended
["mem-quota"] = get_resource_allocation_params(vdu
["guest-epa"].get("mem-quota"))
1284 if vdu
["guest-epa"].get("disk-io-quota"):
1285 extended
["disk-io-quota"] = get_resource_allocation_params(vdu
["guest-epa"].get("disk-io-quota"))
1286 if vdu
["guest-epa"].get("vif-quota"):
1287 extended
["vif-quota"] = get_resource_allocation_params(vdu
["guest-epa"].get("vif-quota"))
1289 extended
["numas"] = [numa
]
1291 extended_text
= yaml
.safe_dump(extended
, default_flow_style
=True, width
=256)
1292 db_flavor
["extended"] = extended_text
1293 # look if flavor exist
1294 temp_flavor_dict
= {'disk': db_flavor
.get('disk', 0),
1295 'ram': db_flavor
.get('ram'),
1296 'vcpus': db_flavor
.get('vcpus'),
1297 'extended': db_flavor
.get('extended')
1299 existing_flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
1300 if existing_flavors
:
1301 flavor_uuid
= existing_flavors
[0]["uuid"]
1303 flavor_uuid
= str(uuid4())
1304 uuid_list
.append(flavor_uuid
)
1305 db_flavor
["uuid"] = flavor_uuid
1306 db_flavors
.append(db_flavor
)
1307 db_vm
["flavor_id"] = flavor_uuid
1309 # VNF affinity and antiaffinity
1310 for pg
in vnfd
.get("placement-groups").itervalues():
1311 pg_name
= get_str(pg
, "name", 255)
1312 for vdu
in pg
.get("member-vdus").itervalues():
1313 vdu_id
= get_str(vdu
, "member-vdu-ref", 255)
1314 if vdu_id
not in vdu_id2db_table_index
:
1315 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'placement-groups[{pg}]':"
1316 "'member-vdus':'{vdu}'. Reference to a non-existing vdu".format(
1317 vnf
=vnfd_id
, pg
=pg_name
, vdu
=vdu_id
),
1318 httperrors
.Bad_Request
)
1319 db_vms
[vdu_id2db_table_index
[vdu_id
]]["availability_zone"] = pg_name
1320 # TODO consider the case of isolation and not colocation
1321 # if pg.get("strategy") == "ISOLATION":
1323 # VNF mgmt configuration
1325 if vnfd
["mgmt-interface"].get("vdu-id"):
1326 mgmt_vdu_id
= get_str(vnfd
["mgmt-interface"], "vdu-id", 255)
1327 if mgmt_vdu_id
not in vdu_id2uuid
:
1328 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'vdu-id':"
1329 "'{vdu}'. Reference to a non-existing vdu".format(
1330 vnf
=vnfd_id
, vdu
=mgmt_vdu_id
),
1331 httperrors
.Bad_Request
)
1332 mgmt_access
["vm_id"] = vdu_id2uuid
[vnfd
["mgmt-interface"]["vdu-id"]]
1333 # if only one cp is defined by this VDU, mark this interface as of type "mgmt"
1334 if vdu_id2cp_name
.get(mgmt_vdu_id
):
1335 if cp_name2db_interface
[vdu_id2cp_name
[mgmt_vdu_id
]]:
1336 cp_name2db_interface
[vdu_id2cp_name
[mgmt_vdu_id
]]["type"] = "mgmt"
1338 if vnfd
["mgmt-interface"].get("ip-address"):
1339 mgmt_access
["ip-address"] = str(vnfd
["mgmt-interface"].get("ip-address"))
1340 if vnfd
["mgmt-interface"].get("cp"):
1341 if vnfd
["mgmt-interface"]["cp"] not in cp_name2iface_uuid
:
1342 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'cp'['{cp}']. "
1343 "Reference to a non-existing connection-point".format(
1344 vnf
=vnfd_id
, cp
=vnfd
["mgmt-interface"]["cp"]),
1345 httperrors
.Bad_Request
)
1346 mgmt_access
["vm_id"] = cp_name2vm_uuid
[vnfd
["mgmt-interface"]["cp"]]
1347 mgmt_access
["interface_id"] = cp_name2iface_uuid
[vnfd
["mgmt-interface"]["cp"]]
1348 # mark this interface as of type mgmt
1349 if cp_name2db_interface
[vnfd
["mgmt-interface"]["cp"]]:
1350 cp_name2db_interface
[vnfd
["mgmt-interface"]["cp"]]["type"] = "mgmt"
1352 default_user
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1356 mgmt_access
["default_user"] = default_user
1357 required
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1360 mgmt_access
["required"] = required
1363 db_vnf
["mgmt_access"] = yaml
.safe_dump(mgmt_access
, default_flow_style
=True, width
=256)
1365 db_vnfs
.append(db_vnf
)
1369 {"images": db_images
},
1370 {"flavors": db_flavors
},
1371 {"ip_profiles": db_ip_profiles
},
1373 {"interfaces": db_interfaces
},
1376 logger
.debug("create_vnf Deployment done vnfDict: %s",
1377 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
1378 mydb
.new_rows(db_tables
, uuid_list
)
1379 return vnfd_uuid_list
1380 except NfvoException
:
1382 except Exception as e
:
1383 logger
.error("Exception {}".format(e
))
1384 raise # NfvoException("Exception {}".format(e), httperrors.Bad_Request)
1387 @deprecated("Use new_vnfd_v3")
1388 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
1389 global global_config
1391 # Step 1. Check the VNF descriptor
1392 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
1393 # Step 2. Check tenant exist
1395 if tenant_id
!= "any":
1396 check_tenant(mydb
, tenant_id
)
1397 if "tenant_id" in vnf_descriptor
["vnf"]:
1398 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1399 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1400 httperrors
.Unauthorized
)
1402 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1403 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1404 if global_config
["auto_push_VNF_to_VIMs"]:
1405 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1407 # Step 4. Review the descriptor and add missing fields
1408 #print vnf_descriptor
1409 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1410 vnf_name
= vnf_descriptor
['vnf']['name']
1411 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1412 if "physical" in vnf_descriptor
['vnf']:
1413 del vnf_descriptor
['vnf']['physical']
1414 #print vnf_descriptor
1416 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1417 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1418 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1420 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1421 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1422 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1424 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1425 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1427 VNFCitem
["name"] = vnfc
['name']
1428 VNFCitem
["availability_zone"] = vnfc
.get('availability_zone')
1429 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
1431 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1434 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1435 myflavorDict
["description"] = VNFCitem
["description"]
1436 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1437 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1438 myflavorDict
["disk"] = vnfc
.get("disk", 0)
1439 myflavorDict
["extended"] = {}
1441 devices
= vnfc
.get("devices")
1443 myflavorDict
["extended"]["devices"] = devices
1446 # 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
1447 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1449 # Previous code has been commented
1450 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1451 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1452 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1453 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1455 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1457 # print "Error creating flavor: unknown processor model. Rollback successful."
1458 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1460 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1461 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1463 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1464 myflavorDict
['extended']['numas'] = vnfc
['numas']
1468 # Step 6.2 New flavors are created in the VIM
1469 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1471 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1472 VNFCitem
["flavor_id"] = flavor_id
1473 VNFCDict
[vnfc
['name']] = VNFCitem
1475 logger
.debug("Creating new images in the VIM for each VNFC")
1476 # Step 6.3 New images are created in the VIM
1477 #For each VNFC, we must create the appropriate image.
1478 #This "for" loop might be integrated with the previous one
1479 #In case this integration is made, the VNFCDict might become a VNFClist.
1480 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1481 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1483 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1484 image_dict
['universal_name']=vnfc
.get('image name')
1485 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1486 image_dict
['location']=vnfc
.get('VNFC image')
1487 #image_dict['new_location']=vnfc.get('image location')
1488 image_dict
['checksum']=vnfc
.get('image checksum')
1489 image_metadata_dict
= vnfc
.get('image metadata', None)
1490 image_metadata_str
= None
1491 if image_metadata_dict
is not None:
1492 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1493 image_dict
['metadata']=image_metadata_str
1494 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1495 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1496 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1497 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1498 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1499 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1500 if vnfc
.get("boot-data"):
1501 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1504 # Step 7. Storing the VNF descriptor in the repository
1505 if "descriptor" not in vnf_descriptor
["vnf"]:
1506 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1508 # Step 8. Adding the VNF to the NFVO DB
1509 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1511 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1512 _
, message
= rollback(mydb
, vims
, rollback_list
)
1513 if isinstance(e
, db_base_Exception
):
1514 error_text
= "Exception at database"
1515 elif isinstance(e
, KeyError):
1516 error_text
= "KeyError exception "
1517 e
.http_code
= httperrors
.Internal_Server_Error
1519 error_text
= "Exception at VIM"
1520 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1521 #logger.error("start_scenario %s", error_text)
1522 raise NfvoException(error_text
, e
.http_code
)
1525 @deprecated("Use new_vnfd_v3")
1526 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
1527 global global_config
1529 # Step 1. Check the VNF descriptor
1530 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
1531 # Step 2. Check tenant exist
1533 if tenant_id
!= "any":
1534 check_tenant(mydb
, tenant_id
)
1535 if "tenant_id" in vnf_descriptor
["vnf"]:
1536 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1537 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1538 httperrors
.Unauthorized
)
1540 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1541 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1542 if global_config
["auto_push_VNF_to_VIMs"]:
1543 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1545 # Step 4. Review the descriptor and add missing fields
1546 #print vnf_descriptor
1547 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1548 vnf_name
= vnf_descriptor
['vnf']['name']
1549 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1550 if "physical" in vnf_descriptor
['vnf']:
1551 del vnf_descriptor
['vnf']['physical']
1552 #print vnf_descriptor
1554 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1555 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1556 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1558 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1559 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1560 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1562 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1563 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1565 VNFCitem
["name"] = vnfc
['name']
1566 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
1568 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1571 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1572 myflavorDict
["description"] = VNFCitem
["description"]
1573 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1574 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1575 myflavorDict
["disk"] = vnfc
.get("disk", 0)
1576 myflavorDict
["extended"] = {}
1578 devices
= vnfc
.get("devices")
1580 myflavorDict
["extended"]["devices"] = devices
1583 # 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
1584 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1586 # Previous code has been commented
1587 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1588 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1589 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1590 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1592 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1594 # print "Error creating flavor: unknown processor model. Rollback successful."
1595 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1597 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1598 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1600 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1601 myflavorDict
['extended']['numas'] = vnfc
['numas']
1605 # Step 6.2 New flavors are created in the VIM
1606 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1608 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1609 VNFCitem
["flavor_id"] = flavor_id
1610 VNFCDict
[vnfc
['name']] = VNFCitem
1612 logger
.debug("Creating new images in the VIM for each VNFC")
1613 # Step 6.3 New images are created in the VIM
1614 #For each VNFC, we must create the appropriate image.
1615 #This "for" loop might be integrated with the previous one
1616 #In case this integration is made, the VNFCDict might become a VNFClist.
1617 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1618 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1620 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1621 image_dict
['universal_name']=vnfc
.get('image name')
1622 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1623 image_dict
['location']=vnfc
.get('VNFC image')
1624 #image_dict['new_location']=vnfc.get('image location')
1625 image_dict
['checksum']=vnfc
.get('image checksum')
1626 image_metadata_dict
= vnfc
.get('image metadata', None)
1627 image_metadata_str
= None
1628 if image_metadata_dict
is not None:
1629 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1630 image_dict
['metadata']=image_metadata_str
1631 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1632 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1633 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1634 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1635 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1636 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1637 if vnfc
.get("boot-data"):
1638 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1640 # Step 7. Storing the VNF descriptor in the repository
1641 if "descriptor" not in vnf_descriptor
["vnf"]:
1642 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1644 # Step 8. Adding the VNF to the NFVO DB
1645 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1647 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1648 _
, message
= rollback(mydb
, vims
, rollback_list
)
1649 if isinstance(e
, db_base_Exception
):
1650 error_text
= "Exception at database"
1651 elif isinstance(e
, KeyError):
1652 error_text
= "KeyError exception "
1653 e
.http_code
= httperrors
.Internal_Server_Error
1655 error_text
= "Exception at VIM"
1656 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1657 #logger.error("start_scenario %s", error_text)
1658 raise NfvoException(error_text
, e
.http_code
)
1661 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
1662 #check valid tenant_id
1663 check_tenant(mydb
, tenant_id
)
1666 if tenant_id
!= "any":
1667 where_or
["tenant_id"] = tenant_id
1668 where_or
["public"] = True
1669 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1671 vnf_id
= vnf
["uuid"]
1672 filter_keys
= ('uuid', 'name', 'description', 'public', "tenant_id", "osm_id", "created_at")
1673 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
1674 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
1675 data
={'vnf' : filtered_content
}
1677 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
1678 SELECT
=('vms.uuid as uuid', 'vms.osm_id as osm_id', 'vms.name as name', 'vms.description as description',
1680 WHERE
={'vnfs.uuid': vnf_id
} )
1681 if len(content
) != 0:
1682 #raise NfvoException("vnf '{}' not found".format(vnf_id), httperrors.Not_Found)
1683 # change boot_data into boot-data
1685 if vm
.get("boot_data"):
1686 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
1689 data
['vnf']['VNFC'] = content
1690 #TODO: GET all the information from a VNFC and include it in the output.
1693 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
1694 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
1695 WHERE
={'vnfs.uuid': vnf_id
} )
1696 data
['vnf']['nets'] = content
1698 #GET ip-profile for each net
1699 for net
in data
['vnf']['nets']:
1700 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1701 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1702 WHERE
={'net_id': net
["uuid"]} )
1703 if len(ipprofiles
)==1:
1704 net
["ip_profile"] = ipprofiles
[0]
1705 elif len(ipprofiles
)>1:
1706 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), httperrors
.Bad_Request
)
1709 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1711 #GET External Interfaces
1712 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1713 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1714 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1715 WHERE
={'vnfs.uuid': vnf_id
, 'interfaces.external_name<>': None} )
1717 data
['vnf']['external-connections'] = content
1722 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1723 # Check tenant exist
1724 if tenant_id
!= "any":
1725 check_tenant(mydb
, tenant_id
)
1726 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1727 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1731 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1733 if tenant_id
!= "any":
1734 where_or
["tenant_id"] = tenant_id
1735 where_or
["public"] = True
1736 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1737 vnf_id
= vnf
["uuid"]
1739 # "Getting the list of flavors and tenants of the VNF"
1740 flavorList
= get_flavorlist(mydb
, vnf_id
)
1741 if len(flavorList
)==0:
1742 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1744 imageList
= get_imagelist(mydb
, vnf_id
)
1745 if len(imageList
)==0:
1746 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1748 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1750 raise NfvoException("vnf '{}' not found".format(vnf_id
), httperrors
.Not_Found
)
1753 for flavor
in flavorList
:
1754 #check if flavor is used by other vnf
1756 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1758 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1760 #flavor not used, must be deleted
1762 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id': flavor
})
1763 for flavor_vim
in c
:
1764 if not flavor_vim
['created']: # skip this flavor because not created by openmano
1768 for vim
in vims
.values():
1769 if vim
["config"]["datacenter_tenant_id"] == flavor_vim
["datacenter_vim_id"]:
1775 myvim
.delete_flavor(flavor_vim
["vim_id"])
1776 except vimconn
.vimconnNotFoundException
:
1777 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"],
1778 flavor_vim
["datacenter_vim_id"] )
1779 except vimconn
.vimconnException
as e
:
1780 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1781 flavor_vim
["vim_id"], flavor_vim
["datacenter_vim_id"], type(e
).__name
__, str(e
))
1782 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"],
1783 flavor_vim
["datacenter_vim_id"]))
1784 # delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1785 mydb
.delete_row_by_id('flavors', flavor
)
1786 except db_base_Exception
as e
:
1787 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1788 undeletedItems
.append("flavor {}".format(flavor
))
1791 for image
in imageList
:
1793 #check if image is used by other vnf
1794 c
= mydb
.get_rows(FROM
='vms', WHERE
=[{'image_id': image
}, {'image_list LIKE ': '%' + image
+ '%'}])
1796 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1798 #image not used, must be deleted
1800 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1802 if image_vim
["datacenter_vim_id"] not in vims
: # TODO change to datacenter_tenant_id
1804 if image_vim
['created']=='false': #skip this image because not created by openmano
1806 myvim
=vims
[ image_vim
["datacenter_id"] ]
1808 myvim
.delete_image(image_vim
["vim_id"])
1809 except vimconn
.vimconnNotFoundException
as e
:
1810 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1811 except vimconn
.vimconnException
as e
:
1812 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1813 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1814 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1815 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1816 mydb
.delete_row_by_id('images', image
)
1817 except db_base_Exception
as e
:
1818 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1819 undeletedItems
.append("image %s" % image
)
1821 return vnf_id
+ " " + vnf
["name"]
1823 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1826 @deprecated("Not used")
1827 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1828 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1832 return -httperrors
.Not_Found
, "datacenter '%s' not found" % datacenter_name
1833 myvim
= vims
.values()[0]
1834 result
,servers
= myvim
.get_hosts_info()
1836 return result
, servers
1837 topology
= {'name':myvim
['name'] , 'servers': servers
}
1838 return result
, topology
1841 def get_hosts(mydb
, nfvo_tenant_id
):
1842 vims
= get_vim(mydb
, nfvo_tenant_id
)
1844 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), httperrors
.Not_Found
)
1846 #print "nfvo.datacenter_action() error. Several datacenters found"
1847 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
1848 myvim
= vims
.values()[0]
1850 hosts
= myvim
.get_hosts()
1851 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1853 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1855 server
={'name':host
['name'], 'vms':[]}
1856 for vm
in host
['instances']:
1857 #get internal name and model
1859 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1860 WHERE
={'vim_vm_id':vm
['id']} )
1862 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1864 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1866 except db_base_Exception
as e
:
1867 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1868 datacenter
['Datacenters'][0]['servers'].append(server
)
1869 #return -400, "en construccion"
1871 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1873 except vimconn
.vimconnException
as e
:
1874 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1877 @deprecated("Use new_nsd_v3")
1878 def new_scenario(mydb
, tenant_id
, topo
):
1880 # result, vims = get_vim(mydb, tenant_id)
1882 # return result, vims
1884 if tenant_id
!= "any":
1885 check_tenant(mydb
, tenant_id
)
1886 if "tenant_id" in topo
:
1887 if topo
["tenant_id"] != tenant_id
:
1888 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1889 httperrors
.Unauthorized
)
1893 #1.1: get VNFs and external_networks (other_nets).
1895 other_nets
={} #external_networks, bridge_networks and data_networkds
1896 nodes
= topo
['topology']['nodes']
1897 for k
in nodes
.keys():
1898 if nodes
[k
]['type'] == 'VNF':
1900 vnfs
[k
]['ifaces'] = {}
1901 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1902 other_nets
[k
] = nodes
[k
]
1903 other_nets
[k
]['external']=True
1904 elif nodes
[k
]['type'] == 'network':
1905 other_nets
[k
] = nodes
[k
]
1906 other_nets
[k
]['external']=False
1909 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1910 for name
,vnf
in vnfs
.items():
1911 where
= {"OR": {"tenant_id": tenant_id
, 'public': "true"}}
1913 error_pos
= "'topology':'nodes':'" + name
+ "'"
1915 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1916 where
['uuid'] = vnf
['vnf_id']
1917 if 'VNF model' in vnf
:
1918 error_text
+= " 'VNF model' " + vnf
['VNF model']
1919 where
['name'] = vnf
['VNF model']
1921 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, httperrors
.Bad_Request
)
1923 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1927 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, httperrors
.Not_Found
)
1929 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", httperrors
.Conflict
)
1930 vnf
['uuid']=vnf_db
[0]['uuid']
1931 vnf
['description']=vnf_db
[0]['description']
1932 #get external interfaces
1933 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1934 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1935 WHERE
={'vnfs.uuid':vnf
['uuid'], 'external_name<>': None} )
1936 for ext_iface
in ext_ifaces
:
1937 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1939 #1.4 get list of connections
1940 conections
= topo
['topology']['connections']
1941 conections_list
= []
1942 conections_list_name
= []
1943 for k
in conections
.keys():
1944 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1945 ifaces_list
= conections
[k
]['nodes'].items()
1946 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1948 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1949 for k2
in conection_pair_list
:
1952 con_type
= conections
[k
].get("type", "link")
1953 if con_type
!= "link":
1955 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), httperrors
.Bad_Request
)
1956 other_nets
[k
] = {'external': False}
1957 if conections
[k
].get("graph"):
1958 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1959 ifaces_list
.append( (k
, None) )
1962 if con_type
== "external_network":
1963 other_nets
[k
]['external'] = True
1964 if conections
[k
].get("model"):
1965 other_nets
[k
]["model"] = conections
[k
]["model"]
1967 other_nets
[k
]["model"] = k
1968 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1969 other_nets
[k
]["model"] = con_type
1971 conections_list_name
.append(k
)
1972 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)
1973 #print set(ifaces_list)
1974 #check valid VNF and iface names
1975 for iface
in ifaces_list
:
1976 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1977 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1978 str(k
), iface
[0]), httperrors
.Not_Found
)
1979 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1980 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1981 str(k
), iface
[0], iface
[1]), httperrors
.Not_Found
)
1983 #1.5 unify connections from the pair list to a consolidated list
1985 while index
< len(conections_list
):
1987 while index2
< len(conections_list
):
1988 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1989 conections_list
[index
] |
= conections_list
[index2
]
1990 del conections_list
[index2
]
1991 del conections_list_name
[index2
]
1994 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1996 #for k in conections_list:
2001 #1.6 Delete non external nets
2002 # for k in other_nets.keys():
2003 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
2004 # for con in conections_list:
2006 # for index in range(0,len(con)):
2007 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
2008 # for index in delete_indexes:
2011 #1.7: Check external_ports are present at database table datacenter_nets
2012 for k
,net
in other_nets
.items():
2013 error_pos
= "'topology':'nodes':'" + k
+ "'"
2014 if net
['external']==False:
2015 if 'name' not in net
:
2017 if 'model' not in net
:
2018 raise NfvoException("needed a 'model' at " + error_pos
, httperrors
.Bad_Request
)
2019 if net
['model']=='bridge_net':
2020 net
['type']='bridge';
2021 elif net
['model']=='dataplane_net':
2024 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, httperrors
.Not_Found
)
2026 #IF we do not want to check that external network exist at datacenter
2031 # if 'net_id' in net:
2032 # error_text += " 'net_id' " + net['net_id']
2033 # WHERE_['uuid'] = net['net_id']
2034 # if 'model' in net:
2035 # error_text += " 'model' " + net['model']
2036 # WHERE_['name'] = net['model']
2037 # if len(WHERE_) == 0:
2038 # return -httperrors.Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
2039 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
2040 # FROM='datacenter_nets', WHERE=WHERE_ )
2042 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
2044 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
2045 # return -httperrors.Bad_Request, "unknown " +error_text+ " at " + error_pos
2047 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
2048 # return -httperrors.Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
2049 # other_nets[k].update(net_db[0])
2052 net_nb
=0 #Number of nets
2053 for con
in conections_list
:
2054 #check if this is connected to a external net
2058 for index
in range(0,len(con
)):
2059 #check if this is connected to a external net
2060 for net_key
in other_nets
.keys():
2061 if con
[index
][0]==net_key
:
2062 if other_net_index
>=0:
2063 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
2064 #print "nfvo.new_scenario " + error_text
2065 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2067 other_net_index
= index
2068 net_target
= net_key
2070 #print "other_net_index", other_net_index
2072 if other_net_index
>=0:
2073 del con
[other_net_index
]
2074 #IF we do not want to check that external network exist at datacenter
2075 if other_nets
[net_target
]['external'] :
2076 if "name" not in other_nets
[net_target
]:
2077 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
2078 if other_nets
[net_target
]["type"] == "external_network":
2079 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
2080 other_nets
[net_target
]["type"] = "data"
2082 other_nets
[net_target
]["type"] = "bridge"
2084 # if other_nets[net_target]['external'] :
2085 # 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
2086 # if type_=='data' and other_nets[net_target]['type']=="ptp":
2087 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
2088 # print "nfvo.new_scenario " + error_text
2089 # return -httperrors.Bad_Request, error_text
2092 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
2095 net_type_bridge
=False
2097 net_target
= "__-__net"+str(net_nb
)
2098 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
2099 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
2102 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
2103 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
2104 if iface_type
=='mgmt' or iface_type
=='bridge':
2105 net_type_bridge
= True
2107 net_type_data
= True
2108 if net_type_bridge
and net_type_data
:
2109 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
2110 #print "nfvo.new_scenario " + error_text
2111 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2112 elif net_type_bridge
:
2115 type_
='data' if len(con
)>2 else 'ptp'
2116 net_list
[net_target
]['type'] = type_
2119 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
2120 #print "nfvo.new_scenario " + error_text
2122 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2124 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
2125 #1.8.1 obtain management net
2126 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
2127 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
2128 #1.8.2 check all interfaces from all vnfs
2130 add_mgmt_net
= False
2131 for vnf
in vnfs
.values():
2132 for iface
in vnf
['ifaces'].values():
2133 if iface
['type']=='mgmt' and 'net_key' not in iface
:
2134 #iface not connected
2135 iface
['net_key'] = 'mgmt'
2137 if add_mgmt_net
and 'mgmt' not in net_list
:
2138 net_list
['mgmt']=mgmt_net
[0]
2139 net_list
['mgmt']['external']=True
2140 net_list
['mgmt']['graph']={'visible':False}
2142 net_list
.update(other_nets
)
2144 #print 'net_list', net_list
2149 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
2150 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
2151 'tenant_id':tenant_id
, 'name':topo
['name'],
2152 'description':topo
.get('description',topo
['name']),
2153 'public': topo
.get('public', False)
2159 @deprecated("Use new_nsd_v3")
2160 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
2161 """ This creates a new scenario for version 0.2 and 0.3"""
2162 scenario
= scenario_dict
["scenario"]
2163 if tenant_id
!= "any":
2164 check_tenant(mydb
, tenant_id
)
2165 if "tenant_id" in scenario
:
2166 if scenario
["tenant_id"] != tenant_id
:
2167 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
2168 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
2169 scenario
["tenant_id"], tenant_id
), httperrors
.Unauthorized
)
2173 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
2174 for name
,vnf
in scenario
["vnfs"].iteritems():
2175 where
= {"OR": {"tenant_id": tenant_id
, 'public': "true"}}
2177 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
2179 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
2180 where
['uuid'] = vnf
['vnf_id']
2181 if 'vnf_name' in vnf
:
2182 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
2183 where
['name'] = vnf
['vnf_name']
2185 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, httperrors
.Bad_Request
)
2186 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
2189 if len(vnf_db
) == 0:
2190 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, httperrors
.Not_Found
)
2191 elif len(vnf_db
) > 1:
2192 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", httperrors
.Conflict
)
2193 vnf
['uuid'] = vnf_db
[0]['uuid']
2194 vnf
['description'] = vnf_db
[0]['description']
2196 # get external interfaces
2197 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
2198 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
2199 WHERE
={'vnfs.uuid':vnf
['uuid'], 'external_name<>': None} )
2200 for ext_iface
in ext_ifaces
:
2201 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
2202 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
2204 # 2: Insert net_key and ip_address at every vnf interface
2205 for net_name
, net
in scenario
["networks"].items():
2206 net_type_bridge
= False
2207 net_type_data
= False
2208 for iface_dict
in net
["interfaces"]:
2209 if version
== "0.2":
2210 temp_dict
= iface_dict
2212 elif version
== "0.3":
2213 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
2214 ip_address
= iface_dict
.get('ip_address', None)
2215 for vnf
, iface
in temp_dict
.items():
2216 if vnf
not in scenario
["vnfs"]:
2217 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
2219 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2220 raise NfvoException(error_text
, httperrors
.Not_Found
)
2221 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
2222 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
2223 .format(net_name
, iface
)
2224 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2225 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2226 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
2227 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
2228 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
2229 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2230 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2231 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
2232 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
2233 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
2234 if iface_type
== 'mgmt' or iface_type
== 'bridge':
2235 net_type_bridge
= True
2237 net_type_data
= True
2239 if net_type_bridge
and net_type_data
:
2240 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
2242 # logger.debug("nfvo.new_scenario " + error_text)
2243 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2244 elif net_type_bridge
:
2247 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
2249 if net
.get("implementation"): # for v0.3
2250 if type_
== "bridge" and net
["implementation"] == "underlay":
2251 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
2252 "'network':'{}'".format(net_name
)
2253 # logger.debug(error_text)
2254 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2255 elif type_
!= "bridge" and net
["implementation"] == "overlay":
2256 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
2257 "'network':'{}'".format(net_name
)
2258 # logger.debug(error_text)
2259 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2260 net
.pop("implementation")
2261 if "type" in net
and version
== "0.3": # for v0.3
2262 if type_
== "data" and net
["type"] == "e-line":
2263 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
2264 "'e-line' at 'network':'{}'".format(net_name
)
2265 # logger.debug(error_text)
2266 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2267 elif type_
== "ptp" and net
["type"] == "e-lan":
2271 net
['name'] = net_name
2272 net
['external'] = net
.get('external', False)
2274 # 3: insert at database
2275 scenario
["nets"] = scenario
["networks"]
2276 scenario
['tenant_id'] = tenant_id
2277 scenario_id
= mydb
.new_scenario(scenario
)
2281 def new_nsd_v3(mydb
, tenant_id
, nsd_descriptor
):
2283 Parses an OSM IM nsd_catalog and insert at DB
2286 :param nsd_descriptor:
2287 :return: The list of created NSD ids
2290 mynsd
= nsd_catalog
.nsd()
2292 pybindJSONDecoder
.load_ietf_json(nsd_descriptor
, None, None, obj
=mynsd
, skip_unknown
=True)
2293 except Exception as e
:
2294 raise NfvoException("Error. Invalid NS descriptor format: " + str(e
), httperrors
.Bad_Request
)
2298 db_sce_interfaces
= []
2301 db_sce_rsp_hops
= []
2302 db_sce_classifiers
= []
2303 db_sce_classifier_matches
= []
2305 db_ip_profiles_index
= 0
2308 for nsd_yang
in mynsd
.nsd_catalog
.nsd
.itervalues():
2309 nsd
= nsd_yang
.get()
2312 scenario_uuid
= str(uuid4())
2313 uuid_list
.append(scenario_uuid
)
2314 nsd_uuid_list
.append(scenario_uuid
)
2316 "uuid": scenario_uuid
,
2317 "osm_id": get_str(nsd
, "id", 255),
2318 "name": get_str(nsd
, "name", 255),
2319 "description": get_str(nsd
, "description", 255),
2320 "tenant_id": tenant_id
,
2321 "vendor": get_str(nsd
, "vendor", 255),
2322 "short_name": get_str(nsd
, "short-name", 255),
2323 "descriptor": str(nsd_descriptor
)[:60000],
2325 db_scenarios
.append(db_scenario
)
2327 # table sce_vnfs (constituent-vnfd)
2328 vnf_index2scevnf_uuid
= {}
2329 vnf_index2vnf_uuid
= {}
2330 for vnf
in nsd
.get("constituent-vnfd").itervalues():
2331 existing_vnf
= mydb
.get_rows(FROM
="vnfs", WHERE
={'osm_id': str(vnf
["vnfd-id-ref"])[:255],
2332 'tenant_id': tenant_id
})
2333 if not existing_vnf
:
2334 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'constituent-vnfd':'vnfd-id-ref':"
2335 "'{}'. Reference to a non-existing VNFD in the catalog".format(
2336 str(nsd
["id"]), str(vnf
["vnfd-id-ref"])[:255]),
2337 httperrors
.Bad_Request
)
2338 sce_vnf_uuid
= str(uuid4())
2339 uuid_list
.append(sce_vnf_uuid
)
2341 "uuid": sce_vnf_uuid
,
2342 "scenario_id": scenario_uuid
,
2343 # "name": get_str(vnf, "member-vnf-index", 255),
2344 "name": existing_vnf
[0]["name"][:200] + "." + get_str(vnf
, "member-vnf-index", 50),
2345 "vnf_id": existing_vnf
[0]["uuid"],
2346 "member_vnf_index": str(vnf
["member-vnf-index"]),
2347 # TODO 'start-by-default': True
2349 vnf_index2scevnf_uuid
[str(vnf
['member-vnf-index'])] = sce_vnf_uuid
2350 vnf_index2vnf_uuid
[str(vnf
['member-vnf-index'])] = existing_vnf
[0]["uuid"]
2351 db_sce_vnfs
.append(db_sce_vnf
)
2353 # table ip_profiles (ip-profiles)
2354 ip_profile_name2db_table_index
= {}
2355 for ip_profile
in nsd
.get("ip-profiles").itervalues():
2357 "ip_version": str(ip_profile
["ip-profile-params"].get("ip-version", "ipv4")),
2358 "subnet_address": str(ip_profile
["ip-profile-params"].get("subnet-address")),
2359 "gateway_address": str(ip_profile
["ip-profile-params"].get("gateway-address")),
2360 "dhcp_enabled": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("enabled", True)),
2361 "dhcp_start_address": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("start-address")),
2362 "dhcp_count": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("count")),
2365 for dns
in ip_profile
["ip-profile-params"]["dns-server"].itervalues():
2366 dns_list
.append(str(dns
.get("address")))
2367 db_ip_profile
["dns_address"] = ";".join(dns_list
)
2368 if ip_profile
["ip-profile-params"].get('security-group'):
2369 db_ip_profile
["security_group"] = ip_profile
["ip-profile-params"]['security-group']
2370 ip_profile_name2db_table_index
[str(ip_profile
["name"])] = db_ip_profiles_index
2371 db_ip_profiles_index
+= 1
2372 db_ip_profiles
.append(db_ip_profile
)
2374 # table sce_nets (internal-vld)
2375 for vld
in nsd
.get("vld").itervalues():
2376 sce_net_uuid
= str(uuid4())
2377 uuid_list
.append(sce_net_uuid
)
2379 "uuid": sce_net_uuid
,
2380 "name": get_str(vld
, "name", 255),
2381 "scenario_id": scenario_uuid
,
2383 "multipoint": not vld
.get("type") == "ELINE",
2384 "osm_id": get_str(vld
, "id", 255),
2386 "description": get_str(vld
, "description", 255),
2388 # guess type of network
2389 if vld
.get("mgmt-network"):
2390 db_sce_net
["type"] = "bridge"
2391 db_sce_net
["external"] = True
2392 elif vld
.get("provider-network").get("overlay-type") == "VLAN":
2393 db_sce_net
["type"] = "data"
2395 # later on it will be fixed to bridge or data depending on the type of interfaces attached to it
2396 db_sce_net
["type"] = None
2397 db_sce_nets
.append(db_sce_net
)
2399 # ip-profile, link db_ip_profile with db_sce_net
2400 if vld
.get("ip-profile-ref"):
2401 ip_profile_name
= vld
.get("ip-profile-ref")
2402 if ip_profile_name
not in ip_profile_name2db_table_index
:
2403 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'ip-profile-ref':'{}'."
2404 " Reference to a non-existing 'ip_profiles'".format(
2405 str(nsd
["id"]), str(vld
["id"]), str(vld
["ip-profile-ref"])),
2406 httperrors
.Bad_Request
)
2407 db_ip_profiles
[ip_profile_name2db_table_index
[ip_profile_name
]]["sce_net_id"] = sce_net_uuid
2408 elif vld
.get("vim-network-name"):
2409 db_sce_net
["vim_network_name"] = get_str(vld
, "vim-network-name", 255)
2411 # table sce_interfaces (vld:vnfd-connection-point-ref)
2412 for iface
in vld
.get("vnfd-connection-point-ref").itervalues():
2413 vnf_index
= str(iface
['member-vnf-index-ref'])
2414 # check correct parameters
2415 if vnf_index
not in vnf_index2vnf_uuid
:
2416 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2417 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2418 "'nsd':'constituent-vnfd'".format(
2419 str(nsd
["id"]), str(vld
["id"]), str(iface
["member-vnf-index-ref"])),
2420 httperrors
.Bad_Request
)
2422 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid', 'i.type as iface_type'),
2423 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2424 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2425 'external_name': get_str(iface
, "vnfd-connection-point-ref",
2427 if not existing_ifaces
:
2428 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2429 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2430 "connection-point name at VNFD '{}'".format(
2431 str(nsd
["id"]), str(vld
["id"]), str(iface
["vnfd-connection-point-ref"]),
2432 str(iface
.get("vnfd-id-ref"))[:255]),
2433 httperrors
.Bad_Request
)
2434 interface_uuid
= existing_ifaces
[0]["uuid"]
2435 if existing_ifaces
[0]["iface_type"] == "data":
2436 db_sce_net
["type"] = "data"
2437 sce_interface_uuid
= str(uuid4())
2438 uuid_list
.append(sce_net_uuid
)
2439 iface_ip_address
= None
2440 if iface
.get("ip-address"):
2441 iface_ip_address
= str(iface
.get("ip-address"))
2442 db_sce_interface
= {
2443 "uuid": sce_interface_uuid
,
2444 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2445 "sce_net_id": sce_net_uuid
,
2446 "interface_id": interface_uuid
,
2447 "ip_address": iface_ip_address
,
2449 db_sce_interfaces
.append(db_sce_interface
)
2450 if not db_sce_net
["type"]:
2451 db_sce_net
["type"] = "bridge"
2453 # table sce_vnffgs (vnffgd)
2454 for vnffg
in nsd
.get("vnffgd").itervalues():
2455 sce_vnffg_uuid
= str(uuid4())
2456 uuid_list
.append(sce_vnffg_uuid
)
2458 "uuid": sce_vnffg_uuid
,
2459 "name": get_str(vnffg
, "name", 255),
2460 "scenario_id": scenario_uuid
,
2461 "vendor": get_str(vnffg
, "vendor", 255),
2462 "description": get_str(vld
, "description", 255),
2464 db_sce_vnffgs
.append(db_sce_vnffg
)
2467 for rsp
in vnffg
.get("rsp").itervalues():
2468 sce_rsp_uuid
= str(uuid4())
2469 uuid_list
.append(sce_rsp_uuid
)
2471 "uuid": sce_rsp_uuid
,
2472 "name": get_str(rsp
, "name", 255),
2473 "sce_vnffg_id": sce_vnffg_uuid
,
2474 "id": get_str(rsp
, "id", 255), # only useful to link with classifiers; will be removed later in the code
2476 db_sce_rsps
.append(db_sce_rsp
)
2477 for iface
in rsp
.get("vnfd-connection-point-ref").itervalues():
2478 vnf_index
= str(iface
['member-vnf-index-ref'])
2479 if_order
= int(iface
['order'])
2480 # check correct parameters
2481 if vnf_index
not in vnf_index2vnf_uuid
:
2482 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2483 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2484 "'nsd':'constituent-vnfd'".format(
2485 str(nsd
["id"]), str(rsp
["id"]), str(iface
["member-vnf-index-ref"])),
2486 httperrors
.Bad_Request
)
2488 ingress_existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2489 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2491 'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2492 'external_name': get_str(iface
, "vnfd-ingress-connection-point-ref",
2494 if not ingress_existing_ifaces
:
2495 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2496 "-ref':'vnfd-ingress-connection-point-ref':'{}'. Reference to a non-existing "
2497 "connection-point name at VNFD '{}'".format(
2498 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-ingress-connection-point-ref"]),
2499 str(iface
.get("vnfd-id-ref"))[:255]), httperrors
.Bad_Request
)
2501 egress_existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2502 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2504 'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2505 'external_name': get_str(iface
, "vnfd-egress-connection-point-ref",
2507 if not egress_existing_ifaces
:
2508 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2509 "-ref':'vnfd-egress-connection-point-ref':'{}'. Reference to a non-existing "
2510 "connection-point name at VNFD '{}'".format(
2511 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-egress-connection-point-ref"]),
2512 str(iface
.get("vnfd-id-ref"))[:255]), HTTP_Bad_Request
)
2514 ingress_interface_uuid
= ingress_existing_ifaces
[0]["uuid"]
2515 egress_interface_uuid
= egress_existing_ifaces
[0]["uuid"]
2516 sce_rsp_hop_uuid
= str(uuid4())
2517 uuid_list
.append(sce_rsp_hop_uuid
)
2519 "uuid": sce_rsp_hop_uuid
,
2520 "if_order": if_order
,
2521 "ingress_interface_id": ingress_interface_uuid
,
2522 "egress_interface_id": egress_interface_uuid
,
2523 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2524 "sce_rsp_id": sce_rsp_uuid
,
2526 db_sce_rsp_hops
.append(db_sce_rsp_hop
)
2528 # deal with classifiers
2529 for classifier
in vnffg
.get("classifier").itervalues():
2530 sce_classifier_uuid
= str(uuid4())
2531 uuid_list
.append(sce_classifier_uuid
)
2534 vnf_index
= str(classifier
['member-vnf-index-ref'])
2535 if vnf_index
not in vnf_index2vnf_uuid
:
2536 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'classifier[{}]':'vnfd-connection-point"
2537 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2538 "'nsd':'constituent-vnfd'".format(
2539 str(nsd
["id"]), str(classifier
["id"]), str(classifier
["member-vnf-index-ref"])),
2540 httperrors
.Bad_Request
)
2541 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2542 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2543 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2544 'external_name': get_str(classifier
, "vnfd-connection-point-ref",
2546 if not existing_ifaces
:
2547 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2548 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2549 "connection-point name at VNFD '{}'".format(
2550 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-connection-point-ref"]),
2551 str(iface
.get("vnfd-id-ref"))[:255]),
2552 httperrors
.Bad_Request
)
2553 interface_uuid
= existing_ifaces
[0]["uuid"]
2555 db_sce_classifier
= {
2556 "uuid": sce_classifier_uuid
,
2557 "name": get_str(classifier
, "name", 255),
2558 "sce_vnffg_id": sce_vnffg_uuid
,
2559 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2560 "interface_id": interface_uuid
,
2562 rsp_id
= get_str(classifier
, "rsp-id-ref", 255)
2563 rsp
= next((item
for item
in db_sce_rsps
if item
["id"] == rsp_id
), None)
2564 db_sce_classifier
["sce_rsp_id"] = rsp
["uuid"]
2565 db_sce_classifiers
.append(db_sce_classifier
)
2567 for match
in classifier
.get("match-attributes").itervalues():
2568 sce_classifier_match_uuid
= str(uuid4())
2569 uuid_list
.append(sce_classifier_match_uuid
)
2570 db_sce_classifier_match
= {
2571 "uuid": sce_classifier_match_uuid
,
2572 "ip_proto": get_str(match
, "ip-proto", 2),
2573 "source_ip": get_str(match
, "source-ip-address", 16),
2574 "destination_ip": get_str(match
, "destination-ip-address", 16),
2575 "source_port": get_str(match
, "source-port", 5),
2576 "destination_port": get_str(match
, "destination-port", 5),
2577 "sce_classifier_id": sce_classifier_uuid
,
2579 db_sce_classifier_matches
.append(db_sce_classifier_match
)
2582 # remove unneeded id's in sce_rsps
2583 for rsp
in db_sce_rsps
:
2587 {"scenarios": db_scenarios
},
2588 {"sce_nets": db_sce_nets
},
2589 {"ip_profiles": db_ip_profiles
},
2590 {"sce_vnfs": db_sce_vnfs
},
2591 {"sce_interfaces": db_sce_interfaces
},
2592 {"sce_vnffgs": db_sce_vnffgs
},
2593 {"sce_rsps": db_sce_rsps
},
2594 {"sce_rsp_hops": db_sce_rsp_hops
},
2595 {"sce_classifiers": db_sce_classifiers
},
2596 {"sce_classifier_matches": db_sce_classifier_matches
},
2599 logger
.debug("new_nsd_v3 done: %s",
2600 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
2601 mydb
.new_rows(db_tables
, uuid_list
)
2602 return nsd_uuid_list
2603 except NfvoException
:
2605 except Exception as e
:
2606 logger
.error("Exception {}".format(e
))
2607 raise # NfvoException("Exception {}".format(e), httperrors.Bad_Request)
2610 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
2611 data
["uuid"] = scenario_id
2612 data
["tenant_id"] = tenant_id
2613 c
= mydb
.edit_scenario( data
)
2617 @deprecated("Use create_instance")
2618 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
2619 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2620 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
2621 vims
= {datacenter_id
: myvim
}
2622 myvim_tenant
= myvim
['tenant_id']
2623 datacenter_name
= myvim
['name']
2627 #print "Checking that the scenario_id exists and getting the scenario dictionary"
2628 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
=datacenter_id
)
2629 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
2630 scenarioDict
['datacenter_id'] = datacenter_id
2631 #print '================scenarioDict======================='
2632 #print json.dumps(scenarioDict, indent=4)
2633 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
2635 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
2636 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2638 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
2639 auxNetDict
['scenario'] = {}
2641 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
2642 for sce_net
in scenarioDict
['nets']:
2643 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
2645 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
2646 myNetName
= myNetName
[0:255] #limit length
2647 myNetType
= sce_net
['type']
2649 myNetDict
["name"] = myNetName
2650 myNetDict
["type"] = myNetType
2651 myNetDict
["tenant_id"] = myvim_tenant
2652 myNetIPProfile
= sce_net
.get('ip_profile', None)
2654 #We should use the dictionary as input parameter for new_network
2656 if not sce_net
["external"]:
2657 network_id
, _
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2658 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
2659 sce_net
['vim_id'] = network_id
2660 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
2661 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2662 sce_net
["created"] = True
2664 if sce_net
['vim_id'] == None:
2665 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
2666 _
, message
= rollback(mydb
, vims
, rollbackList
)
2667 logger
.error("nfvo.start_scenario: %s", error_text
)
2668 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2669 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
2670 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
2672 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
2673 #For each vnf net, we create it and we add it to instanceNetlist.
2675 for sce_vnf
in scenarioDict
['vnfs']:
2676 for net
in sce_vnf
['nets']:
2677 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
2679 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
2680 myNetName
= myNetName
[0:255] #limit length
2681 myNetType
= net
['type']
2683 myNetDict
["name"] = myNetName
2684 myNetDict
["type"] = myNetType
2685 myNetDict
["tenant_id"] = myvim_tenant
2686 myNetIPProfile
= net
.get('ip_profile', None)
2689 #We should use the dictionary as input parameter for new_network
2690 network_id
, _
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2691 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
2692 net
['vim_id'] = network_id
2693 if sce_vnf
['uuid'] not in auxNetDict
:
2694 auxNetDict
[sce_vnf
['uuid']] = {}
2695 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
2696 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2697 net
["created"] = True
2699 #print "auxNetDict:"
2700 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2702 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
2703 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2705 for sce_vnf
in scenarioDict
['vnfs']:
2706 vnf_availability_zones
= []
2707 for vm
in sce_vnf
['vms']:
2708 vm_av
= vm
.get('availability_zone')
2709 if vm_av
and vm_av
not in vnf_availability_zones
:
2710 vnf_availability_zones
.append(vm_av
)
2712 # check if there is enough availability zones available at vim level.
2713 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
2714 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
2715 raise NfvoException('No enough availability zones at VIM for this deployment', httperrors
.Bad_Request
)
2717 for vm
in sce_vnf
['vms']:
2720 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
2721 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
2722 #myVMDict['description'] = vm['description']
2723 myVMDict
['description'] = myVMDict
['name'][0:99]
2725 myVMDict
['start'] = "no"
2726 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2727 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
2729 #create image at vim in case it not exist
2730 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2731 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
2732 vm
['vim_image_id'] = image_id
2734 #create flavor at vim in case it not exist
2735 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2736 if flavor_dict
['extended']!=None:
2737 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2738 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
2739 vm
['vim_flavor_id'] = flavor_id
2742 myVMDict
['imageRef'] = vm
['vim_image_id']
2743 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2744 myVMDict
['networks'] = []
2745 for iface
in vm
['interfaces']:
2747 if iface
['type']=="data":
2748 netDict
['type'] = iface
['model']
2749 elif "model" in iface
and iface
["model"]!=None:
2750 netDict
['model']=iface
['model']
2751 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2752 #discover type of interface looking at flavor
2753 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2754 for flavor_iface
in numa
.get('interfaces',[]):
2755 if flavor_iface
.get('name') == iface
['internal_name']:
2756 if flavor_iface
['dedicated'] == 'yes':
2757 netDict
['type']="PF" #passthrough
2758 elif flavor_iface
['dedicated'] == 'no':
2759 netDict
['type']="VF" #siov
2760 elif flavor_iface
['dedicated'] == 'yes:sriov':
2761 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2762 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2764 netDict
["use"]=iface
['type']
2765 if netDict
["use"]=="data" and not netDict
.get("type"):
2766 #print "netDict", netDict
2767 #print "iface", iface
2768 e_text
= "Cannot determine the interface type PF or VF of VNF '%s' VM '%s' iface '%s'" %(sce_vnf
['name'], vm
['name'], iface
['internal_name'])
2769 if flavor_dict
.get('extended')==None:
2770 raise NfvoException(e_text
+ "After database migration some information is not available. \
2771 Try to delete and create the scenarios and VNFs again", httperrors
.Conflict
)
2773 raise NfvoException(e_text
, httperrors
.Internal_Server_Error
)
2774 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2775 netDict
["type"]="virtual"
2776 if "vpci" in iface
and iface
["vpci"] is not None:
2777 netDict
['vpci'] = iface
['vpci']
2778 if "mac" in iface
and iface
["mac"] is not None:
2779 netDict
['mac_address'] = iface
['mac']
2780 if "port-security" in iface
and iface
["port-security"] is not None:
2781 netDict
['port_security'] = iface
['port-security']
2782 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2783 netDict
['floating_ip'] = iface
['floating-ip']
2784 netDict
['name'] = iface
['internal_name']
2785 if iface
['net_id'] is None:
2786 for vnf_iface
in sce_vnf
["interfaces"]:
2789 if vnf_iface
['interface_id']==iface
['uuid']:
2790 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
2793 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2794 #skip bridge ifaces not connected to any net
2795 #if 'net_id' not in netDict or netDict['net_id']==None:
2797 myVMDict
['networks'].append(netDict
)
2798 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2799 #print myVMDict['name']
2800 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2801 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2802 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2804 if 'availability_zone' in myVMDict
:
2805 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
2809 vm_id
, _
= myvim
.new_vminstance(myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2810 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2811 availability_zone_index
=av_index
,
2812 availability_zone_list
=vnf_availability_zones
)
2813 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
2814 vm
['vim_id'] = vm_id
2815 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2816 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2817 for net
in myVMDict
['networks']:
2819 for iface
in vm
['interfaces']:
2820 if net
["name"]==iface
["internal_name"]:
2821 iface
["vim_id"]=net
["vim_id"]
2824 logger
.debug("start scenario Deployment done")
2825 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2826 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
2827 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
2828 return mydb
.get_instance_scenario(instance_id
)
2830 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
2831 _
, message
= rollback(mydb
, vims
, rollbackList
)
2832 if isinstance(e
, db_base_Exception
):
2833 error_text
= "Exception at database"
2835 error_text
= "Exception at VIM"
2836 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2837 #logger.error("start_scenario %s", error_text)
2838 raise NfvoException(error_text
, e
.http_code
)
2840 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
2841 """ join the cloud config information into cloud_config_preserve.
2842 In case of conflict cloud_config_preserve preserves
2845 if not cloud_config_preserve
and not cloud_config
:
2848 new_cloud_config
= {"key-pairs":[], "users":[]}
2850 if cloud_config_preserve
:
2851 for key
in cloud_config_preserve
.get("key-pairs", () ):
2852 if key
not in new_cloud_config
["key-pairs"]:
2853 new_cloud_config
["key-pairs"].append(key
)
2855 for key
in cloud_config
.get("key-pairs", () ):
2856 if key
not in new_cloud_config
["key-pairs"]:
2857 new_cloud_config
["key-pairs"].append(key
)
2858 if not new_cloud_config
["key-pairs"]:
2859 del new_cloud_config
["key-pairs"]
2863 new_cloud_config
["users"] += cloud_config
.get("users", () )
2864 if cloud_config_preserve
:
2865 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
2866 index_to_delete
= []
2867 users
= new_cloud_config
.get("users", [])
2868 for index0
in range(0,len(users
)):
2869 if index0
in index_to_delete
:
2871 for index1
in range(index0
+1,len(users
)):
2872 if index1
in index_to_delete
:
2874 if users
[index0
]["name"] == users
[index1
]["name"]:
2875 index_to_delete
.append(index1
)
2876 for key
in users
[index1
].get("key-pairs",()):
2877 if "key-pairs" not in users
[index0
]:
2878 users
[index0
]["key-pairs"] = [key
]
2879 elif key
not in users
[index0
]["key-pairs"]:
2880 users
[index0
]["key-pairs"].append(key
)
2881 index_to_delete
.sort(reverse
=True)
2882 for index
in index_to_delete
:
2884 if not new_cloud_config
["users"]:
2885 del new_cloud_config
["users"]
2888 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
2889 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
2890 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
2891 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
2894 new_cloud_config
["user-data"] = []
2895 if cloud_config
and cloud_config
.get("user-data"):
2896 if isinstance(cloud_config
["user-data"], list):
2897 new_cloud_config
["user-data"] += cloud_config
["user-data"]
2899 new_cloud_config
["user-data"].append(cloud_config
["user-data"])
2900 if cloud_config_preserve
and cloud_config_preserve
.get("user-data"):
2901 if isinstance(cloud_config_preserve
["user-data"], list):
2902 new_cloud_config
["user-data"] += cloud_config_preserve
["user-data"]
2904 new_cloud_config
["user-data"].append(cloud_config_preserve
["user-data"])
2905 if not new_cloud_config
["user-data"]:
2906 del new_cloud_config
["user-data"]
2909 new_cloud_config
["config-files"] = []
2910 if cloud_config
and cloud_config
.get("config-files") != None:
2911 new_cloud_config
["config-files"] += cloud_config
["config-files"]
2912 if cloud_config_preserve
:
2913 for file in cloud_config_preserve
.get("config-files", ()):
2914 for index
in range(0, len(new_cloud_config
["config-files"])):
2915 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
2916 new_cloud_config
["config-files"][index
] = file
2919 new_cloud_config
["config-files"].append(file)
2920 if not new_cloud_config
["config-files"]:
2921 del new_cloud_config
["config-files"]
2922 return new_cloud_config
2925 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
2926 datacenter_id
= None
2927 datacenter_name
= None
2930 if datacenter_tenant_id
:
2931 thread_id
= datacenter_tenant_id
2932 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
2934 where_
={"td.nfvo_tenant_id": tenant_id
}
2935 if datacenter_id_name
:
2936 if utils
.check_valid_uuid(datacenter_id_name
):
2937 datacenter_id
= datacenter_id_name
2938 where_
["dt.datacenter_id"] = datacenter_id
2940 datacenter_name
= datacenter_id_name
2941 where_
["d.name"] = datacenter_name
2942 if datacenter_tenant_id
:
2943 where_
["dt.uuid"] = datacenter_tenant_id
2944 datacenters
= mydb
.get_rows(
2945 SELECT
=("dt.uuid as datacenter_tenant_id",),
2946 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
2947 "join datacenters as d on d.uuid=dt.datacenter_id",
2949 if len(datacenters
) > 1:
2950 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
2952 thread_id
= datacenters
[0]["datacenter_tenant_id"]
2953 thread
= vim_threads
["running"].get(thread_id
)
2955 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
2956 return thread_id
, thread
2957 except db_base_Exception
as e
:
2958 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
2961 def get_datacenter_uuid(mydb
, tenant_id
, datacenter_id_name
):
2963 if utils
.check_valid_uuid(datacenter_id_name
):
2964 WHERE_dict
['d.uuid'] = datacenter_id_name
2966 WHERE_dict
['d.name'] = datacenter_id_name
2969 WHERE_dict
['nfvo_tenant_id'] = tenant_id
2970 from_
= "tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join datacenter_tenants as" \
2971 " dt on td.datacenter_tenant_id=dt.uuid"
2973 from_
= 'datacenters as d'
2974 vimaccounts
= mydb
.get_rows(FROM
=from_
, SELECT
=("d.uuid as uuid, d.name as name",), WHERE
=WHERE_dict
)
2975 if len(vimaccounts
) == 0:
2976 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
2977 elif len(vimaccounts
)>1:
2978 #print "nfvo.datacenter_action() error. Several datacenters found"
2979 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
2980 return vimaccounts
[0]["uuid"], vimaccounts
[0]["name"]
2983 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
2984 datacenter_id
= None
2985 datacenter_name
= None
2986 if datacenter_id_name
:
2987 if utils
.check_valid_uuid(datacenter_id_name
):
2988 datacenter_id
= datacenter_id_name
2990 datacenter_name
= datacenter_id_name
2991 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
2993 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
2995 #print "nfvo.datacenter_action() error. Several datacenters found"
2996 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
2997 return vims
.keys()[0], vims
.values()[0]
3001 """Takes dict d and updates it with the values in dict u.
3002 It merges all depth levels"""
3003 for k
, v
in u
.iteritems():
3004 if isinstance(v
, collections
.Mapping
):
3005 r
= update(d
.get(k
, {}), v
)
3012 def create_instance(mydb
, tenant_id
, instance_dict
):
3013 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
3014 # logger.debug("Creating instance...")
3015 scenario
= instance_dict
["scenario"]
3017 # find main datacenter
3019 myvim_threads_id
= {}
3020 datacenter
= instance_dict
.get("datacenter")
3021 default_wim_account
= instance_dict
.get("wim_account")
3022 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3023 myvims
[default_datacenter_id
] = vim
3024 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
3025 tenant
= mydb
.get_rows_by_id('nfvo_tenants', tenant_id
)
3026 # myvim_tenant = myvim['tenant_id']
3029 # print "Checking that the scenario exists and getting the scenario dictionary"
3030 if isinstance(scenario
, str):
3031 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, datacenter_vim_id
=myvim_threads_id
[default_datacenter_id
],
3032 datacenter_id
=default_datacenter_id
)
3034 scenarioDict
= scenario
3035 scenarioDict
["uuid"] = None
3037 # logger.debug(">>>>>> Dictionaries before merging")
3038 # logger.debug(">>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
3039 # logger.debug(">>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
3041 db_instance_vnfs
= []
3042 db_instance_vms
= []
3043 db_instance_interfaces
= []
3044 db_instance_sfis
= []
3045 db_instance_sfs
= []
3046 db_instance_classifications
= []
3047 db_instance_sfps
= []
3052 instance_name
= instance_dict
["name"]
3053 instance_uuid
= str(uuid4())
3054 uuid_list
.append(instance_uuid
)
3055 db_instance_scenario
= {
3056 "uuid": instance_uuid
,
3057 "name": instance_name
,
3058 "tenant_id": tenant_id
,
3059 "scenario_id": scenarioDict
['uuid'],
3060 "datacenter_id": default_datacenter_id
,
3061 # filled bellow 'datacenter_tenant_id'
3062 "description": instance_dict
.get("description"),
3064 if scenarioDict
.get("cloud-config"):
3065 db_instance_scenario
["cloud_config"] = yaml
.safe_dump(scenarioDict
["cloud-config"],
3066 default_flow_style
=True, width
=256)
3067 instance_action_id
= get_task_id()
3068 db_instance_action
= {
3069 "uuid": instance_action_id
, # same uuid for the instance and the action on create
3070 "tenant_id": tenant_id
,
3071 "instance_id": instance_uuid
,
3072 "description": "CREATE",
3075 # Auxiliary dictionaries from x to y
3076 sce_net2instance
= {}
3077 net2task_id
= {'scenario': {}}
3078 # Mapping between local networks and WIMs
3081 def ip_profile_IM2RO(ip_profile_im
):
3082 # translate from input format to database format
3084 if 'subnet-address' in ip_profile_im
:
3085 ip_profile_ro
['subnet_address'] = ip_profile_im
['subnet-address']
3086 if 'ip-version' in ip_profile_im
:
3087 ip_profile_ro
['ip_version'] = ip_profile_im
['ip-version']
3088 if 'gateway-address' in ip_profile_im
:
3089 ip_profile_ro
['gateway_address'] = ip_profile_im
['gateway-address']
3090 if 'dns-address' in ip_profile_im
:
3091 ip_profile_ro
['dns_address'] = ip_profile_im
['dns-address']
3092 if isinstance(ip_profile_ro
['dns_address'], (list, tuple)):
3093 ip_profile_ro
['dns_address'] = ";".join(ip_profile_ro
['dns_address'])
3094 if 'dhcp' in ip_profile_im
:
3095 ip_profile_ro
['dhcp_start_address'] = ip_profile_im
['dhcp'].get('start-address')
3096 ip_profile_ro
['dhcp_enabled'] = ip_profile_im
['dhcp'].get('enabled', True)
3097 ip_profile_ro
['dhcp_count'] = ip_profile_im
['dhcp'].get('count')
3098 return ip_profile_ro
3100 # logger.debug("Creating instance from scenario-dict:\n%s",
3101 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
3103 # 0 check correct parameters
3104 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).iteritems():
3105 for scenario_net
in scenarioDict
['nets']:
3106 if net_name
== scenario_net
.get("name") or net_name
== scenario_net
.get("osm_id") or net_name
== scenario_net
.get("uuid"):
3109 raise NfvoException("Invalid scenario network name or id '{}' at instance:networks".format(net_name
),
3110 httperrors
.Bad_Request
)
3111 if "sites" not in net_instance_desc
:
3112 net_instance_desc
["sites"] = [ {} ]
3113 site_without_datacenter_field
= False
3114 for site
in net_instance_desc
["sites"]:
3115 if site
.get("datacenter"):
3116 site
["datacenter"], _
= get_datacenter_uuid(mydb
, tenant_id
, site
["datacenter"])
3117 if site
["datacenter"] not in myvims
:
3118 # Add this datacenter to myvims
3119 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
3121 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
3122 site
["datacenter"] = d
# change name to id
3124 if site_without_datacenter_field
:
3125 raise NfvoException("Found more than one entries without datacenter field at "
3126 "instance:networks:{}:sites".format(net_name
), httperrors
.Bad_Request
)
3127 site_without_datacenter_field
= True
3128 site
["datacenter"] = default_datacenter_id
# change name to id
3130 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
3131 for scenario_vnf
in scenarioDict
['vnfs']:
3132 if vnf_name
== scenario_vnf
['member_vnf_index'] or vnf_name
== scenario_vnf
['uuid'] or vnf_name
== scenario_vnf
['name']:
3135 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_name
), httperrors
.Bad_Request
)
3136 if "datacenter" in vnf_instance_desc
:
3137 # Add this datacenter to myvims
3138 vnf_instance_desc
["datacenter"], _
= get_datacenter_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3139 if vnf_instance_desc
["datacenter"] not in myvims
:
3140 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3142 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3143 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
3145 for net_id
, net_instance_desc
in vnf_instance_desc
.get("networks", {}).iteritems():
3146 for scenario_net
in scenario_vnf
['nets']:
3147 if net_id
== scenario_net
['osm_id'] or net_id
== scenario_net
['uuid'] or net_id
== scenario_net
["name"]:
3150 raise NfvoException("Invalid net id or name '{}' at instance:vnfs:networks".format(net_id
), httperrors
.Bad_Request
)
3151 if net_instance_desc
.get("vim-network-name"):
3152 scenario_net
["vim-network-name"] = net_instance_desc
["vim-network-name"]
3153 if net_instance_desc
.get("vim-network-id"):
3154 scenario_net
["vim-network-id"] = net_instance_desc
["vim-network-id"]
3155 if net_instance_desc
.get("name"):
3156 scenario_net
["name"] = net_instance_desc
["name"]
3157 if 'ip-profile' in net_instance_desc
:
3158 ipprofile_db
= ip_profile_IM2RO(net_instance_desc
['ip-profile'])
3159 if 'ip_profile' not in scenario_net
:
3160 scenario_net
['ip_profile'] = ipprofile_db
3162 update(scenario_net
['ip_profile'], ipprofile_db
)
3164 for vdu_id
, vdu_instance_desc
in vnf_instance_desc
.get("vdus", {}).iteritems():
3165 for scenario_vm
in scenario_vnf
['vms']:
3166 if vdu_id
== scenario_vm
['osm_id'] or vdu_id
== scenario_vm
["name"]:
3169 raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id
), httperrors
.Bad_Request
)
3170 scenario_vm
["instance_parameters"] = vdu_instance_desc
3171 for iface_id
, iface_instance_desc
in vdu_instance_desc
.get("interfaces", {}).iteritems():
3172 for scenario_interface
in scenario_vm
['interfaces']:
3173 if iface_id
== scenario_interface
['internal_name'] or iface_id
== scenario_interface
["external_name"]:
3174 scenario_interface
.update(iface_instance_desc
)
3177 raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id
), httperrors
.Bad_Request
)
3179 # 0.1 parse cloud-config parameters
3180 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
3182 # 0.2 merge instance information into scenario
3183 # Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
3184 # However, this is not possible yet.
3185 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).iteritems():
3186 for scenario_net
in scenarioDict
['nets']:
3187 if net_name
== scenario_net
.get("name") or net_name
== scenario_net
.get("osm_id") or net_name
== scenario_net
.get("uuid"):
3188 if "wim_account" in net_instance_desc
and net_instance_desc
["wim_account"] is not None:
3189 scenario_net
["wim_account"] = net_instance_desc
["wim_account"]
3190 if 'ip-profile' in net_instance_desc
:
3191 ipprofile_db
= ip_profile_IM2RO(net_instance_desc
['ip-profile'])
3192 if 'ip_profile' not in scenario_net
:
3193 scenario_net
['ip_profile'] = ipprofile_db
3195 update(scenario_net
['ip_profile'], ipprofile_db
)
3196 for interface
in net_instance_desc
.get('interfaces', ()):
3197 if 'ip_address' in interface
:
3198 for vnf
in scenarioDict
['vnfs']:
3199 if interface
['vnf'] == vnf
['name']:
3200 for vnf_interface
in vnf
['interfaces']:
3201 if interface
['vnf_interface'] == vnf_interface
['external_name']:
3202 vnf_interface
['ip_address'] = interface
['ip_address']
3204 # logger.debug(">>>>>>>> Merged dictionary")
3205 # logger.debug("Creating instance scenario-dict MERGED:\n%s",
3206 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
3208 # 1. Creating new nets (sce_nets) in the VIM"
3209 number_mgmt_networks
= 0
3210 db_instance_nets
= []
3211 for sce_net
in scenarioDict
['nets']:
3212 sce_net_uuid
= sce_net
.get('uuid', sce_net
["name"])
3213 # get involved datacenters where this network need to be created
3214 involved_datacenters
= []
3215 for sce_vnf
in scenarioDict
.get("vnfs", ()):
3216 vnf_datacenter
= sce_vnf
.get("datacenter", default_datacenter_id
)
3217 if vnf_datacenter
in involved_datacenters
:
3219 if sce_vnf
.get("interfaces"):
3220 for sce_vnf_ifaces
in sce_vnf
["interfaces"]:
3221 if sce_vnf_ifaces
.get("sce_net_id") == sce_net
["uuid"]:
3222 involved_datacenters
.append(vnf_datacenter
)
3224 if not involved_datacenters
:
3225 involved_datacenters
.append(default_datacenter_id
)
3226 target_wim_account
= sce_net
.get("wim_account", default_wim_account
)
3229 # TODO: use this information during network creation
3230 wim_account_id
= wim_account_name
= None
3231 if len(involved_datacenters
) > 1 and 'uuid' in sce_net
:
3232 if target_wim_account
is None or target_wim_account
is True: # automatic selection of WIM
3233 # OBS: sce_net without uuid are used internally to VNFs
3234 # and the assumption is that VNFs will not be split among
3235 # different datacenters
3236 wim_account
= wim_engine
.find_suitable_wim_account(
3237 involved_datacenters
, tenant_id
)
3238 wim_account_id
= wim_account
['uuid']
3239 wim_account_name
= wim_account
['name']
3240 wim_usage
[sce_net
['uuid']] = wim_account_id
3241 elif isinstance(target_wim_account
, str): # manual selection of WIM
3242 wim_account
.persist
.get_wim_account_by(target_wim_account
, tenant_id
)
3243 wim_account_id
= wim_account
['uuid']
3244 wim_account_name
= wim_account
['name']
3245 wim_usage
[sce_net
['uuid']] = wim_account_id
3246 else: # not WIM usage
3247 wim_usage
[sce_net
['uuid']] = False
3251 if instance_dict
.get("networks") and instance_dict
["networks"].get(sce_net
["name"]):
3252 descriptor_net
= instance_dict
["networks"][sce_net
["name"]]
3253 net_name
= descriptor_net
.get("vim-network-name")
3254 # add datacenters from instantiation parameters
3255 if descriptor_net
.get("sites"):
3256 for site
in descriptor_net
["sites"]:
3257 if site
.get("datacenter") and site
["datacenter"] not in involved_datacenters
:
3258 involved_datacenters
.append(site
["datacenter"])
3259 sce_net2instance
[sce_net_uuid
] = {}
3260 net2task_id
['scenario'][sce_net_uuid
] = {}
3262 if sce_net
["external"]:
3263 number_mgmt_networks
+= 1
3265 for datacenter_id
in involved_datacenters
:
3267 netmap_create
= None
3268 if descriptor_net
.get("sites"):
3269 for site
in descriptor_net
["sites"]:
3270 if site
.get("datacenter") == datacenter_id
:
3271 netmap_use
= site
.get("netmap-use")
3272 netmap_create
= site
.get("netmap-create")
3275 vim
= myvims
[datacenter_id
]
3276 myvim_thread_id
= myvim_threads_id
[datacenter_id
]
3278 net_type
= sce_net
['type']
3280 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} # 'shared': True
3283 if sce_net
["external"]:
3284 net_name
= sce_net
["name"]
3286 net_name
= "{}-{}".format(instance_name
, sce_net
["name"])
3287 net_name
= net_name
[:255] # limit length
3289 if netmap_use
or netmap_create
:
3290 create_network
= False
3291 lookfor_network
= False
3293 lookfor_network
= True
3294 if utils
.check_valid_uuid(netmap_use
):
3295 lookfor_filter
["id"] = netmap_use
3297 lookfor_filter
["name"] = netmap_use
3299 create_network
= True
3300 net_vim_name
= net_name
3301 if isinstance(netmap_create
, str):
3302 net_vim_name
= netmap_create
3303 elif sce_net
.get("vim_network_name"):
3304 create_network
= False
3305 lookfor_network
= True
3306 lookfor_filter
["name"] = sce_net
.get("vim_network_name")
3307 elif sce_net
["external"]:
3308 if sce_net
.get('vim_id'):
3309 # there is a netmap at datacenter_nets database # TODO REVISE!!!!
3310 create_network
= False
3311 lookfor_network
= True
3312 lookfor_filter
["id"] = sce_net
['vim_id']
3313 elif vim
["config"].get("management_network_id") or vim
["config"].get("management_network_name"):
3314 if number_mgmt_networks
> 1:
3315 raise NfvoException("Found several VLD of type mgmt. "
3316 "You must concrete what vim-network must be use for each one",
3317 httperrors
.Bad_Request
)
3318 create_network
= False
3319 lookfor_network
= True
3320 if vim
["config"].get("management_network_id"):
3321 lookfor_filter
["id"] = vim
["config"]["management_network_id"]
3323 lookfor_filter
["name"] = vim
["config"]["management_network_name"]
3325 # There is not a netmap, look at datacenter for a net with this name and create if not found
3326 create_network
= True
3327 lookfor_network
= True
3328 lookfor_filter
["name"] = sce_net
["name"]
3329 net_vim_name
= sce_net
["name"]
3331 net_vim_name
= net_name
3332 create_network
= True
3333 lookfor_network
= False
3337 task_action
= "CREATE"
3338 task_extra
["params"] = (net_vim_name
, net_type
, sce_net
.get('ip_profile', None), wim_account_name
)
3340 task_extra
["find"] = (lookfor_filter
,)
3341 elif lookfor_network
:
3342 task_action
= "FIND"
3343 task_extra
["params"] = (lookfor_filter
,)
3345 # fill database content
3346 net_uuid
= str(uuid4())
3347 uuid_list
.append(net_uuid
)
3348 sce_net2instance
[sce_net_uuid
][datacenter_id
] = net_uuid
3352 "vim_name": net_vim_name
,
3353 "instance_scenario_id": instance_uuid
,
3354 "sce_net_id": sce_net
.get("uuid"),
3355 "created": create_network
,
3356 'datacenter_id': datacenter_id
,
3357 'datacenter_tenant_id': myvim_thread_id
,
3358 'status': 'BUILD' # if create_network else "ACTIVE"
3360 db_instance_nets
.append(db_net
)
3362 "instance_action_id": instance_action_id
,
3363 "status": "SCHEDULED",
3364 "task_index": task_index
,
3365 "datacenter_vim_id": myvim_thread_id
,
3366 "action": task_action
,
3367 "item": "instance_nets",
3368 "item_id": net_uuid
,
3369 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
3371 net2task_id
['scenario'][sce_net_uuid
][datacenter_id
] = task_index
3373 db_vim_actions
.append(db_vim_action
)
3375 if 'ip_profile' in sce_net
:
3377 'instance_net_id': net_uuid
,
3378 'ip_version': sce_net
['ip_profile']['ip_version'],
3379 'subnet_address': sce_net
['ip_profile']['subnet_address'],
3380 'gateway_address': sce_net
['ip_profile']['gateway_address'],
3381 'dns_address': sce_net
['ip_profile']['dns_address'],
3382 'dhcp_enabled': sce_net
['ip_profile']['dhcp_enabled'],
3383 'dhcp_start_address': sce_net
['ip_profile']['dhcp_start_address'],
3384 'dhcp_count': sce_net
['ip_profile']['dhcp_count'],
3386 db_ip_profiles
.append(db_ip_profile
)
3390 "default_datacenter_id": default_datacenter_id
,
3391 "myvim_threads_id": myvim_threads_id
,
3392 "instance_uuid": instance_uuid
,
3393 "instance_name": instance_name
,
3394 "instance_action_id": instance_action_id
,
3396 "cloud_config": cloud_config
,
3397 "RO_pub_key": tenant
[0].get('RO_pub_key'),
3398 "instance_parameters": instance_dict
,
3401 "task_index": task_index
,
3402 "uuid_list": uuid_list
,
3403 "db_instance_nets": db_instance_nets
,
3404 "db_vim_actions": db_vim_actions
,
3405 "db_ip_profiles": db_ip_profiles
,
3406 "db_instance_vnfs": db_instance_vnfs
,
3407 "db_instance_vms": db_instance_vms
,
3408 "db_instance_interfaces": db_instance_interfaces
,
3409 "net2task_id": net2task_id
,
3410 "sce_net2instance": sce_net2instance
,
3412 # sce_vnf_list = sorted(scenarioDict['vnfs'], key=lambda k: k['name'])
3413 for sce_vnf
in scenarioDict
.get('vnfs', ()): # sce_vnf_list:
3414 instantiate_vnf(mydb
, sce_vnf
, vnf_params
, vnf_params_out
, rollbackList
)
3415 task_index
= vnf_params_out
["task_index"]
3416 uuid_list
= vnf_params_out
["uuid_list"]
3419 # task_depends_on = []
3420 for vnffg
in scenarioDict
.get('vnffgs', ()):
3421 for rsp
in vnffg
['rsps']:
3423 for cp
in rsp
['connection_points']:
3424 count
= mydb
.get_rows(
3426 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_rsp_hops as h "
3427 "on interfaces.uuid=h.ingress_interface_id",
3428 WHERE
={'h.uuid': cp
['uuid']})[0]['count']
3429 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == cp
['sce_vnf_id']), None)
3430 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3432 for instance_vm
in instance_vms
:
3433 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3435 dependencies
.append(action
['task_index'])
3436 # TODO: throw exception if count != len(instance_vms)
3437 # TODO: and action shouldn't ever be None
3439 for i
in range(count
):
3441 sfi_uuid
= str(uuid4())
3443 "ingress_interface_id": cp
["ingress_interface_id"],
3444 "egress_interface_id": cp
["egress_interface_id"]
3446 uuid_list
.append(sfi_uuid
)
3449 "instance_scenario_id": instance_uuid
,
3450 'sce_rsp_hop_id': cp
['uuid'],
3451 'datacenter_id': datacenter_id
,
3452 'datacenter_tenant_id': myvim_thread_id
,
3453 "vim_sfi_id": None, # vim thread will populate
3455 db_instance_sfis
.append(db_sfi
)
3457 "instance_action_id": instance_action_id
,
3458 "task_index": task_index
,
3459 "datacenter_vim_id": myvim_thread_id
,
3461 "status": "SCHEDULED",
3462 "item": "instance_sfis",
3463 "item_id": sfi_uuid
,
3464 "extra": yaml
.safe_dump({"params": extra_params
, "depends_on": [dependencies
[i
]]},
3465 default_flow_style
=True, width
=256)
3467 sfis_created
.append(task_index
)
3469 db_vim_actions
.append(db_vim_action
)
3471 sf_uuid
= str(uuid4())
3472 uuid_list
.append(sf_uuid
)
3475 "instance_scenario_id": instance_uuid
,
3476 'sce_rsp_hop_id': cp
['uuid'],
3477 'datacenter_id': datacenter_id
,
3478 'datacenter_tenant_id': myvim_thread_id
,
3479 "vim_sf_id": None, # vim thread will populate
3481 db_instance_sfs
.append(db_sf
)
3483 "instance_action_id": instance_action_id
,
3484 "task_index": task_index
,
3485 "datacenter_vim_id": myvim_thread_id
,
3487 "status": "SCHEDULED",
3488 "item": "instance_sfs",
3490 "extra": yaml
.safe_dump({"params": "", "depends_on": sfis_created
},
3491 default_flow_style
=True, width
=256)
3493 sfs_created
.append(task_index
)
3495 db_vim_actions
.append(db_vim_action
)
3496 classifier
= rsp
['classifier']
3498 # TODO the following ~13 lines can be reused for the sfi case
3499 count
= mydb
.get_rows(
3500 SELECT
=('vms.count'),
3501 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_classifiers as c on interfaces.uuid=c.interface_id",
3502 WHERE
={'c.uuid': classifier
['uuid']})[0]['count']
3503 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == classifier
['sce_vnf_id']), None)
3504 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3506 for instance_vm
in instance_vms
:
3507 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3509 dependencies
.append(action
['task_index'])
3510 # TODO: throw exception if count != len(instance_vms)
3511 # TODO: and action shouldn't ever be None
3512 classifications_created
= []
3513 for i
in range(count
):
3514 for match
in classifier
['matches']:
3515 # create classifications
3516 classification_uuid
= str(uuid4())
3517 uuid_list
.append(classification_uuid
)
3518 db_classification
= {
3519 "uuid": classification_uuid
,
3520 "instance_scenario_id": instance_uuid
,
3521 'sce_classifier_match_id': match
['uuid'],
3522 'datacenter_id': datacenter_id
,
3523 'datacenter_tenant_id': myvim_thread_id
,
3524 "vim_classification_id": None, # vim thread will populate
3526 db_instance_classifications
.append(db_classification
)
3527 classification_params
= {
3528 "ip_proto": match
["ip_proto"],
3529 "source_ip": match
["source_ip"],
3530 "destination_ip": match
["destination_ip"],
3531 "source_port": match
["source_port"],
3532 "destination_port": match
["destination_port"]
3535 "instance_action_id": instance_action_id
,
3536 "task_index": task_index
,
3537 "datacenter_vim_id": myvim_thread_id
,
3539 "status": "SCHEDULED",
3540 "item": "instance_classifications",
3541 "item_id": classification_uuid
,
3542 "extra": yaml
.safe_dump({"params": classification_params
, "depends_on": [dependencies
[i
]]},
3543 default_flow_style
=True, width
=256)
3545 classifications_created
.append(task_index
)
3547 db_vim_actions
.append(db_vim_action
)
3550 sfp_uuid
= str(uuid4())
3551 uuid_list
.append(sfp_uuid
)
3554 "instance_scenario_id": instance_uuid
,
3555 'sce_rsp_id': rsp
['uuid'],
3556 'datacenter_id': datacenter_id
,
3557 'datacenter_tenant_id': myvim_thread_id
,
3558 "vim_sfp_id": None, # vim thread will populate
3560 db_instance_sfps
.append(db_sfp
)
3562 "instance_action_id": instance_action_id
,
3563 "task_index": task_index
,
3564 "datacenter_vim_id": myvim_thread_id
,
3566 "status": "SCHEDULED",
3567 "item": "instance_sfps",
3568 "item_id": sfp_uuid
,
3569 "extra": yaml
.safe_dump({"params": "", "depends_on": sfs_created
+ classifications_created
},
3570 default_flow_style
=True, width
=256)
3573 db_vim_actions
.append(db_vim_action
)
3574 db_instance_action
["number_tasks"] = task_index
3577 logger
.debug('wim_usage:\n%s\n\n', pformat(wim_usage
))
3578 wan_links
= wim_engine
.derive_wan_links(wim_usage
, db_instance_nets
, tenant_id
)
3579 wim_actions
= wim_engine
.create_actions(wan_links
)
3580 wim_actions
, db_instance_action
= (
3581 wim_engine
.incorporate_actions(wim_actions
, db_instance_action
))
3584 scenarioDict
["datacenter2tenant"] = myvim_threads_id
3586 db_instance_scenario
['datacenter_tenant_id'] = myvim_threads_id
[default_datacenter_id
]
3587 db_instance_scenario
['datacenter_id'] = default_datacenter_id
3589 {"instance_scenarios": db_instance_scenario
},
3590 {"instance_vnfs": db_instance_vnfs
},
3591 {"instance_nets": db_instance_nets
},
3592 {"ip_profiles": db_ip_profiles
},
3593 {"instance_vms": db_instance_vms
},
3594 {"instance_interfaces": db_instance_interfaces
},
3595 {"instance_actions": db_instance_action
},
3596 {"instance_sfis": db_instance_sfis
},
3597 {"instance_sfs": db_instance_sfs
},
3598 {"instance_classifications": db_instance_classifications
},
3599 {"instance_sfps": db_instance_sfps
},
3600 {"instance_wim_nets": wan_links
},
3601 {"vim_wim_actions": db_vim_actions
+ wim_actions
}
3604 logger
.debug("create_instance done DB tables: %s",
3605 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
3606 mydb
.new_rows(db_tables
, uuid_list
)
3607 for myvim_thread_id
in myvim_threads_id
.values():
3608 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
3610 wim_engine
.dispatch(wim_actions
)
3612 returned_instance
= mydb
.get_instance_scenario(instance_uuid
)
3613 returned_instance
["action_id"] = instance_action_id
3614 return returned_instance
3615 except (NfvoException
, vimconn
.vimconnException
, wimconn
.WimConnectorError
, db_base_Exception
) as e
:
3616 message
= rollback(mydb
, myvims
, rollbackList
)
3617 if isinstance(e
, db_base_Exception
):
3618 error_text
= "database Exception"
3619 elif isinstance(e
, vimconn
.vimconnException
):
3620 error_text
= "VIM Exception"
3621 elif isinstance(e
, wimconn
.WimConnectorError
):
3622 error_text
= "WIM Exception"
3624 error_text
= "Exception"
3625 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
3626 # logger.error("create_instance: %s", error_text)
3628 raise NfvoException(error_text
, e
.http_code
)
3631 def instantiate_vnf(mydb
, sce_vnf
, params
, params_out
, rollbackList
):
3632 default_datacenter_id
= params
["default_datacenter_id"]
3633 myvim_threads_id
= params
["myvim_threads_id"]
3634 instance_uuid
= params
["instance_uuid"]
3635 instance_name
= params
["instance_name"]
3636 instance_action_id
= params
["instance_action_id"]
3637 myvims
= params
["myvims"]
3638 cloud_config
= params
["cloud_config"]
3639 RO_pub_key
= params
["RO_pub_key"]
3641 task_index
= params_out
["task_index"]
3642 uuid_list
= params_out
["uuid_list"]
3643 db_instance_nets
= params_out
["db_instance_nets"]
3644 db_vim_actions
= params_out
["db_vim_actions"]
3645 db_ip_profiles
= params_out
["db_ip_profiles"]
3646 db_instance_vnfs
= params_out
["db_instance_vnfs"]
3647 db_instance_vms
= params_out
["db_instance_vms"]
3648 db_instance_interfaces
= params_out
["db_instance_interfaces"]
3649 net2task_id
= params_out
["net2task_id"]
3650 sce_net2instance
= params_out
["sce_net2instance"]
3652 vnf_net2instance
= {}
3654 # 2. Creating new nets (vnf internal nets) in the VIM"
3655 # For each vnf net, we create it and we add it to instanceNetlist.
3656 if sce_vnf
.get("datacenter"):
3657 datacenter_id
= sce_vnf
["datacenter"]
3658 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
3660 datacenter_id
= default_datacenter_id
3661 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
3662 for net
in sce_vnf
['nets']:
3664 # descriptor_net = instance_dict.get("vnfs", {}).get(sce_vnf["name"], {})
3665 # net_name = descriptor_net.get("name")
3668 net_name
= "{}-{}".format(instance_name
, net
["name"])
3669 net_name
= net_name
[:255] # limit length
3670 net_type
= net
['type']
3672 if sce_vnf
['uuid'] not in vnf_net2instance
:
3673 vnf_net2instance
[sce_vnf
['uuid']] = {}
3674 if sce_vnf
['uuid'] not in net2task_id
:
3675 net2task_id
[sce_vnf
['uuid']] = {}
3676 net2task_id
[sce_vnf
['uuid']][net
['uuid']] = task_index
3678 # fill database content
3679 net_uuid
= str(uuid4())
3680 uuid_list
.append(net_uuid
)
3681 vnf_net2instance
[sce_vnf
['uuid']][net
['uuid']] = net_uuid
3685 "vim_name": net_name
,
3686 "instance_scenario_id": instance_uuid
,
3687 "net_id": net
["uuid"],
3689 'datacenter_id': datacenter_id
,
3690 'datacenter_tenant_id': myvim_thread_id
,
3692 db_instance_nets
.append(db_net
)
3695 if net
.get("vim-network-name"):
3696 lookfor_filter
["name"] = net
["vim-network-name"]
3697 if net
.get("vim-network-id"):
3698 lookfor_filter
["id"] = net
["vim-network-id"]
3700 task_action
= "FIND"
3701 task_extra
= {"params": (lookfor_filter
,)}
3703 task_action
= "CREATE"
3704 task_extra
= {"params": (net_name
, net_type
, net
.get('ip_profile', None))}
3707 "instance_action_id": instance_action_id
,
3708 "task_index": task_index
,
3709 "datacenter_vim_id": myvim_thread_id
,
3710 "status": "SCHEDULED",
3711 "action": task_action
,
3712 "item": "instance_nets",
3713 "item_id": net_uuid
,
3714 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
3717 db_vim_actions
.append(db_vim_action
)
3719 if 'ip_profile' in net
:
3721 'instance_net_id': net_uuid
,
3722 'ip_version': net
['ip_profile']['ip_version'],
3723 'subnet_address': net
['ip_profile']['subnet_address'],
3724 'gateway_address': net
['ip_profile']['gateway_address'],
3725 'dns_address': net
['ip_profile']['dns_address'],
3726 'dhcp_enabled': net
['ip_profile']['dhcp_enabled'],
3727 'dhcp_start_address': net
['ip_profile']['dhcp_start_address'],
3728 'dhcp_count': net
['ip_profile']['dhcp_count'],
3730 db_ip_profiles
.append(db_ip_profile
)
3732 # print "vnf_net2instance:"
3733 # print yaml.safe_dump(vnf_net2instance, indent=4, default_flow_style=False)
3735 # 3. Creating new vm instances in the VIM
3736 # myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
3738 if sce_vnf
.get('mgmt_access'):
3739 ssh_access
= sce_vnf
['mgmt_access'].get('config-access', {}).get('ssh-access')
3740 vnf_availability_zones
= []
3741 for vm
in sce_vnf
.get('vms'):
3742 vm_av
= vm
.get('availability_zone')
3743 if vm_av
and vm_av
not in vnf_availability_zones
:
3744 vnf_availability_zones
.append(vm_av
)
3746 # check if there is enough availability zones available at vim level.
3747 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
3748 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
3749 raise NfvoException('No enough availability zones at VIM for this deployment', httperrors
.Bad_Request
)
3751 if sce_vnf
.get("datacenter"):
3752 vim
= myvims
[sce_vnf
["datacenter"]]
3753 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
3754 datacenter_id
= sce_vnf
["datacenter"]
3756 vim
= myvims
[default_datacenter_id
]
3757 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
3758 datacenter_id
= default_datacenter_id
3759 sce_vnf
["datacenter_id"] = datacenter_id
3762 vnf_uuid
= str(uuid4())
3763 uuid_list
.append(vnf_uuid
)
3766 'instance_scenario_id': instance_uuid
,
3767 'vnf_id': sce_vnf
['vnf_id'],
3768 'sce_vnf_id': sce_vnf
['uuid'],
3769 'datacenter_id': datacenter_id
,
3770 'datacenter_tenant_id': myvim_thread_id
,
3772 db_instance_vnfs
.append(db_instance_vnf
)
3774 for vm
in sce_vnf
['vms']:
3776 if vm
.get("pdu_type"):
3780 sce_vnf_name
= sce_vnf
['member_vnf_index'] if sce_vnf
['member_vnf_index'] else sce_vnf
['name']
3781 myVMDict
['name'] = "{}-{}-{}".format(instance_name
[:64], sce_vnf_name
[:64], vm
["name"][:64])
3782 myVMDict
['description'] = myVMDict
['name'][0:99]
3784 # myVMDict['start'] = "no"
3785 if vm
.get("instance_parameters") and vm
["instance_parameters"].get("name"):
3786 myVMDict
['name'] = vm
["instance_parameters"].get("name")
3787 myVMDict
['name'] = myVMDict
['name'][0:255] # limit name length
3788 # create image at vim in case it not exist
3789 image_uuid
= vm
['image_id']
3790 if vm
.get("image_list"):
3791 for alternative_image
in vm
["image_list"]:
3792 if alternative_image
["vim_type"] == vim
["config"]["_vim_type_internal"]:
3793 image_uuid
= alternative_image
['image_id']
3795 image_dict
= mydb
.get_table_by_uuid_name("images", image_uuid
)
3796 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
3797 vm
['vim_image_id'] = image_id
3799 # create flavor at vim in case it not exist
3800 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
3801 if flavor_dict
['extended'] != None:
3802 flavor_dict
['extended'] = yaml
.load(flavor_dict
['extended'])
3803 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
3805 # Obtain information for additional disks
3806 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',),
3807 WHERE
={'vim_id': flavor_id
})
3808 if not extended_flavor_dict
:
3809 raise NfvoException("flavor '{}' not found".format(flavor_id
), httperrors
.Not_Found
)
3811 # extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
3812 myVMDict
['disks'] = None
3813 extended_info
= extended_flavor_dict
[0]['extended']
3814 if extended_info
!= None:
3815 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
3816 if 'disks' in extended_flavor_dict_yaml
:
3817 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
3818 if vm
.get("instance_parameters") and vm
["instance_parameters"].get("devices"):
3819 for disk
in myVMDict
['disks']:
3820 if disk
.get("name") in vm
["instance_parameters"]["devices"]:
3821 disk
.update(vm
["instance_parameters"]["devices"][disk
.get("name")])
3823 vm
['vim_flavor_id'] = flavor_id
3824 myVMDict
['imageRef'] = vm
['vim_image_id']
3825 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
3826 myVMDict
['availability_zone'] = vm
.get('availability_zone')
3827 myVMDict
['networks'] = []
3828 task_depends_on
= []
3829 # TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
3830 is_management_vm
= False
3832 for iface
in vm
['interfaces']:
3834 if iface
['type'] == "data":
3835 netDict
['type'] = iface
['model']
3836 elif "model" in iface
and iface
["model"] != None:
3837 netDict
['model'] = iface
['model']
3838 # TODO in future, remove this because mac_address will not be set, and the type of PV,VF
3839 # is obtained from iterface table model
3840 # discover type of interface looking at flavor
3841 for numa
in flavor_dict
.get('extended', {}).get('numas', []):
3842 for flavor_iface
in numa
.get('interfaces', []):
3843 if flavor_iface
.get('name') == iface
['internal_name']:
3844 if flavor_iface
['dedicated'] == 'yes':
3845 netDict
['type'] = "PF" # passthrough
3846 elif flavor_iface
['dedicated'] == 'no':
3847 netDict
['type'] = "VF" # siov
3848 elif flavor_iface
['dedicated'] == 'yes:sriov':
3849 netDict
['type'] = "VFnotShared" # sriov but only one sriov on the PF
3850 netDict
["mac_address"] = flavor_iface
.get("mac_address")
3852 netDict
["use"] = iface
['type']
3853 if netDict
["use"] == "data" and not netDict
.get("type"):
3854 # print "netDict", netDict
3855 # print "iface", iface
3856 e_text
= "Cannot determine the interface type PF or VF of VNF '{}' VM '{}' iface '{}'".fromat(
3857 sce_vnf
['name'], vm
['name'], iface
['internal_name'])
3858 if flavor_dict
.get('extended') == None:
3859 raise NfvoException(e_text
+ "After database migration some information is not available. \
3860 Try to delete and create the scenarios and VNFs again", httperrors
.Conflict
)
3862 raise NfvoException(e_text
, httperrors
.Internal_Server_Error
)
3863 if netDict
["use"] == "mgmt":
3864 is_management_vm
= True
3865 netDict
["type"] = "virtual"
3866 if netDict
["use"] == "bridge":
3867 netDict
["type"] = "virtual"
3868 if iface
.get("vpci"):
3869 netDict
['vpci'] = iface
['vpci']
3870 if iface
.get("mac"):
3871 netDict
['mac_address'] = iface
['mac']
3872 if iface
.get("mac_address"):
3873 netDict
['mac_address'] = iface
['mac_address']
3874 if iface
.get("ip_address"):
3875 netDict
['ip_address'] = iface
['ip_address']
3876 if iface
.get("port-security") is not None:
3877 netDict
['port_security'] = iface
['port-security']
3878 if iface
.get("floating-ip") is not None:
3879 netDict
['floating_ip'] = iface
['floating-ip']
3880 netDict
['name'] = iface
['internal_name']
3881 if iface
['net_id'] is None:
3882 for vnf_iface
in sce_vnf
["interfaces"]:
3885 if vnf_iface
['interface_id'] == iface
['uuid']:
3886 netDict
['net_id'] = "TASK-{}".format(
3887 net2task_id
['scenario'][vnf_iface
['sce_net_id']][datacenter_id
])
3888 instance_net_id
= sce_net2instance
[vnf_iface
['sce_net_id']][datacenter_id
]
3889 task_depends_on
.append(net2task_id
['scenario'][vnf_iface
['sce_net_id']][datacenter_id
])
3892 netDict
['net_id'] = "TASK-{}".format(net2task_id
[sce_vnf
['uuid']][iface
['net_id']])
3893 instance_net_id
= vnf_net2instance
[sce_vnf
['uuid']][iface
['net_id']]
3894 task_depends_on
.append(net2task_id
[sce_vnf
['uuid']][iface
['net_id']])
3895 # skip bridge ifaces not connected to any net
3896 if 'net_id' not in netDict
or netDict
['net_id'] == None:
3898 myVMDict
['networks'].append(netDict
)
3901 # 'instance_vm_id': instance_vm_uuid,
3902 "instance_net_id": instance_net_id
,
3903 'interface_id': iface
['uuid'],
3904 # 'vim_interface_id': ,
3905 'type': 'external' if iface
['external_name'] is not None else 'internal',
3906 'ip_address': iface
.get('ip_address'),
3907 'mac_address': iface
.get('mac'),
3908 'floating_ip': int(iface
.get('floating-ip', False)),
3909 'port_security': int(iface
.get('port-security', True))
3911 db_vm_ifaces
.append(db_vm_iface
)
3912 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3913 # print myVMDict['name']
3914 # print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
3915 # print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
3916 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3918 # We add the RO key to cloud_config if vnf will need ssh access
3919 cloud_config_vm
= cloud_config
3920 if is_management_vm
and params
["instance_parameters"].get("mgmt_keys"):
3921 cloud_config_vm
= unify_cloud_config({"key-pairs": params
["instance_parameters"]["mgmt_keys"]},
3924 if vm
.get("instance_parameters") and vm
["instance_parameters"].get("mgmt_keys"):
3925 cloud_config_vm
= unify_cloud_config({"key-pairs": vm
["instance_parameters"]["mgmt_keys"]},
3927 # if ssh_access and ssh_access['required'] and ssh_access['default-user'] and tenant[0].get('RO_pub_key'):
3928 # RO_key = {"key-pairs": [tenant[0]['RO_pub_key']]}
3929 # cloud_config_vm = unify_cloud_config(cloud_config_vm, RO_key)
3930 if vm
.get("boot_data"):
3931 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config_vm
)
3933 if myVMDict
.get('availability_zone'):
3934 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
3937 for vm_index
in range(0, vm
.get('count', 1)):
3938 vm_name
= myVMDict
['name'] + "-" + str(vm_index
+1)
3939 task_params
= (vm_name
, myVMDict
['description'], myVMDict
.get('start', None),
3940 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'], cloud_config_vm
,
3941 myVMDict
['disks'], av_index
, vnf_availability_zones
)
3942 # put interface uuid back to scenario[vnfs][vms[[interfaces]
3943 for net
in myVMDict
['networks']:
3945 for iface
in vm
['interfaces']:
3946 if net
["name"] == iface
["internal_name"]:
3947 iface
["vim_id"] = net
["vim_id"]
3949 vm_uuid
= str(uuid4())
3950 uuid_list
.append(vm_uuid
)
3953 'instance_vnf_id': vnf_uuid
,
3954 # TODO delete "vim_vm_id": vm_id,
3955 "vm_id": vm
["uuid"],
3956 "vim_name": vm_name
,
3959 db_instance_vms
.append(db_vm
)
3962 for db_vm_iface
in db_vm_ifaces
:
3963 iface_uuid
= str(uuid4())
3964 uuid_list
.append(iface_uuid
)
3965 db_vm_iface_instance
= {
3967 "instance_vm_id": vm_uuid
3969 db_vm_iface_instance
.update(db_vm_iface
)
3970 if db_vm_iface_instance
.get("ip_address"): # increment ip_address
3971 ip
= db_vm_iface_instance
.get("ip_address")
3976 ip
= ip
[i
:] + str(int(ip
[:i
]) + 1)
3977 db_vm_iface_instance
["ip_address"] = ip
3979 db_vm_iface_instance
["ip_address"] = None
3980 db_instance_interfaces
.append(db_vm_iface_instance
)
3981 myVMDict
['networks'][iface_index
]["uuid"] = iface_uuid
3985 "instance_action_id": instance_action_id
,
3986 "task_index": task_index
,
3987 "datacenter_vim_id": myvim_thread_id
,
3989 "status": "SCHEDULED",
3990 "item": "instance_vms",
3992 "extra": yaml
.safe_dump({"params": task_params
, "depends_on": task_depends_on
},
3993 default_flow_style
=True, width
=256)
3996 db_vim_actions
.append(db_vim_action
)
3997 params_out
["task_index"] = task_index
3998 params_out
["uuid_list"] = uuid_list
4001 def delete_instance(mydb
, tenant_id
, instance_id
):
4002 # print "Checking that the instance_id exists and getting the instance dictionary"
4003 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
4004 # print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
4005 tenant_id
= instanceDict
["tenant_id"]
4008 # We need to retrieve the WIM Actions now, before the instance_scenario is
4009 # deleted. The reason for that is that: ON CASCADE rules will delete the
4010 # instance_wim_nets record in the database
4011 wim_actions
= wim_engine
.delete_actions(instance_scenario_id
=instance_id
)
4014 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
4015 # 1. Delete from Database
4016 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
4018 # 2. delete from VIM
4022 vimthread_affected
= {}
4023 net2vm_dependencies
= {}
4026 instance_action_id
= get_task_id()
4028 db_instance_action
= {
4029 "uuid": instance_action_id
, # same uuid for the instance and the action on create
4030 "tenant_id": tenant_id
,
4031 "instance_id": instance_id
,
4032 "description": "DELETE",
4033 # "number_tasks": 0 # filled bellow
4036 # 2.1 deleting VNFFGs
4037 for sfp
in instanceDict
.get('sfps', ()):
4038 vimthread_affected
[sfp
["datacenter_tenant_id"]] = None
4039 datacenter_key
= (sfp
["datacenter_id"], sfp
["datacenter_tenant_id"])
4040 if datacenter_key
not in myvims
:
4042 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sfp
["datacenter_id"], sfp
["datacenter_tenant_id"])
4043 except NfvoException
as e
:
4044 logger
.error(str(e
))
4046 myvim_threads
[datacenter_key
] = myvim_thread
4047 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sfp
["datacenter_id"],
4048 datacenter_tenant_id
=sfp
["datacenter_tenant_id"])
4050 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfp
["datacenter_id"], sfp
["datacenter_tenant_id"]))
4051 myvims
[datacenter_key
] = None
4053 myvims
[datacenter_key
] = vims
.values()[0]
4054 myvim
= myvims
[datacenter_key
]
4055 myvim_thread
= myvim_threads
[datacenter_key
]
4058 error_msg
+= "\n vim_sfp_id={} cannot be deleted because datacenter={} not found".format(sfp
['vim_sfp_id'], sfp
["datacenter_id"])
4060 extra
= {"params": (sfp
['vim_sfp_id'])}
4062 "instance_action_id": instance_action_id
,
4063 "task_index": task_index
,
4064 "datacenter_vim_id": sfp
["datacenter_tenant_id"],
4066 "status": "SCHEDULED",
4067 "item": "instance_sfps",
4068 "item_id": sfp
["uuid"],
4069 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4072 db_vim_actions
.append(db_vim_action
)
4074 for classification
in instanceDict
['classifications']:
4075 vimthread_affected
[classification
["datacenter_tenant_id"]] = None
4076 datacenter_key
= (classification
["datacenter_id"], classification
["datacenter_tenant_id"])
4077 if datacenter_key
not in myvims
:
4079 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, classification
["datacenter_id"], classification
["datacenter_tenant_id"])
4080 except NfvoException
as e
:
4081 logger
.error(str(e
))
4083 myvim_threads
[datacenter_key
] = myvim_thread
4084 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=classification
["datacenter_id"],
4085 datacenter_tenant_id
=classification
["datacenter_tenant_id"])
4087 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(classification
["datacenter_id"],
4088 classification
["datacenter_tenant_id"]))
4089 myvims
[datacenter_key
] = None
4091 myvims
[datacenter_key
] = vims
.values()[0]
4092 myvim
= myvims
[datacenter_key
]
4093 myvim_thread
= myvim_threads
[datacenter_key
]
4096 error_msg
+= "\n vim_classification_id={} cannot be deleted because datacenter={} not found".format(classification
['vim_classification_id'],
4097 classification
["datacenter_id"])
4099 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfps"]
4100 extra
= {"params": (classification
['vim_classification_id']), "depends_on": depends_on
}
4102 "instance_action_id": instance_action_id
,
4103 "task_index": task_index
,
4104 "datacenter_vim_id": classification
["datacenter_tenant_id"],
4106 "status": "SCHEDULED",
4107 "item": "instance_classifications",
4108 "item_id": classification
["uuid"],
4109 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4112 db_vim_actions
.append(db_vim_action
)
4114 for sf
in instanceDict
.get('sfs', ()):
4115 vimthread_affected
[sf
["datacenter_tenant_id"]] = None
4116 datacenter_key
= (sf
["datacenter_id"], sf
["datacenter_tenant_id"])
4117 if datacenter_key
not in myvims
:
4119 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sf
["datacenter_id"], sf
["datacenter_tenant_id"])
4120 except NfvoException
as e
:
4121 logger
.error(str(e
))
4123 myvim_threads
[datacenter_key
] = myvim_thread
4124 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sf
["datacenter_id"],
4125 datacenter_tenant_id
=sf
["datacenter_tenant_id"])
4127 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sf
["datacenter_id"], sf
["datacenter_tenant_id"]))
4128 myvims
[datacenter_key
] = None
4130 myvims
[datacenter_key
] = vims
.values()[0]
4131 myvim
= myvims
[datacenter_key
]
4132 myvim_thread
= myvim_threads
[datacenter_key
]
4135 error_msg
+= "\n vim_sf_id={} cannot be deleted because datacenter={} not found".format(sf
['vim_sf_id'], sf
["datacenter_id"])
4137 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfps"]
4138 extra
= {"params": (sf
['vim_sf_id']), "depends_on": depends_on
}
4140 "instance_action_id": instance_action_id
,
4141 "task_index": task_index
,
4142 "datacenter_vim_id": sf
["datacenter_tenant_id"],
4144 "status": "SCHEDULED",
4145 "item": "instance_sfs",
4146 "item_id": sf
["uuid"],
4147 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4150 db_vim_actions
.append(db_vim_action
)
4152 for sfi
in instanceDict
.get('sfis', ()):
4153 vimthread_affected
[sfi
["datacenter_tenant_id"]] = None
4154 datacenter_key
= (sfi
["datacenter_id"], sfi
["datacenter_tenant_id"])
4155 if datacenter_key
not in myvims
:
4157 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sfi
["datacenter_id"], sfi
["datacenter_tenant_id"])
4158 except NfvoException
as e
:
4159 logger
.error(str(e
))
4161 myvim_threads
[datacenter_key
] = myvim_thread
4162 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sfi
["datacenter_id"],
4163 datacenter_tenant_id
=sfi
["datacenter_tenant_id"])
4165 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfi
["datacenter_id"], sfi
["datacenter_tenant_id"]))
4166 myvims
[datacenter_key
] = None
4168 myvims
[datacenter_key
] = vims
.values()[0]
4169 myvim
= myvims
[datacenter_key
]
4170 myvim_thread
= myvim_threads
[datacenter_key
]
4173 error_msg
+= "\n vim_sfi_id={} cannot be deleted because datacenter={} not found".format(sfi
['vim_sfi_id'], sfi
["datacenter_id"])
4175 depends_on
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfs"]
4176 extra
= {"params": (sfi
['vim_sfi_id']), "depends_on": depends_on
}
4178 "instance_action_id": instance_action_id
,
4179 "task_index": task_index
,
4180 "datacenter_vim_id": sfi
["datacenter_tenant_id"],
4182 "status": "SCHEDULED",
4183 "item": "instance_sfis",
4184 "item_id": sfi
["uuid"],
4185 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4188 db_vim_actions
.append(db_vim_action
)
4192 for sce_vnf
in instanceDict
.get('vnfs', ()):
4193 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
4194 vimthread_affected
[sce_vnf
["datacenter_tenant_id"]] = None
4195 if datacenter_key
not in myvims
:
4197 _
, myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
4198 except NfvoException
as e
:
4199 logger
.error(str(e
))
4201 myvim_threads
[datacenter_key
] = myvim_thread
4202 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
4203 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
4205 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
4206 sce_vnf
["datacenter_tenant_id"]))
4207 myvims
[datacenter_key
] = None
4209 myvims
[datacenter_key
] = vims
.values()[0]
4210 myvim
= myvims
[datacenter_key
]
4211 myvim_thread
= myvim_threads
[datacenter_key
]
4213 for vm
in sce_vnf
['vms']:
4215 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
4217 sfi_dependencies
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfis"]
4219 "instance_action_id": instance_action_id
,
4220 "task_index": task_index
,
4221 "datacenter_vim_id": sce_vnf
["datacenter_tenant_id"],
4223 "status": "SCHEDULED",
4224 "item": "instance_vms",
4225 "item_id": vm
["uuid"],
4226 "extra": yaml
.safe_dump({"params": vm
["interfaces"], "depends_on": sfi_dependencies
},
4227 default_flow_style
=True, width
=256)
4229 db_vim_actions
.append(db_vim_action
)
4230 for interface
in vm
["interfaces"]:
4231 if not interface
.get("instance_net_id"):
4233 if interface
["instance_net_id"] not in net2vm_dependencies
:
4234 net2vm_dependencies
[interface
["instance_net_id"]] = []
4235 net2vm_dependencies
[interface
["instance_net_id"]].append(task_index
)
4240 for net
in instanceDict
['nets']:
4241 vimthread_affected
[net
["datacenter_tenant_id"]] = None
4242 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
4243 if datacenter_key
not in myvims
:
4245 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, net
["datacenter_id"], net
["datacenter_tenant_id"])
4246 except NfvoException
as e
:
4247 logger
.error(str(e
))
4249 myvim_threads
[datacenter_key
] = myvim_thread
4250 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
4251 datacenter_tenant_id
=net
["datacenter_tenant_id"])
4253 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
4254 myvims
[datacenter_key
] = None
4256 myvims
[datacenter_key
] = vims
.values()[0]
4257 myvim
= myvims
[datacenter_key
]
4258 myvim_thread
= myvim_threads
[datacenter_key
]
4261 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
4263 extra
= {"params": (net
['vim_net_id'], net
['sdn_net_id'])}
4264 if net2vm_dependencies
.get(net
["uuid"]):
4265 extra
["depends_on"] = net2vm_dependencies
[net
["uuid"]]
4266 sfi_dependencies
= [action
["task_index"] for action
in db_vim_actions
if action
["item"] == "instance_sfis"]
4267 if len(sfi_dependencies
) > 0:
4268 if "depends_on" in extra
:
4269 extra
["depends_on"] += sfi_dependencies
4271 extra
["depends_on"] = sfi_dependencies
4273 "instance_action_id": instance_action_id
,
4274 "task_index": task_index
,
4275 "datacenter_vim_id": net
["datacenter_tenant_id"],
4277 "status": "SCHEDULED",
4278 "item": "instance_nets",
4279 "item_id": net
["uuid"],
4280 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4283 db_vim_actions
.append(db_vim_action
)
4285 db_instance_action
["number_tasks"] = task_index
4288 wim_actions
, db_instance_action
= (
4289 wim_engine
.incorporate_actions(wim_actions
, db_instance_action
))
4293 {"instance_actions": db_instance_action
},
4294 {"vim_wim_actions": db_vim_actions
+ wim_actions
}
4297 logger
.debug("delete_instance done DB tables: %s",
4298 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
4299 mydb
.new_rows(db_tables
, ())
4300 for myvim_thread_id
in vimthread_affected
.keys():
4301 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
4303 wim_engine
.dispatch(wim_actions
)
4305 if len(error_msg
) > 0:
4306 return 'action_id={} instance {} deleted but some elements could not be deleted, or already deleted '\
4307 '(error: 404) from VIM: {}'.format(instance_action_id
, message
, error_msg
)
4309 return "action_id={} instance {} deleted".format(instance_action_id
, message
)
4311 def get_instance_id(mydb
, tenant_id
, instance_id
):
4313 #check valid tenant_id
4314 check_tenant(mydb
, tenant_id
)
4317 instance_dict
= mydb
.get_instance_scenario(instance_id
, tenant_id
, verbose
=True)
4318 for net
in instance_dict
["nets"]:
4319 if net
.get("sdn_net_id"):
4320 net_sdn
= ovim
.show_network(net
["sdn_net_id"])
4322 "admin_state_up": net_sdn
.get("admin_state_up"),
4323 "flows": net_sdn
.get("flows"),
4324 "last_error": net_sdn
.get("last_error"),
4325 "ports": net_sdn
.get("ports"),
4326 "type": net_sdn
.get("type"),
4327 "status": net_sdn
.get("status"),
4328 "vlan": net_sdn
.get("vlan"),
4330 return instance_dict
4332 @deprecated("Instance is automatically refreshed by vim_threads")
4333 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
4334 '''Refreshes a scenario instance. It modifies instanceDict'''
4336 - 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
4339 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
4340 # #print "nfvo.refresh_instance begins"
4341 # #print json.dumps(instanceDict, indent=4)
4343 # #print "Getting the VIM URL and the VIM tenant_id"
4346 # # 1. Getting VIM vm and net list
4347 # vms_updated = [] #List of VM instance uuids in openmano that were updated
4350 # for sce_vnf in instanceDict['vnfs']:
4351 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
4352 # if datacenter_key not in vm_list:
4353 # vm_list[datacenter_key] = []
4354 # if datacenter_key not in myvims:
4355 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
4356 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
4357 # if len(vims) == 0:
4358 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
4359 # myvims[datacenter_key] = None
4361 # myvims[datacenter_key] = vims.values()[0]
4362 # for vm in sce_vnf['vms']:
4363 # vm_list[datacenter_key].append(vm['vim_vm_id'])
4364 # vms_notupdated.append(vm["uuid"])
4366 # nets_updated = [] #List of VM instance uuids in openmano that were updated
4367 # nets_notupdated=[]
4369 # for net in instanceDict['nets']:
4370 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
4371 # if datacenter_key not in net_list:
4372 # net_list[datacenter_key] = []
4373 # if datacenter_key not in myvims:
4374 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
4375 # datacenter_tenant_id=net["datacenter_tenant_id"])
4376 # if len(vims) == 0:
4377 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
4378 # myvims[datacenter_key] = None
4380 # myvims[datacenter_key] = vims.values()[0]
4382 # net_list[datacenter_key].append(net['vim_net_id'])
4383 # nets_notupdated.append(net["uuid"])
4385 # # 1. Getting the status of all VMs
4387 # for datacenter_key in myvims:
4388 # if not vm_list.get(datacenter_key):
4392 # if not myvims[datacenter_key]:
4393 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
4396 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
4398 # except vimconn.vimconnException as e:
4399 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
4400 # failed_message = str(e)
4402 # for vm in vm_list[datacenter_key]:
4403 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
4405 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
4406 # for sce_vnf in instanceDict['vnfs']:
4407 # for vm in sce_vnf['vms']:
4408 # vm_id = vm['vim_vm_id']
4409 # interfaces = vm_dict[vm_id].pop('interfaces', [])
4410 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
4411 # has_mgmt_iface = False
4412 # for iface in vm["interfaces"]:
4413 # if iface["type"]=="mgmt":
4414 # has_mgmt_iface = True
4415 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
4416 # vm_dict[vm_id]['status'] = "ACTIVE"
4417 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
4418 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
4419 # 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'):
4420 # vm['status'] = vm_dict[vm_id]['status']
4421 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
4422 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
4423 # # 2.1. Update in openmano DB the VMs whose status changed
4425 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
4426 # vms_notupdated.remove(vm["uuid"])
4428 # vms_updated.append(vm["uuid"])
4429 # except db_base_Exception as e:
4430 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
4431 # # 2.2. Update in openmano DB the interface VMs
4432 # for interface in interfaces:
4433 # #translate from vim_net_id to instance_net_id
4434 # network_id_list=[]
4435 # for net in instanceDict['nets']:
4436 # if net["vim_net_id"] == interface["vim_net_id"]:
4437 # network_id_list.append(net["uuid"])
4438 # if not network_id_list:
4440 # del interface["vim_net_id"]
4442 # for network_id in network_id_list:
4443 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
4444 # except db_base_Exception as e:
4445 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
4447 # # 3. Getting the status of all nets
4449 # for datacenter_key in myvims:
4450 # if not net_list.get(datacenter_key):
4453 # failed_message = ""
4454 # if not myvims[datacenter_key]:
4455 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
4458 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
4460 # except vimconn.vimconnException as e:
4461 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
4462 # failed_message = str(e)
4464 # for net in net_list[datacenter_key]:
4465 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
4467 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
4468 # # TODO: update nets inside a vnf
4469 # for net in instanceDict['nets']:
4470 # net_id = net['vim_net_id']
4471 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
4472 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
4473 # 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'):
4474 # net['status'] = net_dict[net_id]['status']
4475 # net['error_msg'] = net_dict[net_id].get('error_msg')
4476 # net['vim_info'] = net_dict[net_id].get('vim_info')
4477 # # 5.1. Update in openmano DB the nets whose status changed
4479 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
4480 # nets_notupdated.remove(net["uuid"])
4482 # nets_updated.append(net["uuid"])
4483 # except db_base_Exception as e:
4484 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
4486 # # Returns appropriate output
4487 # #print "nfvo.refresh_instance finishes"
4488 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
4489 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
4490 instance_id
= instanceDict
['uuid']
4491 # if len(vms_notupdated)+len(nets_notupdated)>0:
4492 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
4493 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
4495 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
4497 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
4498 #print "Checking that the instance_id exists and getting the instance dictionary"
4499 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
4500 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
4502 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
4503 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
4505 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), httperrors
.Not_Found
)
4506 myvim
= vims
.values()[0]
4511 myvim_threads_id
= {}
4512 if action_dict
.get("vdu-scaling"):
4513 db_instance_vms
= []
4515 db_instance_interfaces
= []
4516 instance_action_id
= get_task_id()
4517 db_instance_action
= {
4518 "uuid": instance_action_id
, # same uuid for the instance and the action on create
4519 "tenant_id": nfvo_tenant
,
4520 "instance_id": instance_id
,
4521 "description": "SCALE",
4523 vm_result
["instance_action_id"] = instance_action_id
4524 vm_result
["created"] = []
4525 vm_result
["deleted"] = []
4527 for vdu
in action_dict
["vdu-scaling"]:
4528 vdu_id
= vdu
.get("vdu-id")
4529 osm_vdu_id
= vdu
.get("osm_vdu_id")
4530 member_vnf_index
= vdu
.get("member-vnf-index")
4531 vdu_count
= vdu
.get("count", 1)
4533 target_vms
= mydb
.get_rows(
4534 FROM
="instance_vms as vms join instance_vnfs as vnfs on vms.instance_vnf_id=vnfs.uuid",
4535 WHERE
={"vms.uuid": vdu_id
},
4536 ORDER_BY
="vms.created_at"
4539 raise NfvoException("Cannot find the vdu with id {}".format(vdu_id
), httperrors
.Not_Found
)
4541 if not osm_vdu_id
and not member_vnf_index
:
4542 raise NfvoException("Invalid input vdu parameters. Must supply either 'vdu-id' of 'osm_vdu_id','member-vnf-index'")
4543 target_vms
= mydb
.get_rows(
4544 # SELECT=("ivms.uuid", "ivnfs.datacenter_id", "ivnfs.datacenter_tenant_id"),
4545 FROM
="instance_vms as ivms join instance_vnfs as ivnfs on ivms.instance_vnf_id=ivnfs.uuid"\
4546 " join sce_vnfs as svnfs on ivnfs.sce_vnf_id=svnfs.uuid"\
4547 " join vms on ivms.vm_id=vms.uuid",
4548 WHERE
={"vms.osm_id": osm_vdu_id
, "svnfs.member_vnf_index": member_vnf_index
,
4549 "ivnfs.instance_scenario_id": instance_id
},
4550 ORDER_BY
="ivms.created_at"
4553 raise NfvoException("Cannot find the vdu with osm_vdu_id {} and member-vnf-index {}".format(osm_vdu_id
, member_vnf_index
), httperrors
.Not_Found
)
4554 vdu_id
= target_vms
[-1]["uuid"]
4555 target_vm
= target_vms
[-1]
4556 datacenter
= target_vm
["datacenter_id"]
4557 myvim_threads_id
[datacenter
], _
= get_vim_thread(mydb
, nfvo_tenant
, datacenter
)
4559 if vdu
["type"] == "delete":
4560 for index
in range(0, vdu_count
):
4561 target_vm
= target_vms
[-1-index
]
4562 vdu_id
= target_vm
["uuid"]
4564 vm_interfaces
= None
4565 for sce_vnf
in instanceDict
['vnfs']:
4566 for vm
in sce_vnf
['vms']:
4567 if vm
["uuid"] == vdu_id
:
4568 vm_interfaces
= vm
["interfaces"]
4572 "instance_action_id": instance_action_id
,
4573 "task_index": task_index
,
4574 "datacenter_vim_id": target_vm
["datacenter_tenant_id"],
4576 "status": "SCHEDULED",
4577 "item": "instance_vms",
4579 "extra": yaml
.safe_dump({"params": vm_interfaces
},
4580 default_flow_style
=True, width
=256)
4583 db_vim_actions
.append(db_vim_action
)
4584 vm_result
["deleted"].append(vdu_id
)
4585 # delete from database
4586 db_instance_vms
.append({"TO-DELETE": vdu_id
})
4588 else: # vdu["type"] == "create":
4590 where
= {"item": "instance_vms", "item_id": target_vm
["uuid"], "action": "CREATE"}
4592 vim_action_to_clone
= mydb
.get_rows(FROM
="vim_wim_actions", WHERE
=where
)
4593 if not vim_action_to_clone
:
4594 raise NfvoException("Cannot find the vim_action at database with {}".format(where
), httperrors
.Internal_Server_Error
)
4595 vim_action_to_clone
= vim_action_to_clone
[0]
4596 extra
= yaml
.safe_load(vim_action_to_clone
["extra"])
4598 # generate a new depends_on. Convert format TASK-Y into new format TASK-ACTION-XXXX.XXXX.Y
4599 # TODO do the same for flavor and image when available
4600 task_depends_on
= []
4601 task_params
= extra
["params"]
4602 task_params_networks
= deepcopy(task_params
[5])
4603 for iface
in task_params
[5]:
4604 if iface
["net_id"].startswith("TASK-"):
4605 if "." not in iface
["net_id"]:
4606 task_depends_on
.append("{}.{}".format(vim_action_to_clone
["instance_action_id"],
4607 iface
["net_id"][5:]))
4608 iface
["net_id"] = "TASK-{}.{}".format(vim_action_to_clone
["instance_action_id"],
4609 iface
["net_id"][5:])
4611 task_depends_on
.append(iface
["net_id"][5:])
4612 if "mac_address" in iface
:
4613 del iface
["mac_address"]
4615 vm_ifaces_to_clone
= mydb
.get_rows(FROM
="instance_interfaces", WHERE
={"instance_vm_id": target_vm
["uuid"]})
4616 for index
in range(0, vdu_count
):
4617 vm_uuid
= str(uuid4())
4618 vm_name
= target_vm
.get('vim_name')
4620 suffix
= vm_name
.rfind("-")
4621 vm_name
= vm_name
[:suffix
+1] + str(index
+ 1 + int(vm_name
[suffix
+1:]))
4626 'instance_vnf_id': target_vm
['instance_vnf_id'],
4627 'vm_id': target_vm
['vm_id'],
4630 db_instance_vms
.append(db_instance_vm
)
4632 for vm_iface
in vm_ifaces_to_clone
:
4633 iface_uuid
= str(uuid4())
4634 iface2iface
[vm_iface
["uuid"]] = iface_uuid
4637 'instance_vm_id': vm_uuid
,
4638 "instance_net_id": vm_iface
["instance_net_id"],
4639 'interface_id': vm_iface
['interface_id'],
4640 'type': vm_iface
['type'],
4641 'floating_ip': vm_iface
['floating_ip'],
4642 'port_security': vm_iface
['port_security']
4644 db_instance_interfaces
.append(db_vm_iface
)
4645 task_params_copy
= deepcopy(task_params
)
4646 for iface
in task_params_copy
[5]:
4647 iface
["uuid"] = iface2iface
[iface
["uuid"]]
4648 # increment ip_address
4649 if "ip_address" in iface
:
4650 ip
= iface
.get("ip_address")
4655 ip
= ip
[i
:] + str(int(ip
[:i
]) + 1)
4656 iface
["ip_address"] = ip
4658 iface
["ip_address"] = None
4660 task_params_copy
[0] = vm_name
4662 "instance_action_id": instance_action_id
,
4663 "task_index": task_index
,
4664 "datacenter_vim_id": vim_action_to_clone
["datacenter_vim_id"],
4666 "status": "SCHEDULED",
4667 "item": "instance_vms",
4671 # TODO examinar parametros, quitar MAC o incrementar. Incrementar IP y colocar las dependencias con ACTION-asdfasd.
4674 "extra": yaml
.safe_dump({"params": task_params_copy
, "depends_on": task_depends_on
}, default_flow_style
=True, width
=256)
4677 db_vim_actions
.append(db_vim_action
)
4678 vm_result
["created"].append(vm_uuid
)
4680 db_instance_action
["number_tasks"] = task_index
4682 {"instance_vms": db_instance_vms
},
4683 {"instance_interfaces": db_instance_interfaces
},
4684 {"instance_actions": db_instance_action
},
4686 # {"instance_sfis": db_instance_sfis},
4687 # {"instance_sfs": db_instance_sfs},
4688 # {"instance_classifications": db_instance_classifications},
4689 # {"instance_sfps": db_instance_sfps},
4690 {"vim_wim_actions": db_vim_actions
}
4692 logger
.debug("create_vdu done DB tables: %s",
4693 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
4694 mydb
.new_rows(db_tables
, [])
4695 for myvim_thread
in myvim_threads_id
.values():
4696 vim_threads
["running"][myvim_thread
].insert_task(db_vim_actions
)
4700 input_vnfs
= action_dict
.pop("vnfs", [])
4701 input_vms
= action_dict
.pop("vms", [])
4702 action_over_all
= True if not input_vnfs
and not input_vms
else False
4703 for sce_vnf
in instanceDict
['vnfs']:
4704 for vm
in sce_vnf
['vms']:
4705 if not action_over_all
and sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
4706 sce_vnf
['member_vnf_index'] not in input_vnfs
and \
4707 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
4710 if "add_public_key" in action_dict
:
4712 if sce_vnf
.get('mgmt_access'):
4713 mgmt_access
= yaml
.load(sce_vnf
['mgmt_access'])
4714 ssh_access
= mgmt_access
['config-access']['ssh-access']
4715 tenant
= mydb
.get_rows_by_id('nfvo_tenants', nfvo_tenant
)
4717 if ssh_access
['required'] and ssh_access
['default-user']:
4718 if 'ip_address' in vm
:
4719 mgmt_ip
= vm
['ip_address'].split(';')
4720 password
= mgmt_access
['config-access'].get('password')
4721 priv_RO_key
= decrypt_key(tenant
[0]['encrypted_RO_priv_key'], tenant
[0]['uuid'])
4722 myvim
.inject_user_key(mgmt_ip
[0], ssh_access
['default-user'],
4723 action_dict
['add_public_key'],
4724 password
=password
, ro_key
=priv_RO_key
)
4726 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4727 httperrors
.Internal_Server_Error
)
4729 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4730 httperrors
.Internal_Server_Error
)
4732 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4733 httperrors
.Internal_Server_Error
)
4735 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
4736 if "console" in action_dict
:
4737 if not global_config
["http_console_proxy"]:
4738 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4739 "description": "{protocol}//{ip}:{port}/{suffix}".format(
4740 protocol
=data
["protocol"],
4741 ip
= data
["server"],
4742 port
= data
["port"],
4743 suffix
= data
["suffix"]),
4747 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
4748 vm_result
[ vm
['uuid'] ] = {"vim_result": -httperrors
.Unauthorized
,
4749 "description": "this console is only reachable by local interface",
4754 #print "console data", data
4756 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
4757 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4758 "description": "{protocol}//{ip}:{port}/{suffix}".format(
4759 protocol
=data
["protocol"],
4760 ip
= global_config
["http_console_host"],
4761 port
= console_thread
.port
,
4762 suffix
= data
["suffix"]),
4766 except NfvoException
as e
:
4767 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
4771 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
4773 except vimconn
.vimconnException
as e
:
4774 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
4777 if vm_ok
==0: #all goes wrong
4782 def instance_action_get(mydb
, nfvo_tenant
, instance_id
, action_id
):
4784 if nfvo_tenant
and nfvo_tenant
!= "any":
4785 filter["tenant_id"] = nfvo_tenant
4786 if instance_id
and instance_id
!= "any":
4787 filter["instance_id"] = instance_id
4789 filter["uuid"] = action_id
4790 rows
= mydb
.get_rows(FROM
="instance_actions", WHERE
=filter)
4793 raise NfvoException("Not found any action with this criteria", httperrors
.Not_Found
)
4794 vim_wim_actions
= mydb
.get_rows(FROM
="vim_wim_actions", WHERE
={"instance_action_id": action_id
})
4795 rows
[0]["vim_wim_actions"] = vim_wim_actions
4796 # for backward compatibility set vim_actions = vim_wim_actions
4797 rows
[0]["vim_actions"] = vim_wim_actions
4798 return {"actions": rows
}
4801 def create_or_use_console_proxy_thread(console_server
, console_port
):
4802 #look for a non-used port
4803 console_thread_key
= console_server
+ ":" + str(console_port
)
4804 if console_thread_key
in global_config
["console_thread"]:
4805 #global_config["console_thread"][console_thread_key].start_timeout()
4806 return global_config
["console_thread"][console_thread_key
]
4808 for port
in global_config
["console_port_iterator"]():
4809 #print "create_or_use_console_proxy_thread() port:", port
4810 if port
in global_config
["console_ports"]:
4813 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
4815 global_config
["console_thread"][console_thread_key
] = clithread
4816 global_config
["console_ports"][port
] = console_thread_key
4818 except cli
.ConsoleProxyExceptionPortUsed
as e
:
4819 #port used, try with onoher
4821 except cli
.ConsoleProxyException
as e
:
4822 raise NfvoException(str(e
), httperrors
.Bad_Request
)
4823 raise NfvoException("Not found any free 'http_console_ports'", httperrors
.Conflict
)
4826 def check_tenant(mydb
, tenant_id
):
4827 '''check that tenant exists at database'''
4828 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
4830 raise NfvoException("tenant '{}' not found".format(tenant_id
), httperrors
.Not_Found
)
4833 def new_tenant(mydb
, tenant_dict
):
4835 tenant_uuid
= str(uuid4())
4836 tenant_dict
['uuid'] = tenant_uuid
4838 pub_key
, priv_key
= create_RO_keypair(tenant_uuid
)
4839 tenant_dict
['RO_pub_key'] = pub_key
4840 tenant_dict
['encrypted_RO_priv_key'] = priv_key
4841 mydb
.new_row("nfvo_tenants", tenant_dict
, confidential_data
=True)
4842 except db_base_Exception
as e
:
4843 raise NfvoException("Error creating the new tenant: {} ".format(tenant_dict
['name']) + str(e
), e
.http_code
)
4846 def delete_tenant(mydb
, tenant
):
4847 #get nfvo_tenant info
4849 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
4850 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
4851 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
4854 def new_datacenter(mydb
, datacenter_descriptor
):
4855 sdn_port_mapping
= None
4856 if "config" in datacenter_descriptor
:
4857 sdn_port_mapping
= datacenter_descriptor
["config"].pop("sdn-port-mapping", None)
4858 datacenter_descriptor
["config"] = yaml
.safe_dump(datacenter_descriptor
["config"], default_flow_style
=True,
4860 # Check that datacenter-type is correct
4861 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
4862 # module_info = None
4864 module
= "vimconn_" + datacenter_type
4865 pkg
= __import__("osm_ro." + module
)
4866 # vim_conn = getattr(pkg, module)
4867 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
4868 except (IOError, ImportError):
4869 # if module_info and module_info[0]:
4870 # file.close(module_info[0])
4871 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}.py' not installed".format(datacenter_type
,
4873 httperrors
.Bad_Request
)
4875 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True, confidential_data
=True)
4876 if sdn_port_mapping
:
4878 datacenter_sdn_port_mapping_set(mydb
, None, datacenter_id
, sdn_port_mapping
)
4879 except Exception as e
:
4880 mydb
.delete_row_by_id("datacenters", datacenter_id
) # Rollback
4882 return datacenter_id
4885 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
4886 # obtain data, check that only one exist
4887 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
4890 datacenter_id
= datacenter
['uuid']
4891 where
= {'uuid': datacenter
['uuid']}
4892 remove_port_mapping
= False
4893 new_sdn_port_mapping
= None
4894 if "config" in datacenter_descriptor
:
4895 if datacenter_descriptor
['config'] != None:
4897 new_config_dict
= datacenter_descriptor
["config"]
4898 if "sdn-port-mapping" in new_config_dict
:
4899 remove_port_mapping
= True
4900 new_sdn_port_mapping
= new_config_dict
.pop("sdn-port-mapping")
4901 # delete null fields
4903 for k
in new_config_dict
:
4904 if new_config_dict
[k
] is None:
4906 if k
== 'sdn-controller':
4907 remove_port_mapping
= True
4909 config_text
= datacenter
.get("config")
4912 config_dict
= yaml
.load(config_text
)
4913 config_dict
.update(new_config_dict
)
4914 # delete null fields
4917 except Exception as e
:
4918 raise NfvoException("Bad format at datacenter:config " + str(e
), httperrors
.Bad_Request
)
4920 datacenter_descriptor
["config"] = yaml
.safe_dump(config_dict
, default_flow_style
=True, width
=256)
4922 datacenter_descriptor
["config"] = None
4923 if remove_port_mapping
:
4925 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_id
)
4926 except ovimException
as e
:
4927 raise NfvoException("Error deleting datacenter-port-mapping " + str(e
), httperrors
.Conflict
)
4929 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
4930 if new_sdn_port_mapping
:
4932 datacenter_sdn_port_mapping_set(mydb
, None, datacenter_id
, new_sdn_port_mapping
)
4933 except ovimException
as e
:
4935 mydb
.update_rows('datacenters', datacenter
, where
)
4936 raise NfvoException("Error adding datacenter-port-mapping " + str(e
), httperrors
.Conflict
)
4937 return datacenter_id
4940 def delete_datacenter(mydb
, datacenter
):
4941 #get nfvo_tenant info
4942 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
4943 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
4945 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_dict
['uuid'])
4946 except ovimException
as e
:
4947 raise NfvoException("Error deleting datacenter-port-mapping " + str(e
))
4948 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
4951 def create_vim_account(mydb
, nfvo_tenant
, datacenter_id
, name
=None, vim_id
=None, vim_tenant
=None, vim_tenant_name
=None,
4952 vim_username
=None, vim_password
=None, config
=None):
4953 # get datacenter info
4955 if not datacenter_id
:
4957 raise NfvoException("You must provide 'vim_id", http_code
=httperrors
.Bad_Request
)
4958 datacenter_id
= vim_id
4959 datacenter_id
, datacenter_name
= get_datacenter_uuid(mydb
, None, datacenter_id
)
4961 create_vim_tenant
= True if not vim_tenant
and not vim_tenant_name
else False
4963 # get nfvo_tenant info
4964 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
4965 if vim_tenant_name
==None:
4966 vim_tenant_name
=tenant_dict
['name']
4968 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
4969 # #check that this association does not exist before
4970 # tenants_datacenters = mydb.get_rows(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict)
4971 # if len(tenants_datacenters)>0:
4972 # raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id, tenant_dict['uuid']), httperrors.Conflict)
4974 vim_tenant_id_exist_atdb
=False
4975 if not create_vim_tenant
:
4976 where_
={"datacenter_id": datacenter_id
}
4977 if vim_tenant
!=None:
4978 where_
["vim_tenant_id"] = vim_tenant
4979 if vim_tenant_name
!=None:
4980 where_
["vim_tenant_name"] = vim_tenant_name
4981 #check if vim_tenant_id is already at database
4982 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
4983 if len(datacenter_tenants_dict
)>=1:
4984 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
4985 vim_tenant_id_exist_atdb
=True
4986 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
4988 datacenter_tenants_dict
= {}
4989 #insert at table datacenter_tenants
4990 else: #if vim_tenant==None:
4991 #create tenant at VIM if not provided
4993 _
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
, vim_user
=vim_username
,
4994 vim_passwd
=vim_password
)
4995 datacenter_name
= myvim
["name"]
4996 vim_tenant
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
4997 except vimconn
.vimconnException
as e
:
4998 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), httperrors
.Internal_Server_Error
)
4999 datacenter_tenants_dict
= {}
5000 datacenter_tenants_dict
["created"]="true"
5002 #fill datacenter_tenants table
5003 if not vim_tenant_id_exist_atdb
:
5004 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant
5005 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
5006 datacenter_tenants_dict
["user"] = vim_username
5007 datacenter_tenants_dict
["passwd"] = vim_password
5008 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
5010 datacenter_tenants_dict
["name"] = name
5012 datacenter_tenants_dict
["name"] = datacenter_name
5014 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
5015 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True, confidential_data
=True)
5016 datacenter_tenants_dict
["uuid"] = id_
5018 #fill tenants_datacenters table
5019 datacenter_tenant_id
= datacenter_tenants_dict
["uuid"]
5020 tenants_datacenter_dict
["datacenter_tenant_id"] = datacenter_tenant_id
5021 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
5024 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
5025 new_thread
= vim_thread
.vim_thread(task_lock
, thread_name
, datacenter_name
, datacenter_tenant_id
,
5026 db
=db
, db_lock
=db_lock
, ovim
=ovim
)
5028 thread_id
= datacenter_tenants_dict
["uuid"]
5029 vim_threads
["running"][thread_id
] = new_thread
5031 except vimconn
.vimconnException
as e
:
5032 raise NfvoException(str(e
), httperrors
.Bad_Request
)
5035 def edit_vim_account(mydb
, nfvo_tenant
, datacenter_tenant_id
, datacenter_id
=None, name
=None, vim_tenant
=None,
5036 vim_tenant_name
=None, vim_username
=None, vim_password
=None, config
=None):
5038 # get vim_account; check is valid for this tenant
5039 from_
= "datacenter_tenants as dt JOIN tenants_datacenters as td ON dt.uuid=td.datacenter_tenant_id"
5040 where_
= {"td.nfvo_tenant_id": nfvo_tenant
}
5041 if datacenter_tenant_id
:
5042 where_
["dt.uuid"] = datacenter_tenant_id
5044 where_
["dt.datacenter_id"] = datacenter_id
5045 vim_accounts
= mydb
.get_rows(SELECT
="dt.uuid as uuid, config", FROM
=from_
, WHERE
=where_
)
5046 if not vim_accounts
:
5047 raise NfvoException("vim_account not found for this tenant", http_code
=httperrors
.Not_Found
)
5048 elif len(vim_accounts
) > 1:
5049 raise NfvoException("found more than one vim_account for this tenant", http_code
=httperrors
.Conflict
)
5050 datacenter_tenant_id
= vim_accounts
[0]["uuid"]
5051 original_config
= vim_accounts
[0]["config"]
5055 original_config_dict
= yaml
.load(original_config
)
5056 original_config_dict
.update(config
)
5057 update
["config"] = yaml
.safe_dump(original_config_dict
, default_flow_style
=True, width
=256)
5059 update_
['name'] = name
5061 update_
['vim_tenant_id'] = vim_tenant
5063 update_
['vim_tenant_name'] = vim_tenant_name
5065 update_
['user'] = vim_username
5067 update_
['passwd'] = vim_password
5069 mydb
.update_rows("datacenter_tenants", UPDATE
=update_
, WHERE
={"uuid": datacenter_tenant_id
})
5071 vim_threads
["running"][datacenter_tenant_id
].insert_task("reload")
5072 return datacenter_tenant_id
5074 def delete_vim_account(mydb
, tenant_id
, vim_account_id
, datacenter
=None):
5075 #get nfvo_tenant info
5076 if not tenant_id
or tenant_id
=="any":
5079 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
5080 tenant_uuid
= tenant_dict
['uuid']
5082 #check that this association exist before
5083 tenants_datacenter_dict
= {}
5085 datacenter_id
, _
= get_datacenter_uuid(mydb
, tenant_uuid
, datacenter
)
5086 tenants_datacenter_dict
["datacenter_id"] = datacenter_id
5087 elif vim_account_id
:
5088 tenants_datacenter_dict
["datacenter_tenant_id"] = vim_account_id
5090 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
5091 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
5092 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
5093 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), httperrors
.Not_Found
)
5095 #delete this association
5096 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
5098 #get vim_tenant info and deletes
5100 for tenant_datacenter_item
in tenant_datacenter_list
:
5101 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
5102 #try to delete vim:tenant
5104 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
5105 if vim_tenant_dict
['created']=='true':
5106 #delete tenant at VIM if created by NFVO
5108 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5109 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
5110 except vimconn
.vimconnException
as e
:
5111 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
5112 logger
.warn(warning
)
5113 except db_base_Exception
as e
:
5114 logger
.error("Cannot delete datacenter_tenants " + str(e
))
5115 pass # the error will be caused because dependencies, vim_tenant can not be deleted
5116 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
5117 thread
= vim_threads
["running"].get(thread_id
)
5119 thread
.insert_task("exit")
5120 vim_threads
["deleting"][thread_id
] = thread
5121 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
5124 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
5126 #get datacenter info
5127 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5129 if 'net-update' in action_dict
:
5131 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
5133 except vimconn
.vimconnException
as e
:
5134 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
5135 raise NfvoException(str(e
), httperrors
.Internal_Server_Error
)
5136 #update nets Change from VIM format to NFVO format
5139 net_nfvo
={'datacenter_id': datacenter_id
}
5140 net_nfvo
['name'] = net
['name']
5141 #net_nfvo['description']= net['name']
5142 net_nfvo
['vim_net_id'] = net
['id']
5143 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
5144 net_nfvo
['shared'] = net
['shared']
5145 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
5146 net_list
.append(net_nfvo
)
5147 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
5148 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
5150 elif 'net-edit' in action_dict
:
5151 net
= action_dict
['net-edit'].pop('net')
5152 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
5153 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
5154 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
5156 elif 'net-delete' in action_dict
:
5157 net
= action_dict
['net-deelte'].get('net')
5158 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
5159 result
= mydb
.delete_row(FROM
='datacenter_nets',
5160 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
5164 raise NfvoException("Unknown action " + str(action_dict
), httperrors
.Bad_Request
)
5167 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
5168 #get datacenter info
5169 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5171 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
5172 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
5173 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
5177 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
5178 #get datacenter info
5179 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5182 action_dict
= action_dict
["netmap"]
5183 if 'vim_id' in action_dict
:
5184 filter_dict
["id"] = action_dict
['vim_id']
5185 if 'vim_name' in action_dict
:
5186 filter_dict
["name"] = action_dict
['vim_name']
5188 filter_dict
["shared"] = True
5191 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
5192 except vimconn
.vimconnException
as e
:
5193 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
5194 raise NfvoException(str(e
), httperrors
.Internal_Server_Error
)
5195 if len(vim_nets
)>1 and action_dict
:
5196 raise NfvoException("more than two networks found, specify with vim_id", httperrors
.Conflict
)
5197 elif len(vim_nets
)==0: # and action_dict:
5198 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), httperrors
.Not_Found
)
5200 for net
in vim_nets
:
5201 net_nfvo
={'datacenter_id': datacenter_id
}
5202 if action_dict
and "name" in action_dict
:
5203 net_nfvo
['name'] = action_dict
['name']
5205 net_nfvo
['name'] = net
['name']
5206 #net_nfvo['description']= net['name']
5207 net_nfvo
['vim_net_id'] = net
['id']
5208 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
5209 net_nfvo
['shared'] = net
['shared']
5210 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
5212 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
5213 net_nfvo
["status"] = "OK"
5214 net_nfvo
["uuid"] = net_id
5215 except db_base_Exception
as e
:
5219 net_nfvo
["status"] = "FAIL: " + str(e
)
5220 net_list
.append(net_nfvo
)
5223 def get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
):
5224 # obtain all network data
5226 if utils
.check_valid_uuid(network_id
):
5227 filter_dict
= {"id": network_id
}
5229 filter_dict
= {"name": network_id
}
5231 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5232 network
= myvim
.get_network_list(filter_dict
=filter_dict
)
5233 except vimconn
.vimconnException
as e
:
5234 raise NfvoException("Not possible to get_sdn_net_id from VIM: {}".format(str(e
)), e
.http_code
)
5236 # ensure the network is defined
5237 if len(network
) == 0:
5238 raise NfvoException("Network {} is not present in the system".format(network_id
),
5239 httperrors
.Bad_Request
)
5241 # ensure there is only one network with the provided name
5242 if len(network
) > 1:
5243 raise NfvoException("Multiple networks present in vim identified by {}".format(network_id
), httperrors
.Bad_Request
)
5245 # ensure it is a dataplane network
5246 if network
[0]['type'] != 'data':
5249 # ensure we use the id
5250 network_id
= network
[0]['id']
5252 # search in dabase mano_db in table instance nets for the sdn_net_id that corresponds to the vim_net_id==network_id
5253 # and with instance_scenario_id==NULL
5254 #search_dict = {'vim_net_id': network_id, 'instance_scenario_id': None}
5255 search_dict
= {'vim_net_id': network_id
}
5258 #sdn_network_id = mydb.get_rows(SELECT=('sdn_net_id',), FROM='instance_nets', WHERE=search_dict)[0]['sdn_net_id']
5259 result
= mydb
.get_rows(SELECT
=('sdn_net_id',), FROM
='instance_nets', WHERE
=search_dict
)
5260 except db_base_Exception
as e
:
5261 raise NfvoException("db_base_Exception obtaining SDN network to associated to vim network {}".format(
5262 network_id
) + str(e
), e
.http_code
)
5266 if net
['sdn_net_id'] != None:
5268 sdn_net_id
= net
['sdn_net_id']
5270 if sdn_net_counter
== 0:
5272 elif sdn_net_counter
== 1:
5275 raise NfvoException("More than one SDN network is associated to vim network {}".format(
5276 network_id
), httperrors
.Internal_Server_Error
)
5278 def get_sdn_controller_id(mydb
, datacenter
):
5279 # Obtain sdn controller id
5280 config
= mydb
.get_rows(SELECT
=('config',), FROM
='datacenters', WHERE
={'uuid': datacenter
})[0].get('config', '{}')
5284 return yaml
.load(config
).get('sdn-controller')
5286 def vim_net_sdn_attach(mydb
, tenant_id
, datacenter
, network_id
, descriptor
):
5288 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
5289 if not sdn_network_id
:
5290 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
), httperrors
.Internal_Server_Error
)
5292 #Obtain sdn controller id
5293 controller_id
= get_sdn_controller_id(mydb
, datacenter
)
5294 if not controller_id
:
5295 raise NfvoException("No SDN controller is set for datacenter {}".format(datacenter
), httperrors
.Internal_Server_Error
)
5297 #Obtain sdn controller info
5298 sdn_controller
= ovim
.show_of_controller(controller_id
)
5301 'name': 'external_port',
5302 'net_id': sdn_network_id
,
5303 'ofc_id': controller_id
,
5304 'switch_dpid': sdn_controller
['dpid'],
5305 'switch_port': descriptor
['port']
5308 if 'vlan' in descriptor
:
5309 port_data
['vlan'] = descriptor
['vlan']
5310 if 'mac' in descriptor
:
5311 port_data
['mac'] = descriptor
['mac']
5313 result
= ovim
.new_port(port_data
)
5314 except ovimException
as e
:
5315 raise NfvoException("ovimException attaching SDN network {} to vim network {}".format(
5316 sdn_network_id
, network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5317 except db_base_Exception
as e
:
5318 raise NfvoException("db_base_Exception attaching SDN network to vim network {}".format(
5319 network_id
) + str(e
), e
.http_code
)
5321 return 'Port uuid: '+ result
5323 def vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, network_id
, port_id
=None):
5325 filter = {'uuid': port_id
}
5327 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
5328 if not sdn_network_id
:
5329 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
),
5330 httperrors
.Internal_Server_Error
)
5331 #in case no port_id is specified only ports marked as 'external_port' will be detached
5332 filter = {'name': 'external_port', 'net_id': sdn_network_id
}
5335 port_list
= ovim
.get_ports(columns
={'uuid'}, filter=filter)
5336 except ovimException
as e
:
5337 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
5338 httperrors
.Internal_Server_Error
)
5340 if len(port_list
) == 0:
5341 raise NfvoException("No ports attached to the network {} were found with the requested criteria".format(network_id
),
5342 httperrors
.Bad_Request
)
5345 for port
in port_list
:
5347 port_uuid_list
.append(port
['uuid'])
5348 ovim
.delete_port(port
['uuid'])
5349 except ovimException
as e
:
5350 raise NfvoException("ovimException deleting port {} for net {}. ".format(port
['uuid'], network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5352 return 'Detached ports uuid: {}'.format(','.join(port_uuid_list
))
5354 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
5355 #get datacenter info
5356 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5359 if utils
.check_valid_uuid(name
):
5360 filter_dict
["id"] = name
5362 filter_dict
["name"] = name
5364 if item
=="networks":
5365 #filter_dict['tenant_id'] = myvim['tenant_id']
5366 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
5368 if len(content
) == 0:
5369 raise NfvoException("Network {} is not present in the system. ".format(name
),
5370 httperrors
.Bad_Request
)
5372 #Update the networks with the attached ports
5374 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, net
['id'])
5375 if sdn_network_id
!= None:
5377 #port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan'}, filter={'name': 'external_port', 'net_id': sdn_network_id})
5378 port_list
= ovim
.get_ports(columns
={'uuid', 'switch_port', 'vlan','name'}, filter={'net_id': sdn_network_id
})
5379 except ovimException
as e
:
5380 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5381 #Remove field name and if port name is external_port save it as 'type'
5382 for port
in port_list
:
5383 if port
['name'] == 'external_port':
5384 port
['type'] = "External"
5386 net
['sdn_network_id'] = sdn_network_id
5387 net
['sdn_attached_ports'] = port_list
5389 elif item
=="tenants":
5390 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
5391 elif item
== "images":
5393 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
5395 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5396 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
5397 if name
and len(content
)==1:
5398 return {item
[:-1]: content
[0]}
5399 elif name
and len(content
)==0:
5400 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
5403 return {item
: content
}
5404 except vimconn
.vimconnException
as e
:
5405 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
5406 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
5409 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
5410 #get datacenter info
5411 if tenant_id
== "any":
5414 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5416 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
5417 logger
.debug("vim_action_delete vim response: " + str(content
))
5418 items
= content
.values()[0]
5419 if type(items
)==list and len(items
)==0:
5420 raise NfvoException("Not found " + item
, httperrors
.Not_Found
)
5421 elif type(items
)==list and len(items
)>1:
5422 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), httperrors
.Not_Found
)
5423 else: # it is a dict
5424 item_id
= items
["id"]
5425 item_name
= str(items
.get("name"))
5428 if item
=="networks":
5429 # If there is a SDN network associated to the vim-network, proceed to clear the relationship and delete it
5430 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, item_id
)
5431 if sdn_network_id
!= None:
5432 #Delete any port attachment to this network
5434 port_list
= ovim
.get_ports(columns
={'uuid'}, filter={'net_id': sdn_network_id
})
5435 except ovimException
as e
:
5436 raise NfvoException(
5437 "ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
5438 httperrors
.Internal_Server_Error
)
5440 # By calling one by one all ports to be detached we ensure that not only the external_ports get detached
5441 for port
in port_list
:
5442 vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, item_id
, port
['uuid'])
5444 #Delete from 'instance_nets' the correspondence between the vim-net-id and the sdn-net-id
5446 mydb
.delete_row(FROM
='instance_nets', WHERE
={'instance_scenario_id': None, 'sdn_net_id': sdn_network_id
, 'vim_net_id': item_id
})
5447 except db_base_Exception
as e
:
5448 raise NfvoException("Error deleting correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
5449 str(e
), e
.http_code
)
5451 #Delete the SDN network
5453 ovim
.delete_network(sdn_network_id
)
5454 except ovimException
as e
:
5455 logger
.error("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
), exc_info
=True)
5456 raise NfvoException("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
),
5457 httperrors
.Internal_Server_Error
)
5459 content
= myvim
.delete_network(item_id
)
5460 elif item
=="tenants":
5461 content
= myvim
.delete_tenant(item_id
)
5462 elif item
== "images":
5463 content
= myvim
.delete_image(item_id
)
5465 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5466 except vimconn
.vimconnException
as e
:
5467 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
5468 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
5470 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
5473 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
5474 #get datacenter info
5475 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
5476 if tenant_id
== "any":
5478 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5480 if item
=="networks":
5481 net
= descriptor
["network"]
5482 net_name
= net
.pop("name")
5483 net_type
= net
.pop("type", "bridge")
5484 net_public
= net
.pop("shared", False)
5485 net_ipprofile
= net
.pop("ip_profile", None)
5486 net_vlan
= net
.pop("vlan", None)
5487 content
, _
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
5489 #If the datacenter has a SDN controller defined and the network is of dataplane type, then create the sdn network
5490 if get_sdn_controller_id(mydb
, datacenter
) != None and (net_type
== 'data' or net_type
== 'ptp'):
5491 #obtain datacenter_tenant_id
5492 datacenter_tenant_id
= mydb
.get_rows(SELECT
=('uuid',),
5493 FROM
='datacenter_tenants',
5494 WHERE
={'datacenter_id': datacenter
})[0]['uuid']
5497 sdn_network
['vlan'] = net_vlan
5498 sdn_network
['type'] = net_type
5499 sdn_network
['name'] = net_name
5500 sdn_network
['region'] = datacenter_tenant_id
5501 ovim_content
= ovim
.new_network(sdn_network
)
5502 except ovimException
as e
:
5503 logger
.error("ovimException creating SDN network={} ".format(
5504 sdn_network
) + str(e
), exc_info
=True)
5505 raise NfvoException("ovimException creating SDN network={} ".format(sdn_network
) + str(e
),
5506 httperrors
.Internal_Server_Error
)
5508 # Save entry in in dabase mano_db in table instance_nets to stablish a dictionary vim_net_id <->sdn_net_id
5509 # use instance_scenario_id=None to distinguish from real instaces of nets
5510 correspondence
= {'instance_scenario_id': None,
5511 'sdn_net_id': ovim_content
,
5512 'vim_net_id': content
,
5513 'datacenter_tenant_id': datacenter_tenant_id
5516 mydb
.new_row('instance_nets', correspondence
, add_uuid
=True)
5517 except db_base_Exception
as e
:
5518 raise NfvoException("Error saving correspondence for VIM/SDN dataplane networks{}: {}".format(
5519 correspondence
, e
), e
.http_code
)
5520 elif item
=="tenants":
5521 tenant
= descriptor
["tenant"]
5522 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
5524 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5525 except vimconn
.vimconnException
as e
:
5526 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
5528 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
5530 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
5531 data
= ovim
.new_of_controller(sdn_controller
)
5532 logger
.debug('New SDN controller created with uuid {}'.format(data
))
5535 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
5536 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
5537 msg
= 'SDN controller {} updated'.format(data
)
5541 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
5542 if controller_id
== None:
5543 data
= ovim
.get_of_controllers()
5545 data
= ovim
.show_of_controller(controller_id
)
5547 msg
= 'SDN controller list:\n {}'.format(data
)
5551 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
5552 select_
= ('uuid', 'config')
5553 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
5554 for datacenter
in datacenters
:
5555 if datacenter
['config']:
5556 config
= yaml
.load(datacenter
['config'])
5557 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
5558 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), httperrors
.Conflict
)
5560 data
= ovim
.delete_of_controller(controller_id
)
5561 msg
= 'SDN controller {} deleted'.format(data
)
5565 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
5566 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
5567 if len(controller
) < 1:
5568 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), httperrors
.Not_Found
)
5571 sdn_controller_id
= yaml
.load(controller
[0]["config"])["sdn-controller"]
5573 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), httperrors
.Bad_Request
)
5575 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
5576 switch_dpid
= sdn_controller
["dpid"]
5579 for compute_node
in sdn_port_mapping
:
5580 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
5582 element
["compute_node"] = compute_node
["compute_node"]
5583 for port
in compute_node
["ports"]:
5584 pci
= port
.get("pci")
5585 element
["switch_port"] = port
.get("switch_port")
5586 element
["switch_mac"] = port
.get("switch_mac")
5587 if not element
["switch_port"] and not element
["switch_mac"]:
5588 raise NfvoException ("The mapping must contain 'switch_port' or 'switch_mac'", httperrors
.Bad_Request
)
5589 for pci_expanded
in utils
.expand_brackets(pci
):
5590 element
["pci"] = pci_expanded
5591 maps
.append(dict(element
))
5593 return ovim
.set_of_port_mapping(maps
, ofc_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, region
=datacenter_id
)
5595 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
5596 maps
= ovim
.get_of_port_mappings(db_filter
={"region": datacenter_id
})
5599 "sdn-controller": None,
5600 "datacenter-id": datacenter_id
,
5602 "ports_mapping": list()
5605 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
5606 if datacenter
['config']:
5607 config
= yaml
.load(datacenter
['config'])
5608 if 'sdn-controller' in config
:
5609 controller_id
= config
['sdn-controller']
5610 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
5611 result
["sdn-controller"] = controller_id
5612 result
["dpid"] = sdn_controller
["dpid"]
5614 if result
["sdn-controller"] == None:
5615 raise NfvoException("SDN controller is not defined for datacenter {}".format(datacenter_id
), httperrors
.Bad_Request
)
5616 if result
["dpid"] == None:
5617 raise NfvoException("It was not possible to determine DPID for SDN controller {}".format(result
["sdn-controller"]),
5618 httperrors
.Internal_Server_Error
)
5623 ports_correspondence_dict
= dict()
5625 if result
["sdn-controller"] != link
["ofc_id"]:
5626 raise NfvoException("The sdn-controller specified for different port mappings differ", httperrors
.Internal_Server_Error
)
5627 if result
["dpid"] != link
["switch_dpid"]:
5628 raise NfvoException("The dpid specified for different port mappings differ", httperrors
.Internal_Server_Error
)
5630 element
["pci"] = link
["pci"]
5631 if link
["switch_port"]:
5632 element
["switch_port"] = link
["switch_port"]
5633 if link
["switch_mac"]:
5634 element
["switch_mac"] = link
["switch_mac"]
5636 if not link
["compute_node"] in ports_correspondence_dict
:
5638 content
["compute_node"] = link
["compute_node"]
5639 content
["ports"] = list()
5640 ports_correspondence_dict
[link
["compute_node"]] = content
5642 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
5644 for key
in sorted(ports_correspondence_dict
):
5645 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
5649 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
5650 return ovim
.clear_of_port_mapping(db_filter
={"region":datacenter_id
})
5652 def create_RO_keypair(tenant_id
):
5654 Creates a public / private keys for a RO tenant and returns their values
5656 tenant_id: ID of the tenant
5658 public_key: Public key for the RO tenant
5659 private_key: Encrypted private key for RO tenant
5663 key
= RSA
.generate(bits
)
5665 public_key
= key
.publickey().exportKey('OpenSSH')
5666 if isinstance(public_key
, ValueError):
5667 raise NfvoException("Unable to create public key: {}".format(public_key
), httperrors
.Internal_Server_Error
)
5668 private_key
= key
.exportKey(passphrase
=tenant_id
, pkcs
=8)
5669 except (ValueError, NameError) as e
:
5670 raise NfvoException("Unable to create private key: {}".format(e
), httperrors
.Internal_Server_Error
)
5671 return public_key
, private_key
5673 def decrypt_key (key
, tenant_id
):
5675 Decrypts an encrypted RSA key
5677 key: Private key to be decrypted
5678 tenant_id: ID of the tenant
5680 unencrypted_key: Unencrypted private key for RO tenant
5683 key
= RSA
.importKey(key
,tenant_id
)
5684 unencrypted_key
= key
.exportKey('PEM')
5685 if isinstance(unencrypted_key
, ValueError):
5686 raise NfvoException("Unable to decrypt the private key: {}".format(unencrypted_key
), httperrors
.Internal_Server_Error
)
5687 except ValueError as e
:
5688 raise NfvoException("Unable to decrypt the private key: {}".format(e
), httperrors
.Internal_Server_Error
)
5689 return unencrypted_key