1 # -*- coding: utf-8 -*-
4 # Copyright 2015 Telefónica Investigación 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
67 global vimconn_imported
71 global wimconn_imported
74 global default_volume_size
75 default_volume_size
= '5' #size in GB
80 vimconn_imported
= {} # dictionary with VIM type as key, loaded module as value
81 vim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-VIMs
82 vim_persistent_info
= {}
84 wimconn_imported
= {} # dictionary with WIM type as key, loaded module as value
85 wim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-WIMs
86 wim_persistent_info
= {}
89 logger
= logging
.getLogger('openmano.nfvo')
96 class NfvoException(httperrors
.HttpMappedError
):
97 """Common Class for NFVO errors"""
103 if task_id
<= last_task_id
:
104 task_id
= last_task_id
+ 0.000001
105 last_task_id
= task_id
106 return "ACTION-{:.6f}".format(task_id
)
107 # return (t.strftime("%Y%m%dT%H%M%S.{}%Z", t.localtime(task_id))).format(int((task_id % 1)*1e6))
110 def new_task(name
, params
, depends
=None):
112 task_id
= get_task_id()
113 task
= {"status": "enqueued", "id": task_id
, "name": name
, "params": params
}
115 task
["depends"] = depends
120 return True if id[:5] == "TASK-" else False
123 def get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_name
, tenant_id
):
124 name
= datacenter_name
[:16]
125 if name
not in vim_threads
["names"]:
126 vim_threads
["names"].append(name
)
128 name
= datacenter_name
[:16] + "." + tenant_name
[:16]
129 if name
not in vim_threads
["names"]:
130 vim_threads
["names"].append(name
)
132 name
= datacenter_id
+ "-" + tenant_id
133 vim_threads
["names"].append(name
)
137 def get_non_used_wim_name(wim_name
, wim_id
, tenant_name
, tenant_id
):
139 if name
not in wim_threads
["names"]:
140 wim_threads
["names"].append(name
)
142 name
= wim_name
[:16] + "." + tenant_name
[:16]
143 if name
not in wim_threads
["names"]:
144 wim_threads
["names"].append(name
)
146 name
= wim_id
+ "-" + tenant_id
147 wim_threads
["names"].append(name
)
151 def start_service(mydb
, persistence
=None, wim
=None):
152 global db
, global_config
153 db
= nfvo_db
.nfvo_db()
154 db
.connect(global_config
['db_host'], global_config
['db_user'], global_config
['db_passwd'], global_config
['db_name'])
158 persistence
.lock
= db_lock
160 persistence
= WimPersistence(db
, lock
=db_lock
)
162 # Initialize openvim for SDN control
163 # TODO: Avoid static configuration by adding new parameters to openmanod.cfg
164 # TODO: review ovim.py to delete not needed configuration
165 ovim_configuration
= {
166 'logger_name': 'openmano.ovim',
167 'network_vlan_range_start': 1000,
168 'network_vlan_range_end': 4096,
169 'db_name': global_config
["db_ovim_name"],
170 'db_host': global_config
["db_ovim_host"],
171 'db_user': global_config
["db_ovim_user"],
172 'db_passwd': global_config
["db_ovim_passwd"],
175 'network_type': 'bridge',
176 #TODO: log_level_of should not be needed. To be modified in ovim
177 'log_level_of': 'DEBUG'
180 # starts ovim library
181 ovim
= ovim_module
.ovim(ovim_configuration
)
184 wim_engine
= wim
or WimEngine(persistence
)
185 wim_engine
.ovim
= ovim
189 #delete old unneeded vim_wim_actions
193 from_
= 'tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join '\
194 'datacenter_tenants as dt on td.datacenter_tenant_id=dt.uuid'
195 select_
= ('type', 'd.config as config', 'd.uuid as datacenter_id', 'vim_url', 'vim_url_admin',
196 'd.name as datacenter_name', 'dt.uuid as datacenter_tenant_id',
197 'dt.vim_tenant_name as vim_tenant_name', 'dt.vim_tenant_id as vim_tenant_id',
198 'user', 'passwd', 'dt.config as dt_config', 'nfvo_tenant_id')
199 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
)
201 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
202 'datacenter_id': vim
.get('datacenter_id')}
204 extra
.update(yaml
.load(vim
["config"]))
205 if vim
.get('dt_config'):
206 extra
.update(yaml
.load(vim
["dt_config"]))
207 if vim
["type"] not in vimconn_imported
:
210 module
= "vimconn_" + vim
["type"]
211 pkg
= __import__("osm_ro." + module
)
212 vim_conn
= getattr(pkg
, module
)
213 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
214 # vim_conn = imp.load_module(vim["type"], *module_info)
215 vimconn_imported
[vim
["type"]] = vim_conn
216 except (IOError, ImportError) as e
:
217 # if module_info and module_info[0]:
218 # file.close(module_info[0])
219 raise NfvoException("Unknown vim type '{}'. Cannot open file '{}.py'; {}: {}".format(
220 vim
["type"], module
, type(e
).__name
__, str(e
)), httperrors
.Bad_Request
)
222 thread_id
= vim
['datacenter_tenant_id']
223 vim_persistent_info
[thread_id
] = {}
226 # return -httperrors.Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
227 myvim
= vimconn_imported
[ vim
["type"] ].vimconnector(
228 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
229 tenant_id
=vim
['vim_tenant_id'], tenant_name
=vim
['vim_tenant_name'],
230 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
231 user
=vim
['user'], passwd
=vim
['passwd'],
232 config
=extra
, persistent_info
=vim_persistent_info
[thread_id
]
234 except vimconn
.vimconnException
as e
:
236 logger
.error("Cannot launch thread for VIM {} '{}': {}".format(vim
['datacenter_name'],
237 vim
['datacenter_id'], e
))
238 except Exception as e
:
239 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, e
),
240 httperrors
.Internal_Server_Error
)
241 thread_name
= get_non_used_vim_name(vim
['datacenter_name'], vim
['vim_tenant_id'], vim
['vim_tenant_name'],
242 vim
['vim_tenant_id'])
243 new_thread
= vim_thread
.vim_thread(task_lock
, thread_name
, vim
['datacenter_name'],
244 vim
['datacenter_tenant_id'], db
=db
, db_lock
=db_lock
, ovim
=ovim
)
246 vim_threads
["running"][thread_id
] = new_thread
248 wim_engine
.start_threads()
249 except db_base_Exception
as e
:
250 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
251 except ovim_module
.ovimException
as e
:
253 if message
[:22] == "DATABASE wrong version":
254 message
= "DATABASE wrong version of lib_osm_openvim {msg} -d{dbname} -u{dbuser} -p{dbpass} {ver}' "\
255 "at host {dbhost}".format(
256 msg
=message
[22:-3], dbname
=global_config
["db_ovim_name"],
257 dbuser
=global_config
["db_ovim_user"], dbpass
=global_config
["db_ovim_passwd"],
258 ver
=message
[-3:-1], dbhost
=global_config
["db_ovim_host"])
259 raise NfvoException(message
, httperrors
.Bad_Request
)
263 global ovim
, global_config
266 for thread_id
, thread
in vim_threads
["running"].items():
267 thread
.insert_task("exit")
268 vim_threads
["deleting"][thread_id
] = thread
269 vim_threads
["running"] = {}
272 wim_engine
.stop_threads()
274 if global_config
and global_config
.get("console_thread"):
275 for thread
in global_config
["console_thread"]:
276 thread
.terminate
= True
279 return ("openmanod version {} {}\n(c) Copyright Telefonica".format(global_config
["version"],
280 global_config
["version_date"] ))
284 Clean unused or old entries at database to avoid unlimited growing
285 :param mydb: database connector
288 # get and delete unused vim_wim_actions: all elements deleted, one week before, instance not present
289 now
= t
.time()-3600*24*7
290 instance_action_id
= None
293 actions_to_delete
= mydb
.get_rows(
294 SELECT
=("item", "item_id", "instance_action_id"),
295 FROM
="vim_wim_actions as va join instance_actions as ia on va.instance_action_id=ia.uuid "
296 "left join instance_scenarios as i on ia.instance_id=i.uuid",
297 WHERE
={"va.action": "DELETE", "va.modified_at<": now
, "i.uuid": None,
298 "va.status": ("DONE", "SUPERSEDED")},
301 for to_delete
in actions_to_delete
:
302 mydb
.delete_row(FROM
="vim_wim_actions", WHERE
=to_delete
)
303 if instance_action_id
!= to_delete
["instance_action_id"]:
304 instance_action_id
= to_delete
["instance_action_id"]
305 mydb
.delete_row(FROM
="instance_actions", WHERE
={"uuid": instance_action_id
})
306 nb_deleted
+= len(actions_to_delete
)
307 if len(actions_to_delete
) < 100:
310 logger
.debug("Removed {} unused vim_wim_actions".format(nb_deleted
))
313 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
315 return result, content:
316 <0, error_text upon error
317 nb_records, flavor_list on success
320 WHERE_dict
['vnf_id'] = vnf_id
321 if nfvo_tenant
is not None:
322 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
324 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
325 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
326 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
327 #print "get_flavor_list result:", result
328 #print "get_flavor_list content:", content
330 for flavor
in flavors
:
331 flavorList
.append(flavor
['flavor_id'])
335 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
337 Get used images of all vms belonging to this VNFD
338 :param mydb: database conector
339 :param vnf_id: vnfd uuid
340 :param nfvo_tenant: tenant, not used
341 :return: The list of image uuid used
344 vms
= mydb
.get_rows(SELECT
=('image_id','image_list'), FROM
='vms', WHERE
={'vnf_id': vnf_id
})
346 if vm
["image_id"] not in image_list
:
347 image_list
.append(vm
["image_id"])
349 vm_image_list
= yaml
.load(vm
["image_list"])
350 for image_dict
in vm_image_list
:
351 if image_dict
["image_id"] not in image_list
:
352 image_list
.append(image_dict
["image_id"])
356 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
357 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None, ignore_errors
=False):
358 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
359 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
360 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
361 raise exception upon error
364 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
365 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
366 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
367 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
368 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
369 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
370 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
371 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'
372 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
373 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
374 'user','passwd', 'dt.config as dt_config')
376 from_
= 'datacenters as d'
377 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
379 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
382 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
383 'datacenter_id': vim
.get('datacenter_id'),
384 '_vim_type_internal': vim
.get('type')}
386 extra
.update(yaml
.load(vim
["config"]))
387 if vim
.get('dt_config'):
388 extra
.update(yaml
.load(vim
["dt_config"]))
389 if vim
["type"] not in vimconn_imported
:
392 module
= "vimconn_" + vim
["type"]
393 pkg
= __import__("osm_ro." + module
)
394 vim_conn
= getattr(pkg
, module
)
395 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
396 # vim_conn = imp.load_module(vim["type"], *module_info)
397 vimconn_imported
[vim
["type"]] = vim_conn
398 except (IOError, ImportError) as e
:
399 # if module_info and module_info[0]:
400 # file.close(module_info[0])
402 logger
.error("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
403 vim
["type"], module
, type(e
).__name
__, str(e
)))
405 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
406 vim
["type"], module
, type(e
).__name
__, str(e
)), httperrors
.Bad_Request
)
409 if 'datacenter_tenant_id' in vim
:
410 thread_id
= vim
["datacenter_tenant_id"]
411 if thread_id
not in vim_persistent_info
:
412 vim_persistent_info
[thread_id
] = {}
413 persistent_info
= vim_persistent_info
[thread_id
]
417 # return -httperrors.Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
418 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
419 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
420 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
),
421 tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
422 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
423 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
424 config
=extra
, persistent_info
=persistent_info
426 except Exception as e
:
428 logger
.error("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)))
430 http_code
= httperrors
.Internal_Server_Error
431 if isinstance(e
, vimconn
.vimconnException
):
432 http_code
= e
.http_code
433 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), http_code
)
435 except db_base_Exception
as e
:
436 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
439 def rollback(mydb
, vims
, rollback_list
):
441 #delete things by reverse order
442 for i
in range(len(rollback_list
)-1, -1, -1):
443 item
= rollback_list
[i
]
444 if item
["where"]=="vim":
445 if item
["vim_id"] not in vims
:
447 if is_task_id(item
["uuid"]):
449 vim
= vims
[item
["vim_id"]]
451 if item
["what"]=="image":
452 vim
.delete_image(item
["uuid"])
453 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_vim_id": vim
["id"], "vim_id":item
["uuid"]})
454 elif item
["what"]=="flavor":
455 vim
.delete_flavor(item
["uuid"])
456 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_vim_id": vim
["id"], "vim_id":item
["uuid"]})
457 elif item
["what"]=="network":
458 vim
.delete_network(item
["uuid"])
459 elif item
["what"]=="vm":
460 vim
.delete_vminstance(item
["uuid"])
461 except vimconn
.vimconnException
as e
:
462 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
463 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
464 except db_base_Exception
as e
:
465 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
469 if item
["what"]=="image":
470 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
471 elif item
["what"]=="flavor":
472 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
473 except db_base_Exception
as e
:
474 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
475 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
476 if len(undeleted_items
)==0:
477 return True," Rollback successful."
479 return False," Rollback fails to delete: " + str(undeleted_items
)
482 def check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1):
484 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
486 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
488 #dataplane interfaces
489 for numa
in vnfc
.get("numas",() ):
490 for interface
in numa
.get("interfaces",()):
491 if interface
["name"] in name_dict
:
493 "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
494 vnfc
["name"], interface
["name"]),
495 httperrors
.Bad_Request
)
496 name_dict
[ interface
["name"] ] = "underlay"
498 for interface
in vnfc
.get("bridge-ifaces",() ):
499 if interface
["name"] in name_dict
:
501 "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
502 vnfc
["name"], interface
["name"]),
503 httperrors
.Bad_Request
)
504 name_dict
[ interface
["name"] ] = "overlay"
505 vnfc_interfaces
[ vnfc
["name"] ] = name_dict
506 # check bood-data info
507 # if "boot-data" in vnfc:
508 # # check that user-data is incompatible with users and config-files
509 # if (vnfc["boot-data"].get("users") or vnfc["boot-data"].get("config-files")) and vnfc["boot-data"].get("user-data"):
510 # raise NfvoException(
511 # "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
512 # httperrors.Bad_Request)
514 #check if the info in external_connections matches with the one in the vnfcs
516 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
517 if external_connection
["name"] in name_list
:
519 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
520 external_connection
["name"]),
521 httperrors
.Bad_Request
)
522 name_list
.append(external_connection
["name"])
523 if external_connection
["VNFC"] not in vnfc_interfaces
:
525 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
526 external_connection
["name"], external_connection
["VNFC"]),
527 httperrors
.Bad_Request
)
529 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
531 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
532 external_connection
["name"],
533 external_connection
["local_iface_name"]),
534 httperrors
.Bad_Request
)
536 #check if the info in internal_connections matches with the one in the vnfcs
538 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
539 if internal_connection
["name"] in name_list
:
541 "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection".format(
542 internal_connection
["name"]),
543 httperrors
.Bad_Request
)
544 name_list
.append(internal_connection
["name"])
545 #We should check that internal-connections of type "ptp" have only 2 elements
547 if len(internal_connection
["elements"])>2 and (internal_connection
.get("type") == "ptp" or internal_connection
.get("type") == "e-line"):
549 "Error at 'vnf:internal-connections[name:'{}']:elements', size must be 2 for a '{}' type. Consider change it to '{}' type".format(
550 internal_connection
["name"],
551 'ptp' if vnf_descriptor_version
==1 else 'e-line',
552 'data' if vnf_descriptor_version
==1 else "e-lan"),
553 httperrors
.Bad_Request
)
554 for port
in internal_connection
["elements"]:
556 iface
= port
["local_iface_name"]
557 if vnf
not in vnfc_interfaces
:
559 "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
560 internal_connection
["name"], vnf
),
561 httperrors
.Bad_Request
)
562 if iface
not in vnfc_interfaces
[ vnf
]:
564 "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
565 internal_connection
["name"], iface
),
566 httperrors
.Bad_Request
)
567 return -httperrors
.Bad_Request
,
568 if vnf_descriptor_version
==1 and "type" not in internal_connection
:
569 if vnfc_interfaces
[vnf
][iface
] == "overlay":
570 internal_connection
["type"] = "bridge"
572 internal_connection
["type"] = "data"
573 if vnf_descriptor_version
==2 and "implementation" not in internal_connection
:
574 if vnfc_interfaces
[vnf
][iface
] == "overlay":
575 internal_connection
["implementation"] = "overlay"
577 internal_connection
["implementation"] = "underlay"
578 if (internal_connection
.get("type") == "data" or internal_connection
.get("type") == "ptp" or \
579 internal_connection
.get("implementation") == "underlay") and vnfc_interfaces
[vnf
][iface
] == "overlay":
581 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
582 internal_connection
["name"],
583 iface
, 'bridge' if vnf_descriptor_version
==1 else 'overlay',
584 'data' if vnf_descriptor_version
==1 else 'underlay'),
585 httperrors
.Bad_Request
)
586 if (internal_connection
.get("type") == "bridge" or internal_connection
.get("implementation") == "overlay") and \
587 vnfc_interfaces
[vnf
][iface
] == "underlay":
589 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
590 internal_connection
["name"], iface
,
591 'data' if vnf_descriptor_version
==1 else 'underlay',
592 'bridge' if vnf_descriptor_version
==1 else 'overlay'),
593 httperrors
.Bad_Request
)
596 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=None):
598 if only_create_at_vim
:
599 image_mano_id
= image_dict
['uuid']
600 if return_on_error
== None:
601 return_on_error
= True
603 if image_dict
['location']:
604 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
606 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
608 image_mano_id
= images
[0]['uuid']
610 #create image in MANO DB
611 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
612 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
613 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
615 #temp_image_dict['location'] = image_dict.get('new_location') if image_dict['location'] is None
616 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
617 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
618 #create image at every vim
619 for vim_id
,vim
in vims
.iteritems():
620 datacenter_vim_id
= vim
["config"]["datacenter_tenant_id"]
621 image_created
="false"
623 image_db
= mydb
.get_rows(FROM
="datacenters_images",
624 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'image_id': image_mano_id
})
625 #look at VIM if this image exist
627 if image_dict
['location'] is not None:
628 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
631 filter_dict
['name'] = image_dict
['universal_name']
632 if image_dict
.get('checksum') != None:
633 filter_dict
['checksum'] = image_dict
['checksum']
634 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
635 vim_images
= vim
.get_image_list(filter_dict
)
636 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
637 if len(vim_images
) > 1:
638 raise vimconn
.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict
)), httperrors
.Conflict
)
639 elif len(vim_images
) == 0:
640 raise vimconn
.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict
)))
642 #logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
643 image_vim_id
= vim_images
[0]['id']
645 except vimconn
.vimconnNotFoundException
as e
:
646 #Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
648 #image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
649 if image_dict
['location']:
650 image_vim_id
= vim
.new_image(image_dict
)
651 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
654 #If we reach this point, then the image has image name, and optionally checksum, and could not be found
655 raise vimconn
.vimconnException(str(e
))
656 except vimconn
.vimconnException
as e
:
658 logger
.error("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
661 logger
.warn("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
663 except vimconn
.vimconnException
as e
:
665 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
667 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
670 #if we reach here, the image has been created or existed
672 #add new vim_id at datacenters_images
673 mydb
.new_row('datacenters_images', {'datacenter_vim_id': datacenter_vim_id
,
674 'image_id':image_mano_id
,
675 'vim_id': image_vim_id
,
676 'created':image_created
})
677 elif image_db
[0]["vim_id"]!=image_vim_id
:
678 #modify existing vim_id at datacenters_images
679 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_vim_id':vim_id
, 'image_id':image_mano_id
})
681 return image_vim_id
if only_create_at_vim
else image_mano_id
684 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
685 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',0),
686 'ram':flavor_dict
.get('ram'),
687 'vcpus':flavor_dict
.get('vcpus'),
689 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
690 del flavor_dict
['extended']
691 if 'extended' in flavor_dict
:
692 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
694 #look if flavor exist
695 if only_create_at_vim
:
696 flavor_mano_id
= flavor_dict
['uuid']
697 if return_on_error
== None:
698 return_on_error
= True
700 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
702 flavor_mano_id
= flavors
[0]['uuid']
705 #create one by one the images of aditional disks
706 dev_image_list
=[] #list of images
707 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
709 for device
in flavor_dict
['extended'].get('devices',[]):
710 if "image" not in device
and "image name" not in device
:
713 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
714 image_dict
['universal_name']=device
.get('image name')
715 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
716 image_dict
['location']=device
.get('image')
717 #image_dict['new_location']=vnfc.get('image location')
718 image_dict
['checksum']=device
.get('image checksum')
719 image_metadata_dict
= device
.get('image metadata', None)
720 image_metadata_str
= None
721 if image_metadata_dict
!= None:
722 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
723 image_dict
['metadata']=image_metadata_str
724 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
725 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
726 dev_image_list
.append(image_id
)
728 temp_flavor_dict
['name'] = flavor_dict
['name']
729 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
730 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
731 flavor_mano_id
= content
732 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
733 #create flavor at every vim
734 if 'uuid' in flavor_dict
:
735 del flavor_dict
['uuid']
737 for vim_id
,vim
in vims
.items():
738 datacenter_vim_id
= vim
["config"]["datacenter_tenant_id"]
739 flavor_created
="false"
741 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors",
742 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
})
743 #look at VIM if this flavor exist SKIPPED
744 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
746 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
750 # Create the flavor in VIM
751 # Translate images at devices from MANO id to VIM id
753 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
754 # make a copy of original devices
757 for device
in flavor_dict
["extended"].get("devices",[]):
760 devices_original
.append(dev
)
761 if 'image' in device
:
763 if 'image metadata' in device
:
764 del device
['image metadata']
765 if 'image checksum' in device
:
766 del device
['image checksum']
768 for index
in range(0,len(devices_original
)) :
769 device
=devices_original
[index
]
770 if "image" not in device
and "image name" not in device
:
771 # if 'size' in device:
772 disk_list
.append({'size': device
.get('size', default_volume_size
), 'name': device
.get('name')})
775 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
776 image_dict
['universal_name']=device
.get('image name')
777 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
778 image_dict
['location']=device
.get('image')
779 # image_dict['new_location']=device.get('image location')
780 image_dict
['checksum']=device
.get('image checksum')
781 image_metadata_dict
= device
.get('image metadata', None)
782 image_metadata_str
= None
783 if image_metadata_dict
!= None:
784 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
785 image_dict
['metadata']=image_metadata_str
786 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
787 image_dict
["uuid"]=image_mano_id
788 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
790 #save disk information (image must be based on and size
791 disk_list
.append({'image_id': image_vim_id
, 'size': device
.get('size', default_volume_size
)})
793 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
796 #check that this vim_id exist in VIM, if not create
797 flavor_vim_id
=flavor_db
[0]["vim_id"]
799 vim
.get_flavor(flavor_vim_id
)
800 continue #flavor exist
801 except vimconn
.vimconnException
:
803 #create flavor at vim
804 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
807 flavor_vim_id
=vim
.get_flavor_id_from_data(flavor_dict
)
808 flavor_create
="false"
809 except vimconn
.vimconnException
as e
:
812 if not flavor_vim_id
:
813 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
814 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
815 flavor_created
="true"
816 except vimconn
.vimconnException
as e
:
818 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
820 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
823 #if reach here the flavor has been create or exist
824 if len(flavor_db
)==0:
825 #add new vim_id at datacenters_flavors
826 extended_devices_yaml
= None
827 if len(disk_list
) > 0:
828 extended_devices
= dict()
829 extended_devices
['disks'] = disk_list
830 extended_devices_yaml
= yaml
.safe_dump(extended_devices
,default_flow_style
=True,width
=256)
831 mydb
.new_row('datacenters_flavors',
832 {'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
, 'vim_id': flavor_vim_id
,
833 'created': flavor_created
, 'extended': extended_devices_yaml
})
834 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
835 #modify existing vim_id at datacenters_flavors
836 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
},
837 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
})
839 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
842 def get_str(obj
, field
, length
):
844 Obtain the str value,
849 value
= obj
.get(field
)
850 if value
is not None:
851 value
= str(value
)[:length
]
854 def _lookfor_or_create_image(db_image
, mydb
, descriptor
):
856 fill image content at db_image dictionary. Check if the image with this image and checksum exist
857 :param db_image: dictionary to insert data
858 :param mydb: database connector
859 :param descriptor: yang descriptor
860 :return: uuid if the image exist at DB, or None if a new image must be created with the data filled at db_image
863 db_image
["name"] = get_str(descriptor
, "image", 255)
864 db_image
["checksum"] = get_str(descriptor
, "image-checksum", 32)
865 if not db_image
["checksum"]: # Ensure that if empty string, None is stored
866 db_image
["checksum"] = None
867 if db_image
["name"].startswith("/"):
868 db_image
["location"] = db_image
["name"]
869 existing_images
= mydb
.get_rows(FROM
="images", WHERE
={'location': db_image
["location"]})
871 db_image
["universal_name"] = db_image
["name"]
872 existing_images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name': db_image
['universal_name'],
873 'checksum': db_image
['checksum']})
875 return existing_images
[0]["uuid"]
877 image_uuid
= str(uuid4())
878 db_image
["uuid"] = image_uuid
881 def new_vnfd_v3(mydb
, tenant_id
, vnf_descriptor
):
883 Parses an OSM IM vnfd_catalog and insert at DB
886 :param vnf_descriptor:
887 :return: The list of cretated vnf ids
890 myvnfd
= vnfd_catalog
.vnfd()
892 pybindJSONDecoder
.load_ietf_json(vnf_descriptor
, None, None, obj
=myvnfd
, path_helper
=True)
893 except Exception as e
:
894 raise NfvoException("Error. Invalid VNF descriptor format " + str(e
), httperrors
.Bad_Request
)
902 db_ip_profiles_index
= 0
906 vnfd_catalog_descriptor
= vnf_descriptor
.get("vnfd:vnfd-catalog")
907 if not vnfd_catalog_descriptor
:
908 vnfd_catalog_descriptor
= vnf_descriptor
.get("vnfd-catalog")
909 vnfd_descriptor_list
= vnfd_catalog_descriptor
.get("vnfd")
910 if not vnfd_descriptor_list
:
911 vnfd_descriptor_list
= vnfd_catalog_descriptor
.get("vnfd:vnfd")
912 for vnfd_yang
in myvnfd
.vnfd_catalog
.vnfd
.itervalues():
913 vnfd
= vnfd_yang
.get()
916 vnf_uuid
= str(uuid4())
917 uuid_list
.append(vnf_uuid
)
918 vnfd_uuid_list
.append(vnf_uuid
)
919 vnfd_id
= get_str(vnfd
, "id", 255)
923 "name": get_str(vnfd
, "name", 255),
924 "description": get_str(vnfd
, "description", 255),
925 "tenant_id": tenant_id
,
926 "vendor": get_str(vnfd
, "vendor", 255),
927 "short_name": get_str(vnfd
, "short-name", 255),
928 "descriptor": str(vnf_descriptor
)[:60000]
931 for vnfd_descriptor
in vnfd_descriptor_list
:
932 if vnfd_descriptor
["id"] == str(vnfd
["id"]):
935 # table ip_profiles (ip-profiles)
936 ip_profile_name2db_table_index
= {}
937 for ip_profile
in vnfd
.get("ip-profiles").itervalues():
939 "ip_version": str(ip_profile
["ip-profile-params"].get("ip-version", "ipv4")),
940 "subnet_address": str(ip_profile
["ip-profile-params"].get("subnet-address")),
941 "gateway_address": str(ip_profile
["ip-profile-params"].get("gateway-address")),
942 "dhcp_enabled": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("enabled", True)),
943 "dhcp_start_address": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("start-address")),
944 "dhcp_count": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("count")),
947 for dns
in ip_profile
["ip-profile-params"]["dns-server"].itervalues():
948 dns_list
.append(str(dns
.get("address")))
949 db_ip_profile
["dns_address"] = ";".join(dns_list
)
950 if ip_profile
["ip-profile-params"].get('security-group'):
951 db_ip_profile
["security_group"] = ip_profile
["ip-profile-params"]['security-group']
952 ip_profile_name2db_table_index
[str(ip_profile
["name"])] = db_ip_profiles_index
953 db_ip_profiles_index
+= 1
954 db_ip_profiles
.append(db_ip_profile
)
956 # table nets (internal-vld)
957 net_id2uuid
= {} # for mapping interface with network
958 for vld
in vnfd
.get("internal-vld").itervalues():
959 net_uuid
= str(uuid4())
960 uuid_list
.append(net_uuid
)
962 "name": get_str(vld
, "name", 255),
965 "description": get_str(vld
, "description", 255),
966 "osm_id": get_str(vld
, "id", 255),
967 "type": "bridge", # TODO adjust depending on connection point type
969 net_id2uuid
[vld
.get("id")] = net_uuid
970 db_nets
.append(db_net
)
971 # ip-profile, link db_ip_profile with db_sce_net
972 if vld
.get("ip-profile-ref"):
973 ip_profile_name
= vld
.get("ip-profile-ref")
974 if ip_profile_name
not in ip_profile_name2db_table_index
:
975 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vld[{}]':'ip-profile-ref':"
976 "'{}'. Reference to a non-existing 'ip_profiles'".format(
977 str(vnfd
["id"]), str(vld
["id"]), str(vld
["ip-profile-ref"])),
978 httperrors
.Bad_Request
)
979 db_ip_profiles
[ip_profile_name2db_table_index
[ip_profile_name
]]["net_id"] = net_uuid
980 else: #check no ip-address has been defined
981 for icp
in vld
.get("internal-connection-point").itervalues():
982 if icp
.get("ip-address"):
983 raise NfvoException("Error at 'vnfd[{}]':'vld[{}]':'internal-connection-point[{}]' "
984 "contains an ip-address but no ip-profile has been defined at VLD".format(
985 str(vnfd
["id"]), str(vld
["id"]), str(icp
["id"])),
986 httperrors
.Bad_Request
)
988 # connection points vaiable declaration
989 cp_name2iface_uuid
= {}
991 cp_name2db_interface
= {}
995 vdu_id2db_table_index
= {}
996 for vdu
in vnfd
.get("vdu").itervalues():
998 for vdu_descriptor
in vnfd_descriptor
["vdu"]:
999 if vdu_descriptor
["id"] == str(vdu
["id"]):
1001 vm_uuid
= str(uuid4())
1002 uuid_list
.append(vm_uuid
)
1003 vdu_id
= get_str(vdu
, "id", 255)
1007 "name": get_str(vdu
, "name", 255),
1008 "description": get_str(vdu
, "description", 255),
1011 vdu_id2uuid
[db_vm
["osm_id"]] = vm_uuid
1012 vdu_id2db_table_index
[db_vm
["osm_id"]] = db_vms_index
1013 if vdu
.get("count"):
1014 db_vm
["count"] = int(vdu
["count"])
1017 image_present
= False
1018 if vdu
.get("image"):
1019 image_present
= True
1021 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, vdu
)
1023 image_uuid
= db_image
["uuid"]
1024 db_images
.append(db_image
)
1025 db_vm
["image_id"] = image_uuid
1026 if vdu
.get("alternative-images"):
1027 vm_alternative_images
= []
1028 for alt_image
in vdu
.get("alternative-images").itervalues():
1030 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, alt_image
)
1032 image_uuid
= db_image
["uuid"]
1033 db_images
.append(db_image
)
1034 vm_alternative_images
.append({
1035 "image_id": image_uuid
,
1036 "vim_type": str(alt_image
["vim-type"]),
1037 # "universal_name": str(alt_image["image"]),
1038 # "checksum": str(alt_image["image-checksum"]) if alt_image.get("image-checksum") else None
1041 db_vm
["image_list"] = yaml
.safe_dump(vm_alternative_images
, default_flow_style
=True, width
=256)
1045 if vdu
.get("volumes"):
1046 for volume_key
in vdu
["volumes"]:
1047 volume
= vdu
["volumes"][volume_key
]
1048 if not image_present
:
1049 # Convert the first volume to vnfc.image
1050 image_present
= True
1052 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, volume
)
1054 image_uuid
= db_image
["uuid"]
1055 db_images
.append(db_image
)
1056 db_vm
["image_id"] = image_uuid
1058 # Add Openmano devices
1059 device
= {"name": str(volume
.get("name"))}
1060 device
["type"] = str(volume
.get("device-type"))
1061 if volume
.get("size"):
1062 device
["size"] = int(volume
["size"])
1063 if volume
.get("image"):
1064 device
["image name"] = str(volume
["image"])
1065 if volume
.get("image-checksum"):
1066 device
["image checksum"] = str(volume
["image-checksum"])
1068 devices
.append(device
)
1072 if vdu
.get("cloud-init"):
1073 boot_data
["user-data"] = str(vdu
["cloud-init"])
1074 elif vdu
.get("cloud-init-file"):
1075 # TODO Where this file content is present???
1076 # boot_data["user-data"] = vnfd_yang.files[vdu["cloud-init-file"]]
1077 boot_data
["user-data"] = str(vdu
["cloud-init-file"])
1079 if vdu
.get("supplemental-boot-data"):
1080 if vdu
["supplemental-boot-data"].get('boot-data-drive'):
1081 boot_data
['boot-data-drive'] = True
1082 if vdu
["supplemental-boot-data"].get('config-file'):
1083 om_cfgfile_list
= list()
1084 for custom_config_file
in vdu
["supplemental-boot-data"]['config-file'].itervalues():
1085 # TODO Where this file content is present???
1086 cfg_source
= str(custom_config_file
["source"])
1087 om_cfgfile_list
.append({"dest": custom_config_file
["dest"],
1088 "content": cfg_source
})
1089 boot_data
['config-files'] = om_cfgfile_list
1091 db_vm
["boot_data"] = yaml
.safe_dump(boot_data
, default_flow_style
=True, width
=256)
1093 db_vms
.append(db_vm
)
1096 # table interfaces (internal/external interfaces)
1097 flavor_epa_interfaces
= []
1098 vdu_id2cp_name
= {} # stored only when one external connection point is presented at this VDU
1099 # for iface in chain(vdu.get("internal-interface").itervalues(), vdu.get("external-interface").itervalues()):
1100 for iface
in vdu
.get("interface").itervalues():
1101 flavor_epa_interface
= {}
1102 iface_uuid
= str(uuid4())
1103 uuid_list
.append(iface_uuid
)
1106 "internal_name": get_str(iface
, "name", 255),
1109 flavor_epa_interface
["name"] = db_interface
["internal_name"]
1110 if iface
.get("virtual-interface").get("vpci"):
1111 db_interface
["vpci"] = get_str(iface
.get("virtual-interface"), "vpci", 12)
1112 flavor_epa_interface
["vpci"] = db_interface
["vpci"]
1114 if iface
.get("virtual-interface").get("bandwidth"):
1115 bps
= int(iface
.get("virtual-interface").get("bandwidth"))
1116 db_interface
["bw"] = int(math
.ceil(bps
/1000000.0))
1117 flavor_epa_interface
["bandwidth"] = "{} Mbps".format(db_interface
["bw"])
1119 if iface
.get("virtual-interface").get("type") == "OM-MGMT":
1120 db_interface
["type"] = "mgmt"
1121 elif iface
.get("virtual-interface").get("type") in ("VIRTIO", "E1000"):
1122 db_interface
["type"] = "bridge"
1123 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1124 elif iface
.get("virtual-interface").get("type") in ("SR-IOV", "PCI-PASSTHROUGH"):
1125 db_interface
["type"] = "data"
1126 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1127 flavor_epa_interface
["dedicated"] = "no" if iface
["virtual-interface"]["type"] == "SR-IOV" \
1129 flavor_epa_interfaces
.append(flavor_epa_interface
)
1131 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vdu[{}]':'interface':'virtual"
1132 "-interface':'type':'{}'. Interface type is not supported".format(
1133 vnfd_id
, vdu_id
, iface
.get("virtual-interface").get("type")),
1134 httperrors
.Bad_Request
)
1136 if iface
.get("mgmt-interface"):
1137 db_interface
["type"] = "mgmt"
1139 if iface
.get("external-connection-point-ref"):
1141 cp
= vnfd
.get("connection-point")[iface
.get("external-connection-point-ref")]
1142 db_interface
["external_name"] = get_str(cp
, "name", 255)
1143 cp_name2iface_uuid
[db_interface
["external_name"]] = iface_uuid
1144 cp_name2vm_uuid
[db_interface
["external_name"]] = vm_uuid
1145 cp_name2db_interface
[db_interface
["external_name"]] = db_interface
1146 for cp_descriptor
in vnfd_descriptor
["connection-point"]:
1147 if cp_descriptor
["name"] == db_interface
["external_name"]:
1152 if vdu_id
in vdu_id2cp_name
:
1153 vdu_id2cp_name
[vdu_id
] = None # more than two connecdtion point for this VDU
1155 vdu_id2cp_name
[vdu_id
] = db_interface
["external_name"]
1158 if str(cp_descriptor
.get("port-security-enabled")).lower() == "false":
1159 db_interface
["port_security"] = 0
1160 elif str(cp_descriptor
.get("port-security-enabled")).lower() == "true":
1161 db_interface
["port_security"] = 1
1163 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1164 "'interface[{iface}]':'vnfd-connection-point-ref':'{cp}' is not present"
1165 " at connection-point".format(
1166 vnf
=vnfd_id
, vdu
=vdu_id
, iface
=iface
["name"],
1167 cp
=iface
.get("vnfd-connection-point-ref")),
1168 httperrors
.Bad_Request
)
1169 elif iface
.get("internal-connection-point-ref"):
1171 for icp_descriptor
in vdu_descriptor
["internal-connection-point"]:
1172 if icp_descriptor
["id"] == str(iface
.get("internal-connection-point-ref")):
1175 raise KeyError("does not exist at vdu:internal-connection-point")
1178 for vld
in vnfd
.get("internal-vld").itervalues():
1179 for cp
in vld
.get("internal-connection-point").itervalues():
1180 if cp
.get("id-ref") == iface
.get("internal-connection-point-ref"):
1182 raise KeyError("is referenced by more than one 'internal-vld'")
1186 raise KeyError("is not referenced by any 'internal-vld'")
1188 db_interface
["net_id"] = net_id2uuid
[icp_vld
.get("id")]
1189 if str(icp_descriptor
.get("port-security-enabled")).lower() == "false":
1190 db_interface
["port_security"] = 0
1191 elif str(icp_descriptor
.get("port-security-enabled")).lower() == "true":
1192 db_interface
["port_security"] = 1
1193 if icp
.get("ip-address"):
1194 if not icp_vld
.get("ip-profile-ref"):
1196 db_interface
["ip_address"] = str(icp
.get("ip-address"))
1197 except KeyError as e
:
1198 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1199 "'interface[{iface}]':'internal-connection-point-ref':'{cp}'"
1201 vnf
=vnfd_id
, vdu
=vdu_id
, iface
=iface
["name"],
1202 cp
=iface
.get("internal-connection-point-ref"), msg
=str(e
)),
1203 httperrors
.Bad_Request
)
1204 if iface
.get("position"):
1205 db_interface
["created_at"] = int(iface
.get("position")) * 50
1206 if iface
.get("mac-address"):
1207 db_interface
["mac"] = str(iface
.get("mac-address"))
1208 db_interfaces
.append(db_interface
)
1212 "name": get_str(vdu
, "name", 250) + "-flv",
1213 "vcpus": int(vdu
["vm-flavor"].get("vcpu-count", 1)),
1214 "ram": int(vdu
["vm-flavor"].get("memory-mb", 1)),
1215 "disk": int(vdu
["vm-flavor"].get("storage-gb", 0)),
1217 # TODO revise the case of several numa-node-policy node
1221 extended
["devices"] = devices
1222 if flavor_epa_interfaces
:
1223 numa
["interfaces"] = flavor_epa_interfaces
1224 if vdu
.get("guest-epa"): # TODO or dedicated_int:
1225 epa_vcpu_set
= False
1226 if vdu
["guest-epa"].get("numa-node-policy"): # TODO or dedicated_int:
1227 numa_node_policy
= vdu
["guest-epa"].get("numa-node-policy")
1228 if numa_node_policy
.get("node"):
1229 numa_node
= numa_node_policy
["node"].values()[0]
1230 if numa_node
.get("num-cores"):
1231 numa
["cores"] = numa_node
["num-cores"]
1233 if numa_node
.get("paired-threads"):
1234 if numa_node
["paired-threads"].get("num-paired-threads"):
1235 numa
["paired-threads"] = int(numa_node
["paired-threads"]["num-paired-threads"])
1237 if len(numa_node
["paired-threads"].get("paired-thread-ids")):
1238 numa
["paired-threads-id"] = []
1239 for pair
in numa_node
["paired-threads"]["paired-thread-ids"].itervalues():
1240 numa
["paired-threads-id"].append(
1241 (str(pair
["thread-a"]), str(pair
["thread-b"]))
1243 if numa_node
.get("num-threads"):
1244 numa
["threads"] = int(numa_node
["num-threads"])
1246 if numa_node
.get("memory-mb"):
1247 numa
["memory"] = max(int(numa_node
["memory-mb"] / 1024), 1)
1248 if vdu
["guest-epa"].get("mempage-size"):
1249 if vdu
["guest-epa"]["mempage-size"] != "SMALL":
1250 numa
["memory"] = max(int(db_flavor
["ram"] / 1024), 1)
1251 if vdu
["guest-epa"].get("cpu-pinning-policy") and not epa_vcpu_set
:
1252 if vdu
["guest-epa"]["cpu-pinning-policy"] == "DEDICATED":
1253 if vdu
["guest-epa"].get("cpu-thread-pinning-policy") and \
1254 vdu
["guest-epa"]["cpu-thread-pinning-policy"] != "PREFER":
1255 numa
["cores"] = max(db_flavor
["vcpus"], 1)
1257 numa
["threads"] = max(db_flavor
["vcpus"], 1)
1259 extended
["numas"] = [numa
]
1261 extended_text
= yaml
.safe_dump(extended
, default_flow_style
=True, width
=256)
1262 db_flavor
["extended"] = extended_text
1263 # look if flavor exist
1264 temp_flavor_dict
= {'disk': db_flavor
.get('disk', 0),
1265 'ram': db_flavor
.get('ram'),
1266 'vcpus': db_flavor
.get('vcpus'),
1267 'extended': db_flavor
.get('extended')
1269 existing_flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
1270 if existing_flavors
:
1271 flavor_uuid
= existing_flavors
[0]["uuid"]
1273 flavor_uuid
= str(uuid4())
1274 uuid_list
.append(flavor_uuid
)
1275 db_flavor
["uuid"] = flavor_uuid
1276 db_flavors
.append(db_flavor
)
1277 db_vm
["flavor_id"] = flavor_uuid
1279 # VNF affinity and antiaffinity
1280 for pg
in vnfd
.get("placement-groups").itervalues():
1281 pg_name
= get_str(pg
, "name", 255)
1282 for vdu
in pg
.get("member-vdus").itervalues():
1283 vdu_id
= get_str(vdu
, "member-vdu-ref", 255)
1284 if vdu_id
not in vdu_id2db_table_index
:
1285 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'placement-groups[{pg}]':"
1286 "'member-vdus':'{vdu}'. Reference to a non-existing vdu".format(
1287 vnf
=vnfd_id
, pg
=pg_name
, vdu
=vdu_id
),
1288 httperrors
.Bad_Request
)
1289 db_vms
[vdu_id2db_table_index
[vdu_id
]]["availability_zone"] = pg_name
1290 # TODO consider the case of isolation and not colocation
1291 # if pg.get("strategy") == "ISOLATION":
1293 # VNF mgmt configuration
1295 if vnfd
["mgmt-interface"].get("vdu-id"):
1296 mgmt_vdu_id
= get_str(vnfd
["mgmt-interface"], "vdu-id", 255)
1297 if mgmt_vdu_id
not in vdu_id2uuid
:
1298 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'vdu-id':"
1299 "'{vdu}'. Reference to a non-existing vdu".format(
1300 vnf
=vnfd_id
, vdu
=mgmt_vdu_id
),
1301 httperrors
.Bad_Request
)
1302 mgmt_access
["vm_id"] = vdu_id2uuid
[vnfd
["mgmt-interface"]["vdu-id"]]
1303 # if only one cp is defined by this VDU, mark this interface as of type "mgmt"
1304 if vdu_id2cp_name
.get(mgmt_vdu_id
):
1305 cp_name2db_interface
[vdu_id2cp_name
[mgmt_vdu_id
]]["type"] = "mgmt"
1307 if vnfd
["mgmt-interface"].get("ip-address"):
1308 mgmt_access
["ip-address"] = str(vnfd
["mgmt-interface"].get("ip-address"))
1309 if vnfd
["mgmt-interface"].get("cp"):
1310 if vnfd
["mgmt-interface"]["cp"] not in cp_name2iface_uuid
:
1311 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'cp':'{cp}'. "
1312 "Reference to a non-existing connection-point".format(
1313 vnf
=vnfd_id
, cp
=vnfd
["mgmt-interface"]["cp"]),
1314 httperrors
.Bad_Request
)
1315 mgmt_access
["vm_id"] = cp_name2vm_uuid
[vnfd
["mgmt-interface"]["cp"]]
1316 mgmt_access
["interface_id"] = cp_name2iface_uuid
[vnfd
["mgmt-interface"]["cp"]]
1317 # mark this interface as of type mgmt
1318 cp_name2db_interface
[vnfd
["mgmt-interface"]["cp"]]["type"] = "mgmt"
1320 default_user
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1324 mgmt_access
["default_user"] = default_user
1325 required
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1328 mgmt_access
["required"] = required
1331 db_vnf
["mgmt_access"] = yaml
.safe_dump(mgmt_access
, default_flow_style
=True, width
=256)
1333 db_vnfs
.append(db_vnf
)
1337 {"images": db_images
},
1338 {"flavors": db_flavors
},
1339 {"ip_profiles": db_ip_profiles
},
1341 {"interfaces": db_interfaces
},
1344 logger
.debug("create_vnf Deployment done vnfDict: %s",
1345 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
1346 mydb
.new_rows(db_tables
, uuid_list
)
1347 return vnfd_uuid_list
1348 except NfvoException
:
1350 except Exception as e
:
1351 logger
.error("Exception {}".format(e
))
1352 raise # NfvoException("Exception {}".format(e), httperrors.Bad_Request)
1355 @deprecated("Use new_vnfd_v3")
1356 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
1357 global global_config
1359 # Step 1. Check the VNF descriptor
1360 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
1361 # Step 2. Check tenant exist
1363 if tenant_id
!= "any":
1364 check_tenant(mydb
, tenant_id
)
1365 if "tenant_id" in vnf_descriptor
["vnf"]:
1366 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1367 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1368 httperrors
.Unauthorized
)
1370 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1371 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1372 if global_config
["auto_push_VNF_to_VIMs"]:
1373 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1375 # Step 4. Review the descriptor and add missing fields
1376 #print vnf_descriptor
1377 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1378 vnf_name
= vnf_descriptor
['vnf']['name']
1379 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1380 if "physical" in vnf_descriptor
['vnf']:
1381 del vnf_descriptor
['vnf']['physical']
1382 #print vnf_descriptor
1384 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1385 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1386 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1388 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1389 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1390 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1392 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1393 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1395 VNFCitem
["name"] = vnfc
['name']
1396 VNFCitem
["availability_zone"] = vnfc
.get('availability_zone')
1397 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
1399 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1402 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1403 myflavorDict
["description"] = VNFCitem
["description"]
1404 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1405 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1406 myflavorDict
["disk"] = vnfc
.get("disk", 0)
1407 myflavorDict
["extended"] = {}
1409 devices
= vnfc
.get("devices")
1411 myflavorDict
["extended"]["devices"] = devices
1414 # 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
1415 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1417 # Previous code has been commented
1418 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1419 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1420 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1421 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1423 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1425 # print "Error creating flavor: unknown processor model. Rollback successful."
1426 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1428 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1429 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1431 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1432 myflavorDict
['extended']['numas'] = vnfc
['numas']
1436 # Step 6.2 New flavors are created in the VIM
1437 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1439 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1440 VNFCitem
["flavor_id"] = flavor_id
1441 VNFCDict
[vnfc
['name']] = VNFCitem
1443 logger
.debug("Creating new images in the VIM for each VNFC")
1444 # Step 6.3 New images are created in the VIM
1445 #For each VNFC, we must create the appropriate image.
1446 #This "for" loop might be integrated with the previous one
1447 #In case this integration is made, the VNFCDict might become a VNFClist.
1448 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1449 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1451 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1452 image_dict
['universal_name']=vnfc
.get('image name')
1453 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1454 image_dict
['location']=vnfc
.get('VNFC image')
1455 #image_dict['new_location']=vnfc.get('image location')
1456 image_dict
['checksum']=vnfc
.get('image checksum')
1457 image_metadata_dict
= vnfc
.get('image metadata', None)
1458 image_metadata_str
= None
1459 if image_metadata_dict
is not None:
1460 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1461 image_dict
['metadata']=image_metadata_str
1462 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1463 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1464 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1465 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1466 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1467 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1468 if vnfc
.get("boot-data"):
1469 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1472 # Step 7. Storing the VNF descriptor in the repository
1473 if "descriptor" not in vnf_descriptor
["vnf"]:
1474 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1476 # Step 8. Adding the VNF to the NFVO DB
1477 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1479 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1480 _
, message
= rollback(mydb
, vims
, rollback_list
)
1481 if isinstance(e
, db_base_Exception
):
1482 error_text
= "Exception at database"
1483 elif isinstance(e
, KeyError):
1484 error_text
= "KeyError exception "
1485 e
.http_code
= httperrors
.Internal_Server_Error
1487 error_text
= "Exception at VIM"
1488 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1489 #logger.error("start_scenario %s", error_text)
1490 raise NfvoException(error_text
, e
.http_code
)
1493 @deprecated("Use new_vnfd_v3")
1494 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
1495 global global_config
1497 # Step 1. Check the VNF descriptor
1498 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
1499 # Step 2. Check tenant exist
1501 if tenant_id
!= "any":
1502 check_tenant(mydb
, tenant_id
)
1503 if "tenant_id" in vnf_descriptor
["vnf"]:
1504 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1505 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1506 httperrors
.Unauthorized
)
1508 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1509 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1510 if global_config
["auto_push_VNF_to_VIMs"]:
1511 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1513 # Step 4. Review the descriptor and add missing fields
1514 #print vnf_descriptor
1515 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1516 vnf_name
= vnf_descriptor
['vnf']['name']
1517 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1518 if "physical" in vnf_descriptor
['vnf']:
1519 del vnf_descriptor
['vnf']['physical']
1520 #print vnf_descriptor
1522 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1523 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1524 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1526 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1527 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1528 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1530 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1531 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1533 VNFCitem
["name"] = vnfc
['name']
1534 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
1536 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1539 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1540 myflavorDict
["description"] = VNFCitem
["description"]
1541 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1542 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1543 myflavorDict
["disk"] = vnfc
.get("disk", 0)
1544 myflavorDict
["extended"] = {}
1546 devices
= vnfc
.get("devices")
1548 myflavorDict
["extended"]["devices"] = devices
1551 # 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
1552 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1554 # Previous code has been commented
1555 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1556 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1557 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1558 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1560 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1562 # print "Error creating flavor: unknown processor model. Rollback successful."
1563 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1565 # return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1566 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1568 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1569 myflavorDict
['extended']['numas'] = vnfc
['numas']
1573 # Step 6.2 New flavors are created in the VIM
1574 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1576 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1577 VNFCitem
["flavor_id"] = flavor_id
1578 VNFCDict
[vnfc
['name']] = VNFCitem
1580 logger
.debug("Creating new images in the VIM for each VNFC")
1581 # Step 6.3 New images are created in the VIM
1582 #For each VNFC, we must create the appropriate image.
1583 #This "for" loop might be integrated with the previous one
1584 #In case this integration is made, the VNFCDict might become a VNFClist.
1585 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1586 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1588 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1589 image_dict
['universal_name']=vnfc
.get('image name')
1590 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1591 image_dict
['location']=vnfc
.get('VNFC image')
1592 #image_dict['new_location']=vnfc.get('image location')
1593 image_dict
['checksum']=vnfc
.get('image checksum')
1594 image_metadata_dict
= vnfc
.get('image metadata', None)
1595 image_metadata_str
= None
1596 if image_metadata_dict
is not None:
1597 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1598 image_dict
['metadata']=image_metadata_str
1599 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1600 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1601 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1602 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1603 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1604 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1605 if vnfc
.get("boot-data"):
1606 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1608 # Step 7. Storing the VNF descriptor in the repository
1609 if "descriptor" not in vnf_descriptor
["vnf"]:
1610 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1612 # Step 8. Adding the VNF to the NFVO DB
1613 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1615 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1616 _
, message
= rollback(mydb
, vims
, rollback_list
)
1617 if isinstance(e
, db_base_Exception
):
1618 error_text
= "Exception at database"
1619 elif isinstance(e
, KeyError):
1620 error_text
= "KeyError exception "
1621 e
.http_code
= httperrors
.Internal_Server_Error
1623 error_text
= "Exception at VIM"
1624 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1625 #logger.error("start_scenario %s", error_text)
1626 raise NfvoException(error_text
, e
.http_code
)
1629 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
1630 #check valid tenant_id
1631 check_tenant(mydb
, tenant_id
)
1634 if tenant_id
!= "any":
1635 where_or
["tenant_id"] = tenant_id
1636 where_or
["public"] = True
1637 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1639 vnf_id
= vnf
["uuid"]
1640 filter_keys
= ('uuid', 'name', 'description', 'public', "tenant_id", "osm_id", "created_at")
1641 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
1642 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
1643 data
={'vnf' : filtered_content
}
1645 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
1646 SELECT
=('vms.uuid as uuid', 'vms.osm_id as osm_id', 'vms.name as name', 'vms.description as description',
1648 WHERE
={'vnfs.uuid': vnf_id
} )
1650 raise NfvoException("vnf '{}' not found".format(vnf_id
), httperrors
.Not_Found
)
1651 # change boot_data into boot-data
1653 if vm
.get("boot_data"):
1654 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
1657 data
['vnf']['VNFC'] = content
1658 #TODO: GET all the information from a VNFC and include it in the output.
1661 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
1662 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
1663 WHERE
={'vnfs.uuid': vnf_id
} )
1664 data
['vnf']['nets'] = content
1666 #GET ip-profile for each net
1667 for net
in data
['vnf']['nets']:
1668 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1669 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1670 WHERE
={'net_id': net
["uuid"]} )
1671 if len(ipprofiles
)==1:
1672 net
["ip_profile"] = ipprofiles
[0]
1673 elif len(ipprofiles
)>1:
1674 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), httperrors
.Bad_Request
)
1677 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1679 #GET External Interfaces
1680 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1681 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1682 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1683 WHERE
={'vnfs.uuid': vnf_id
, 'interfaces.external_name<>': None} )
1685 data
['vnf']['external-connections'] = content
1690 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1691 # Check tenant exist
1692 if tenant_id
!= "any":
1693 check_tenant(mydb
, tenant_id
)
1694 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1695 vims
= get_vim(mydb
, tenant_id
, ignore_errors
=True)
1699 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1701 if tenant_id
!= "any":
1702 where_or
["tenant_id"] = tenant_id
1703 where_or
["public"] = True
1704 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1705 vnf_id
= vnf
["uuid"]
1707 # "Getting the list of flavors and tenants of the VNF"
1708 flavorList
= get_flavorlist(mydb
, vnf_id
)
1709 if len(flavorList
)==0:
1710 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1712 imageList
= get_imagelist(mydb
, vnf_id
)
1713 if len(imageList
)==0:
1714 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1716 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1718 raise NfvoException("vnf '{}' not found".format(vnf_id
), httperrors
.Not_Found
)
1721 for flavor
in flavorList
:
1722 #check if flavor is used by other vnf
1724 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1726 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1728 #flavor not used, must be deleted
1730 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id': flavor
})
1731 for flavor_vim
in c
:
1732 if not flavor_vim
['created']: # skip this flavor because not created by openmano
1736 for vim
in vims
.values():
1737 if vim
["config"]["datacenter_tenant_id"] == flavor_vim
["datacenter_vim_id"]:
1743 myvim
.delete_flavor(flavor_vim
["vim_id"])
1744 except vimconn
.vimconnNotFoundException
:
1745 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"],
1746 flavor_vim
["datacenter_vim_id"] )
1747 except vimconn
.vimconnException
as e
:
1748 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1749 flavor_vim
["vim_id"], flavor_vim
["datacenter_vim_id"], type(e
).__name
__, str(e
))
1750 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"],
1751 flavor_vim
["datacenter_vim_id"]))
1752 # delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1753 mydb
.delete_row_by_id('flavors', flavor
)
1754 except db_base_Exception
as e
:
1755 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1756 undeletedItems
.append("flavor {}".format(flavor
))
1759 for image
in imageList
:
1761 #check if image is used by other vnf
1762 c
= mydb
.get_rows(FROM
='vms', WHERE
=[{'image_id': image
}, {'image_list LIKE ': '%' + image
+ '%'}])
1764 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1766 #image not used, must be deleted
1768 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1770 if image_vim
["datacenter_vim_id"] not in vims
: # TODO change to datacenter_tenant_id
1772 if image_vim
['created']=='false': #skip this image because not created by openmano
1774 myvim
=vims
[ image_vim
["datacenter_id"] ]
1776 myvim
.delete_image(image_vim
["vim_id"])
1777 except vimconn
.vimconnNotFoundException
as e
:
1778 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1779 except vimconn
.vimconnException
as e
:
1780 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1781 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1782 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1783 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1784 mydb
.delete_row_by_id('images', image
)
1785 except db_base_Exception
as e
:
1786 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1787 undeletedItems
.append("image %s" % image
)
1789 return vnf_id
+ " " + vnf
["name"]
1791 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1794 @deprecated("Not used")
1795 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1796 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1800 return -httperrors
.Not_Found
, "datacenter '%s' not found" % datacenter_name
1801 myvim
= vims
.values()[0]
1802 result
,servers
= myvim
.get_hosts_info()
1804 return result
, servers
1805 topology
= {'name':myvim
['name'] , 'servers': servers
}
1806 return result
, topology
1809 def get_hosts(mydb
, nfvo_tenant_id
):
1810 vims
= get_vim(mydb
, nfvo_tenant_id
)
1812 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), httperrors
.Not_Found
)
1814 #print "nfvo.datacenter_action() error. Several datacenters found"
1815 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
1816 myvim
= vims
.values()[0]
1818 hosts
= myvim
.get_hosts()
1819 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1821 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1823 server
={'name':host
['name'], 'vms':[]}
1824 for vm
in host
['instances']:
1825 #get internal name and model
1827 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1828 WHERE
={'vim_vm_id':vm
['id']} )
1830 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1832 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1834 except db_base_Exception
as e
:
1835 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1836 datacenter
['Datacenters'][0]['servers'].append(server
)
1837 #return -400, "en construccion"
1839 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1841 except vimconn
.vimconnException
as e
:
1842 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1845 @deprecated("Use new_nsd_v3")
1846 def new_scenario(mydb
, tenant_id
, topo
):
1848 # result, vims = get_vim(mydb, tenant_id)
1850 # return result, vims
1852 if tenant_id
!= "any":
1853 check_tenant(mydb
, tenant_id
)
1854 if "tenant_id" in topo
:
1855 if topo
["tenant_id"] != tenant_id
:
1856 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1857 httperrors
.Unauthorized
)
1861 #1.1: get VNFs and external_networks (other_nets).
1863 other_nets
={} #external_networks, bridge_networks and data_networkds
1864 nodes
= topo
['topology']['nodes']
1865 for k
in nodes
.keys():
1866 if nodes
[k
]['type'] == 'VNF':
1868 vnfs
[k
]['ifaces'] = {}
1869 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1870 other_nets
[k
] = nodes
[k
]
1871 other_nets
[k
]['external']=True
1872 elif nodes
[k
]['type'] == 'network':
1873 other_nets
[k
] = nodes
[k
]
1874 other_nets
[k
]['external']=False
1877 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1878 for name
,vnf
in vnfs
.items():
1879 where
= {"OR": {"tenant_id": tenant_id
, 'public': "true"}}
1881 error_pos
= "'topology':'nodes':'" + name
+ "'"
1883 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1884 where
['uuid'] = vnf
['vnf_id']
1885 if 'VNF model' in vnf
:
1886 error_text
+= " 'VNF model' " + vnf
['VNF model']
1887 where
['name'] = vnf
['VNF model']
1889 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, httperrors
.Bad_Request
)
1891 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1895 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, httperrors
.Not_Found
)
1897 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", httperrors
.Conflict
)
1898 vnf
['uuid']=vnf_db
[0]['uuid']
1899 vnf
['description']=vnf_db
[0]['description']
1900 #get external interfaces
1901 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1902 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1903 WHERE
={'vnfs.uuid':vnf
['uuid'], 'external_name<>': None} )
1904 for ext_iface
in ext_ifaces
:
1905 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1907 #1.4 get list of connections
1908 conections
= topo
['topology']['connections']
1909 conections_list
= []
1910 conections_list_name
= []
1911 for k
in conections
.keys():
1912 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1913 ifaces_list
= conections
[k
]['nodes'].items()
1914 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1916 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1917 for k2
in conection_pair_list
:
1920 con_type
= conections
[k
].get("type", "link")
1921 if con_type
!= "link":
1923 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), httperrors
.Bad_Request
)
1924 other_nets
[k
] = {'external': False}
1925 if conections
[k
].get("graph"):
1926 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1927 ifaces_list
.append( (k
, None) )
1930 if con_type
== "external_network":
1931 other_nets
[k
]['external'] = True
1932 if conections
[k
].get("model"):
1933 other_nets
[k
]["model"] = conections
[k
]["model"]
1935 other_nets
[k
]["model"] = k
1936 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1937 other_nets
[k
]["model"] = con_type
1939 conections_list_name
.append(k
)
1940 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)
1941 #print set(ifaces_list)
1942 #check valid VNF and iface names
1943 for iface
in ifaces_list
:
1944 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1945 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1946 str(k
), iface
[0]), httperrors
.Not_Found
)
1947 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1948 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1949 str(k
), iface
[0], iface
[1]), httperrors
.Not_Found
)
1951 #1.5 unify connections from the pair list to a consolidated list
1953 while index
< len(conections_list
):
1955 while index2
< len(conections_list
):
1956 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1957 conections_list
[index
] |
= conections_list
[index2
]
1958 del conections_list
[index2
]
1959 del conections_list_name
[index2
]
1962 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1964 #for k in conections_list:
1969 #1.6 Delete non external nets
1970 # for k in other_nets.keys():
1971 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1972 # for con in conections_list:
1974 # for index in range(0,len(con)):
1975 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1976 # for index in delete_indexes:
1979 #1.7: Check external_ports are present at database table datacenter_nets
1980 for k
,net
in other_nets
.items():
1981 error_pos
= "'topology':'nodes':'" + k
+ "'"
1982 if net
['external']==False:
1983 if 'name' not in net
:
1985 if 'model' not in net
:
1986 raise NfvoException("needed a 'model' at " + error_pos
, httperrors
.Bad_Request
)
1987 if net
['model']=='bridge_net':
1988 net
['type']='bridge';
1989 elif net
['model']=='dataplane_net':
1992 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, httperrors
.Not_Found
)
1994 #IF we do not want to check that external network exist at datacenter
1999 # if 'net_id' in net:
2000 # error_text += " 'net_id' " + net['net_id']
2001 # WHERE_['uuid'] = net['net_id']
2002 # if 'model' in net:
2003 # error_text += " 'model' " + net['model']
2004 # WHERE_['name'] = net['model']
2005 # if len(WHERE_) == 0:
2006 # return -httperrors.Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
2007 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
2008 # FROM='datacenter_nets', WHERE=WHERE_ )
2010 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
2012 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
2013 # return -httperrors.Bad_Request, "unknown " +error_text+ " at " + error_pos
2015 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
2016 # return -httperrors.Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
2017 # other_nets[k].update(net_db[0])
2020 net_nb
=0 #Number of nets
2021 for con
in conections_list
:
2022 #check if this is connected to a external net
2026 for index
in range(0,len(con
)):
2027 #check if this is connected to a external net
2028 for net_key
in other_nets
.keys():
2029 if con
[index
][0]==net_key
:
2030 if other_net_index
>=0:
2031 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
2032 #print "nfvo.new_scenario " + error_text
2033 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2035 other_net_index
= index
2036 net_target
= net_key
2038 #print "other_net_index", other_net_index
2040 if other_net_index
>=0:
2041 del con
[other_net_index
]
2042 #IF we do not want to check that external network exist at datacenter
2043 if other_nets
[net_target
]['external'] :
2044 if "name" not in other_nets
[net_target
]:
2045 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
2046 if other_nets
[net_target
]["type"] == "external_network":
2047 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
2048 other_nets
[net_target
]["type"] = "data"
2050 other_nets
[net_target
]["type"] = "bridge"
2052 # if other_nets[net_target]['external'] :
2053 # 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
2054 # if type_=='data' and other_nets[net_target]['type']=="ptp":
2055 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
2056 # print "nfvo.new_scenario " + error_text
2057 # return -httperrors.Bad_Request, error_text
2060 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
2063 net_type_bridge
=False
2065 net_target
= "__-__net"+str(net_nb
)
2066 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
2067 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
2070 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
2071 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
2072 if iface_type
=='mgmt' or iface_type
=='bridge':
2073 net_type_bridge
= True
2075 net_type_data
= True
2076 if net_type_bridge
and net_type_data
:
2077 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
2078 #print "nfvo.new_scenario " + error_text
2079 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2080 elif net_type_bridge
:
2083 type_
='data' if len(con
)>2 else 'ptp'
2084 net_list
[net_target
]['type'] = type_
2087 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
2088 #print "nfvo.new_scenario " + error_text
2090 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2092 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
2093 #1.8.1 obtain management net
2094 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
2095 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
2096 #1.8.2 check all interfaces from all vnfs
2098 add_mgmt_net
= False
2099 for vnf
in vnfs
.values():
2100 for iface
in vnf
['ifaces'].values():
2101 if iface
['type']=='mgmt' and 'net_key' not in iface
:
2102 #iface not connected
2103 iface
['net_key'] = 'mgmt'
2105 if add_mgmt_net
and 'mgmt' not in net_list
:
2106 net_list
['mgmt']=mgmt_net
[0]
2107 net_list
['mgmt']['external']=True
2108 net_list
['mgmt']['graph']={'visible':False}
2110 net_list
.update(other_nets
)
2112 #print 'net_list', net_list
2117 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
2118 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
2119 'tenant_id':tenant_id
, 'name':topo
['name'],
2120 'description':topo
.get('description',topo
['name']),
2121 'public': topo
.get('public', False)
2127 @deprecated("Use new_nsd_v3")
2128 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
2129 """ This creates a new scenario for version 0.2 and 0.3"""
2130 scenario
= scenario_dict
["scenario"]
2131 if tenant_id
!= "any":
2132 check_tenant(mydb
, tenant_id
)
2133 if "tenant_id" in scenario
:
2134 if scenario
["tenant_id"] != tenant_id
:
2135 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
2136 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
2137 scenario
["tenant_id"], tenant_id
), httperrors
.Unauthorized
)
2141 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
2142 for name
,vnf
in scenario
["vnfs"].iteritems():
2143 where
= {"OR": {"tenant_id": tenant_id
, 'public': "true"}}
2145 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
2147 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
2148 where
['uuid'] = vnf
['vnf_id']
2149 if 'vnf_name' in vnf
:
2150 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
2151 where
['name'] = vnf
['vnf_name']
2153 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, httperrors
.Bad_Request
)
2154 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
2157 if len(vnf_db
) == 0:
2158 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, httperrors
.Not_Found
)
2159 elif len(vnf_db
) > 1:
2160 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", httperrors
.Conflict
)
2161 vnf
['uuid'] = vnf_db
[0]['uuid']
2162 vnf
['description'] = vnf_db
[0]['description']
2164 # get external interfaces
2165 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
2166 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
2167 WHERE
={'vnfs.uuid':vnf
['uuid'], 'external_name<>': None} )
2168 for ext_iface
in ext_ifaces
:
2169 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
2170 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
2172 # 2: Insert net_key and ip_address at every vnf interface
2173 for net_name
, net
in scenario
["networks"].items():
2174 net_type_bridge
= False
2175 net_type_data
= False
2176 for iface_dict
in net
["interfaces"]:
2177 if version
== "0.2":
2178 temp_dict
= iface_dict
2180 elif version
== "0.3":
2181 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
2182 ip_address
= iface_dict
.get('ip_address', None)
2183 for vnf
, iface
in temp_dict
.items():
2184 if vnf
not in scenario
["vnfs"]:
2185 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
2187 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2188 raise NfvoException(error_text
, httperrors
.Not_Found
)
2189 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
2190 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
2191 .format(net_name
, iface
)
2192 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2193 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2194 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
2195 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
2196 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
2197 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2198 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2199 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
2200 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
2201 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
2202 if iface_type
== 'mgmt' or iface_type
== 'bridge':
2203 net_type_bridge
= True
2205 net_type_data
= True
2207 if net_type_bridge
and net_type_data
:
2208 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
2210 # logger.debug("nfvo.new_scenario " + error_text)
2211 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2212 elif net_type_bridge
:
2215 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
2217 if net
.get("implementation"): # for v0.3
2218 if type_
== "bridge" and net
["implementation"] == "underlay":
2219 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
2220 "'network':'{}'".format(net_name
)
2221 # logger.debug(error_text)
2222 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2223 elif type_
!= "bridge" and net
["implementation"] == "overlay":
2224 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
2225 "'network':'{}'".format(net_name
)
2226 # logger.debug(error_text)
2227 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2228 net
.pop("implementation")
2229 if "type" in net
and version
== "0.3": # for v0.3
2230 if type_
== "data" and net
["type"] == "e-line":
2231 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
2232 "'e-line' at 'network':'{}'".format(net_name
)
2233 # logger.debug(error_text)
2234 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2235 elif type_
== "ptp" and net
["type"] == "e-lan":
2239 net
['name'] = net_name
2240 net
['external'] = net
.get('external', False)
2242 # 3: insert at database
2243 scenario
["nets"] = scenario
["networks"]
2244 scenario
['tenant_id'] = tenant_id
2245 scenario_id
= mydb
.new_scenario(scenario
)
2249 def new_nsd_v3(mydb
, tenant_id
, nsd_descriptor
):
2251 Parses an OSM IM nsd_catalog and insert at DB
2254 :param nsd_descriptor:
2255 :return: The list of created NSD ids
2258 mynsd
= nsd_catalog
.nsd()
2260 pybindJSONDecoder
.load_ietf_json(nsd_descriptor
, None, None, obj
=mynsd
)
2261 except Exception as e
:
2262 raise NfvoException("Error. Invalid NS descriptor format: " + str(e
), httperrors
.Bad_Request
)
2266 db_sce_interfaces
= []
2269 db_sce_rsp_hops
= []
2270 db_sce_classifiers
= []
2271 db_sce_classifier_matches
= []
2273 db_ip_profiles_index
= 0
2276 for nsd_yang
in mynsd
.nsd_catalog
.nsd
.itervalues():
2277 nsd
= nsd_yang
.get()
2280 scenario_uuid
= str(uuid4())
2281 uuid_list
.append(scenario_uuid
)
2282 nsd_uuid_list
.append(scenario_uuid
)
2284 "uuid": scenario_uuid
,
2285 "osm_id": get_str(nsd
, "id", 255),
2286 "name": get_str(nsd
, "name", 255),
2287 "description": get_str(nsd
, "description", 255),
2288 "tenant_id": tenant_id
,
2289 "vendor": get_str(nsd
, "vendor", 255),
2290 "short_name": get_str(nsd
, "short-name", 255),
2291 "descriptor": str(nsd_descriptor
)[:60000],
2293 db_scenarios
.append(db_scenario
)
2295 # table sce_vnfs (constituent-vnfd)
2296 vnf_index2scevnf_uuid
= {}
2297 vnf_index2vnf_uuid
= {}
2298 for vnf
in nsd
.get("constituent-vnfd").itervalues():
2299 existing_vnf
= mydb
.get_rows(FROM
="vnfs", WHERE
={'osm_id': str(vnf
["vnfd-id-ref"])[:255],
2300 'tenant_id': tenant_id
})
2301 if not existing_vnf
:
2302 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'constituent-vnfd':'vnfd-id-ref':"
2303 "'{}'. Reference to a non-existing VNFD in the catalog".format(
2304 str(nsd
["id"]), str(vnf
["vnfd-id-ref"])[:255]),
2305 httperrors
.Bad_Request
)
2306 sce_vnf_uuid
= str(uuid4())
2307 uuid_list
.append(sce_vnf_uuid
)
2309 "uuid": sce_vnf_uuid
,
2310 "scenario_id": scenario_uuid
,
2311 # "name": get_str(vnf, "member-vnf-index", 255),
2312 "name": existing_vnf
[0]["name"][:200] + "." + get_str(vnf
, "member-vnf-index", 50),
2313 "vnf_id": existing_vnf
[0]["uuid"],
2314 "member_vnf_index": str(vnf
["member-vnf-index"]),
2315 # TODO 'start-by-default': True
2317 vnf_index2scevnf_uuid
[str(vnf
['member-vnf-index'])] = sce_vnf_uuid
2318 vnf_index2vnf_uuid
[str(vnf
['member-vnf-index'])] = existing_vnf
[0]["uuid"]
2319 db_sce_vnfs
.append(db_sce_vnf
)
2321 # table ip_profiles (ip-profiles)
2322 ip_profile_name2db_table_index
= {}
2323 for ip_profile
in nsd
.get("ip-profiles").itervalues():
2325 "ip_version": str(ip_profile
["ip-profile-params"].get("ip-version", "ipv4")),
2326 "subnet_address": str(ip_profile
["ip-profile-params"].get("subnet-address")),
2327 "gateway_address": str(ip_profile
["ip-profile-params"].get("gateway-address")),
2328 "dhcp_enabled": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("enabled", True)),
2329 "dhcp_start_address": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("start-address")),
2330 "dhcp_count": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("count")),
2333 for dns
in ip_profile
["ip-profile-params"]["dns-server"].itervalues():
2334 dns_list
.append(str(dns
.get("address")))
2335 db_ip_profile
["dns_address"] = ";".join(dns_list
)
2336 if ip_profile
["ip-profile-params"].get('security-group'):
2337 db_ip_profile
["security_group"] = ip_profile
["ip-profile-params"]['security-group']
2338 ip_profile_name2db_table_index
[str(ip_profile
["name"])] = db_ip_profiles_index
2339 db_ip_profiles_index
+= 1
2340 db_ip_profiles
.append(db_ip_profile
)
2342 # table sce_nets (internal-vld)
2343 for vld
in nsd
.get("vld").itervalues():
2344 sce_net_uuid
= str(uuid4())
2345 uuid_list
.append(sce_net_uuid
)
2347 "uuid": sce_net_uuid
,
2348 "name": get_str(vld
, "name", 255),
2349 "scenario_id": scenario_uuid
,
2351 "multipoint": not vld
.get("type") == "ELINE",
2352 "osm_id": get_str(vld
, "id", 255),
2354 "description": get_str(vld
, "description", 255),
2356 # guess type of network
2357 if vld
.get("mgmt-network"):
2358 db_sce_net
["type"] = "bridge"
2359 db_sce_net
["external"] = True
2360 elif vld
.get("provider-network").get("overlay-type") == "VLAN":
2361 db_sce_net
["type"] = "data"
2363 # later on it will be fixed to bridge or data depending on the type of interfaces attached to it
2364 db_sce_net
["type"] = None
2365 db_sce_nets
.append(db_sce_net
)
2367 # ip-profile, link db_ip_profile with db_sce_net
2368 if vld
.get("ip-profile-ref"):
2369 ip_profile_name
= vld
.get("ip-profile-ref")
2370 if ip_profile_name
not in ip_profile_name2db_table_index
:
2371 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'ip-profile-ref':'{}'."
2372 " Reference to a non-existing 'ip_profiles'".format(
2373 str(nsd
["id"]), str(vld
["id"]), str(vld
["ip-profile-ref"])),
2374 httperrors
.Bad_Request
)
2375 db_ip_profiles
[ip_profile_name2db_table_index
[ip_profile_name
]]["sce_net_id"] = sce_net_uuid
2376 elif vld
.get("vim-network-name"):
2377 db_sce_net
["vim_network_name"] = get_str(vld
, "vim-network-name", 255)
2379 # table sce_interfaces (vld:vnfd-connection-point-ref)
2380 for iface
in vld
.get("vnfd-connection-point-ref").itervalues():
2381 vnf_index
= str(iface
['member-vnf-index-ref'])
2382 # check correct parameters
2383 if vnf_index
not in vnf_index2vnf_uuid
:
2384 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2385 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2386 "'nsd':'constituent-vnfd'".format(
2387 str(nsd
["id"]), str(vld
["id"]), str(iface
["member-vnf-index-ref"])),
2388 httperrors
.Bad_Request
)
2390 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid', 'i.type as iface_type'),
2391 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2392 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2393 'external_name': get_str(iface
, "vnfd-connection-point-ref",
2395 if not existing_ifaces
:
2396 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2397 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2398 "connection-point name at VNFD '{}'".format(
2399 str(nsd
["id"]), str(vld
["id"]), str(iface
["vnfd-connection-point-ref"]),
2400 str(iface
.get("vnfd-id-ref"))[:255]),
2401 httperrors
.Bad_Request
)
2402 interface_uuid
= existing_ifaces
[0]["uuid"]
2403 if existing_ifaces
[0]["iface_type"] == "data" and not db_sce_net
["type"]:
2404 db_sce_net
["type"] = "data"
2405 sce_interface_uuid
= str(uuid4())
2406 uuid_list
.append(sce_net_uuid
)
2407 iface_ip_address
= None
2408 if iface
.get("ip-address"):
2409 iface_ip_address
= str(iface
.get("ip-address"))
2410 db_sce_interface
= {
2411 "uuid": sce_interface_uuid
,
2412 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2413 "sce_net_id": sce_net_uuid
,
2414 "interface_id": interface_uuid
,
2415 "ip_address": iface_ip_address
,
2417 db_sce_interfaces
.append(db_sce_interface
)
2418 if not db_sce_net
["type"]:
2419 db_sce_net
["type"] = "bridge"
2421 # table sce_vnffgs (vnffgd)
2422 for vnffg
in nsd
.get("vnffgd").itervalues():
2423 sce_vnffg_uuid
= str(uuid4())
2424 uuid_list
.append(sce_vnffg_uuid
)
2426 "uuid": sce_vnffg_uuid
,
2427 "name": get_str(vnffg
, "name", 255),
2428 "scenario_id": scenario_uuid
,
2429 "vendor": get_str(vnffg
, "vendor", 255),
2430 "description": get_str(vld
, "description", 255),
2432 db_sce_vnffgs
.append(db_sce_vnffg
)
2436 for rsp
in vnffg
.get("rsp").itervalues():
2437 sce_rsp_uuid
= str(uuid4())
2438 uuid_list
.append(sce_rsp_uuid
)
2440 "uuid": sce_rsp_uuid
,
2441 "name": get_str(rsp
, "name", 255),
2442 "sce_vnffg_id": sce_vnffg_uuid
,
2443 "id": get_str(rsp
, "id", 255), # only useful to link with classifiers; will be removed later in the code
2445 db_sce_rsps
.append(db_sce_rsp
)
2446 db_sce_rsp_hops
= []
2447 for iface
in rsp
.get("vnfd-connection-point-ref").itervalues():
2448 vnf_index
= str(iface
['member-vnf-index-ref'])
2449 if_order
= int(iface
['order'])
2450 # check correct parameters
2451 if vnf_index
not in vnf_index2vnf_uuid
:
2452 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2453 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2454 "'nsd':'constituent-vnfd'".format(
2455 str(nsd
["id"]), str(rsp
["id"]), str(iface
["member-vnf-index-ref"])),
2456 httperrors
.Bad_Request
)
2458 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2459 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2460 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2461 'external_name': get_str(iface
, "vnfd-connection-point-ref",
2463 if not existing_ifaces
:
2464 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2465 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2466 "connection-point name at VNFD '{}'".format(
2467 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-connection-point-ref"]),
2468 str(iface
.get("vnfd-id-ref"))[:255]),
2469 httperrors
.Bad_Request
)
2470 interface_uuid
= existing_ifaces
[0]["uuid"]
2471 sce_rsp_hop_uuid
= str(uuid4())
2472 uuid_list
.append(sce_rsp_hop_uuid
)
2474 "uuid": sce_rsp_hop_uuid
,
2475 "if_order": if_order
,
2476 "interface_id": interface_uuid
,
2477 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2478 "sce_rsp_id": sce_rsp_uuid
,
2480 db_sce_rsp_hops
.append(db_sce_rsp_hop
)
2482 # deal with classifiers
2483 db_sce_classifiers
= []
2484 for classifier
in vnffg
.get("classifier").itervalues():
2485 sce_classifier_uuid
= str(uuid4())
2486 uuid_list
.append(sce_classifier_uuid
)
2489 vnf_index
= str(classifier
['member-vnf-index-ref'])
2490 if vnf_index
not in vnf_index2vnf_uuid
:
2491 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'classifier[{}]':'vnfd-connection-point"
2492 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2493 "'nsd':'constituent-vnfd'".format(
2494 str(nsd
["id"]), str(classifier
["id"]), str(classifier
["member-vnf-index-ref"])),
2495 httperrors
.Bad_Request
)
2496 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2497 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2498 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2499 'external_name': get_str(classifier
, "vnfd-connection-point-ref",
2501 if not existing_ifaces
:
2502 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
2503 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2504 "connection-point name at VNFD '{}'".format(
2505 str(nsd
["id"]), str(rsp
["id"]), str(iface
["vnfd-connection-point-ref"]),
2506 str(iface
.get("vnfd-id-ref"))[:255]),
2507 httperrors
.Bad_Request
)
2508 interface_uuid
= existing_ifaces
[0]["uuid"]
2510 db_sce_classifier
= {
2511 "uuid": sce_classifier_uuid
,
2512 "name": get_str(classifier
, "name", 255),
2513 "sce_vnffg_id": sce_vnffg_uuid
,
2514 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2515 "interface_id": interface_uuid
,
2517 rsp_id
= get_str(classifier
, "rsp-id-ref", 255)
2518 rsp
= next((item
for item
in db_sce_rsps
if item
["id"] == rsp_id
), None)
2519 db_sce_classifier
["sce_rsp_id"] = rsp
["uuid"]
2520 db_sce_classifiers
.append(db_sce_classifier
)
2522 db_sce_classifier_matches
= []
2523 for match
in classifier
.get("match-attributes").itervalues():
2524 sce_classifier_match_uuid
= str(uuid4())
2525 uuid_list
.append(sce_classifier_match_uuid
)
2526 db_sce_classifier_match
= {
2527 "uuid": sce_classifier_match_uuid
,
2528 "ip_proto": get_str(match
, "ip-proto", 2),
2529 "source_ip": get_str(match
, "source-ip-address", 16),
2530 "destination_ip": get_str(match
, "destination-ip-address", 16),
2531 "source_port": get_str(match
, "source-port", 5),
2532 "destination_port": get_str(match
, "destination-port", 5),
2533 "sce_classifier_id": sce_classifier_uuid
,
2535 db_sce_classifier_matches
.append(db_sce_classifier_match
)
2538 # remove unneeded id's in sce_rsps
2539 for rsp
in db_sce_rsps
:
2543 {"scenarios": db_scenarios
},
2544 {"sce_nets": db_sce_nets
},
2545 {"ip_profiles": db_ip_profiles
},
2546 {"sce_vnfs": db_sce_vnfs
},
2547 {"sce_interfaces": db_sce_interfaces
},
2548 {"sce_vnffgs": db_sce_vnffgs
},
2549 {"sce_rsps": db_sce_rsps
},
2550 {"sce_rsp_hops": db_sce_rsp_hops
},
2551 {"sce_classifiers": db_sce_classifiers
},
2552 {"sce_classifier_matches": db_sce_classifier_matches
},
2555 logger
.debug("new_nsd_v3 done: %s",
2556 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
2557 mydb
.new_rows(db_tables
, uuid_list
)
2558 return nsd_uuid_list
2559 except NfvoException
:
2561 except Exception as e
:
2562 logger
.error("Exception {}".format(e
))
2563 raise # NfvoException("Exception {}".format(e), httperrors.Bad_Request)
2566 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
2567 data
["uuid"] = scenario_id
2568 data
["tenant_id"] = tenant_id
2569 c
= mydb
.edit_scenario( data
)
2573 @deprecated("Use create_instance")
2574 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
2575 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2576 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
2577 vims
= {datacenter_id
: myvim
}
2578 myvim_tenant
= myvim
['tenant_id']
2579 datacenter_name
= myvim
['name']
2583 #print "Checking that the scenario_id exists and getting the scenario dictionary"
2584 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
=datacenter_id
)
2585 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
2586 scenarioDict
['datacenter_id'] = datacenter_id
2587 #print '================scenarioDict======================='
2588 #print json.dumps(scenarioDict, indent=4)
2589 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
2591 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
2592 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2594 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
2595 auxNetDict
['scenario'] = {}
2597 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
2598 for sce_net
in scenarioDict
['nets']:
2599 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
2601 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
2602 myNetName
= myNetName
[0:255] #limit length
2603 myNetType
= sce_net
['type']
2605 myNetDict
["name"] = myNetName
2606 myNetDict
["type"] = myNetType
2607 myNetDict
["tenant_id"] = myvim_tenant
2608 myNetIPProfile
= sce_net
.get('ip_profile', None)
2610 #We should use the dictionary as input parameter for new_network
2612 if not sce_net
["external"]:
2613 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2614 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
2615 sce_net
['vim_id'] = network_id
2616 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
2617 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2618 sce_net
["created"] = True
2620 if sce_net
['vim_id'] == None:
2621 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
2622 _
, message
= rollback(mydb
, vims
, rollbackList
)
2623 logger
.error("nfvo.start_scenario: %s", error_text
)
2624 raise NfvoException(error_text
, httperrors
.Bad_Request
)
2625 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
2626 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
2628 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
2629 #For each vnf net, we create it and we add it to instanceNetlist.
2631 for sce_vnf
in scenarioDict
['vnfs']:
2632 for net
in sce_vnf
['nets']:
2633 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
2635 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
2636 myNetName
= myNetName
[0:255] #limit length
2637 myNetType
= net
['type']
2639 myNetDict
["name"] = myNetName
2640 myNetDict
["type"] = myNetType
2641 myNetDict
["tenant_id"] = myvim_tenant
2642 myNetIPProfile
= net
.get('ip_profile', None)
2645 #We should use the dictionary as input parameter for new_network
2646 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2647 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
2648 net
['vim_id'] = network_id
2649 if sce_vnf
['uuid'] not in auxNetDict
:
2650 auxNetDict
[sce_vnf
['uuid']] = {}
2651 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
2652 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2653 net
["created"] = True
2655 #print "auxNetDict:"
2656 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2658 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
2659 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2661 for sce_vnf
in scenarioDict
['vnfs']:
2662 vnf_availability_zones
= []
2663 for vm
in sce_vnf
['vms']:
2664 vm_av
= vm
.get('availability_zone')
2665 if vm_av
and vm_av
not in vnf_availability_zones
:
2666 vnf_availability_zones
.append(vm_av
)
2668 # check if there is enough availability zones available at vim level.
2669 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
2670 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
2671 raise NfvoException('No enough availability zones at VIM for this deployment', httperrors
.Bad_Request
)
2673 for vm
in sce_vnf
['vms']:
2676 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
2677 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
2678 #myVMDict['description'] = vm['description']
2679 myVMDict
['description'] = myVMDict
['name'][0:99]
2681 myVMDict
['start'] = "no"
2682 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2683 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
2685 #create image at vim in case it not exist
2686 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2687 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
2688 vm
['vim_image_id'] = image_id
2690 #create flavor at vim in case it not exist
2691 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2692 if flavor_dict
['extended']!=None:
2693 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2694 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
2695 vm
['vim_flavor_id'] = flavor_id
2698 myVMDict
['imageRef'] = vm
['vim_image_id']
2699 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2700 myVMDict
['networks'] = []
2701 for iface
in vm
['interfaces']:
2703 if iface
['type']=="data":
2704 netDict
['type'] = iface
['model']
2705 elif "model" in iface
and iface
["model"]!=None:
2706 netDict
['model']=iface
['model']
2707 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2708 #discover type of interface looking at flavor
2709 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2710 for flavor_iface
in numa
.get('interfaces',[]):
2711 if flavor_iface
.get('name') == iface
['internal_name']:
2712 if flavor_iface
['dedicated'] == 'yes':
2713 netDict
['type']="PF" #passthrough
2714 elif flavor_iface
['dedicated'] == 'no':
2715 netDict
['type']="VF" #siov
2716 elif flavor_iface
['dedicated'] == 'yes:sriov':
2717 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2718 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2720 netDict
["use"]=iface
['type']
2721 if netDict
["use"]=="data" and not netDict
.get("type"):
2722 #print "netDict", netDict
2723 #print "iface", iface
2724 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'])
2725 if flavor_dict
.get('extended')==None:
2726 raise NfvoException(e_text
+ "After database migration some information is not available. \
2727 Try to delete and create the scenarios and VNFs again", httperrors
.Conflict
)
2729 raise NfvoException(e_text
, httperrors
.Internal_Server_Error
)
2730 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2731 netDict
["type"]="virtual"
2732 if "vpci" in iface
and iface
["vpci"] is not None:
2733 netDict
['vpci'] = iface
['vpci']
2734 if "mac" in iface
and iface
["mac"] is not None:
2735 netDict
['mac_address'] = iface
['mac']
2736 if "port-security" in iface
and iface
["port-security"] is not None:
2737 netDict
['port_security'] = iface
['port-security']
2738 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2739 netDict
['floating_ip'] = iface
['floating-ip']
2740 netDict
['name'] = iface
['internal_name']
2741 if iface
['net_id'] is None:
2742 for vnf_iface
in sce_vnf
["interfaces"]:
2745 if vnf_iface
['interface_id']==iface
['uuid']:
2746 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
2749 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2750 #skip bridge ifaces not connected to any net
2751 #if 'net_id' not in netDict or netDict['net_id']==None:
2753 myVMDict
['networks'].append(netDict
)
2754 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2755 #print myVMDict['name']
2756 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2757 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2758 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2760 if 'availability_zone' in myVMDict
:
2761 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
2765 vm_id
, _
= myvim
.new_vminstance(myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2766 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2767 availability_zone_index
=av_index
,
2768 availability_zone_list
=vnf_availability_zones
)
2769 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
2770 vm
['vim_id'] = vm_id
2771 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2772 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2773 for net
in myVMDict
['networks']:
2775 for iface
in vm
['interfaces']:
2776 if net
["name"]==iface
["internal_name"]:
2777 iface
["vim_id"]=net
["vim_id"]
2780 logger
.debug("start scenario Deployment done")
2781 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2782 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
2783 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
2784 return mydb
.get_instance_scenario(instance_id
)
2786 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
2787 _
, message
= rollback(mydb
, vims
, rollbackList
)
2788 if isinstance(e
, db_base_Exception
):
2789 error_text
= "Exception at database"
2791 error_text
= "Exception at VIM"
2792 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2793 #logger.error("start_scenario %s", error_text)
2794 raise NfvoException(error_text
, e
.http_code
)
2796 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
2797 """ join the cloud config information into cloud_config_preserve.
2798 In case of conflict cloud_config_preserve preserves
2801 if not cloud_config_preserve
and not cloud_config
:
2804 new_cloud_config
= {"key-pairs":[], "users":[]}
2806 if cloud_config_preserve
:
2807 for key
in cloud_config_preserve
.get("key-pairs", () ):
2808 if key
not in new_cloud_config
["key-pairs"]:
2809 new_cloud_config
["key-pairs"].append(key
)
2811 for key
in cloud_config
.get("key-pairs", () ):
2812 if key
not in new_cloud_config
["key-pairs"]:
2813 new_cloud_config
["key-pairs"].append(key
)
2814 if not new_cloud_config
["key-pairs"]:
2815 del new_cloud_config
["key-pairs"]
2819 new_cloud_config
["users"] += cloud_config
.get("users", () )
2820 if cloud_config_preserve
:
2821 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
2822 index_to_delete
= []
2823 users
= new_cloud_config
.get("users", [])
2824 for index0
in range(0,len(users
)):
2825 if index0
in index_to_delete
:
2827 for index1
in range(index0
+1,len(users
)):
2828 if index1
in index_to_delete
:
2830 if users
[index0
]["name"] == users
[index1
]["name"]:
2831 index_to_delete
.append(index1
)
2832 for key
in users
[index1
].get("key-pairs",()):
2833 if "key-pairs" not in users
[index0
]:
2834 users
[index0
]["key-pairs"] = [key
]
2835 elif key
not in users
[index0
]["key-pairs"]:
2836 users
[index0
]["key-pairs"].append(key
)
2837 index_to_delete
.sort(reverse
=True)
2838 for index
in index_to_delete
:
2840 if not new_cloud_config
["users"]:
2841 del new_cloud_config
["users"]
2844 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
2845 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
2846 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
2847 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
2850 new_cloud_config
["user-data"] = []
2851 if cloud_config
and cloud_config
.get("user-data"):
2852 if isinstance(cloud_config
["user-data"], list):
2853 new_cloud_config
["user-data"] += cloud_config
["user-data"]
2855 new_cloud_config
["user-data"].append(cloud_config
["user-data"])
2856 if cloud_config_preserve
and cloud_config_preserve
.get("user-data"):
2857 if isinstance(cloud_config_preserve
["user-data"], list):
2858 new_cloud_config
["user-data"] += cloud_config_preserve
["user-data"]
2860 new_cloud_config
["user-data"].append(cloud_config_preserve
["user-data"])
2861 if not new_cloud_config
["user-data"]:
2862 del new_cloud_config
["user-data"]
2865 new_cloud_config
["config-files"] = []
2866 if cloud_config
and cloud_config
.get("config-files") != None:
2867 new_cloud_config
["config-files"] += cloud_config
["config-files"]
2868 if cloud_config_preserve
:
2869 for file in cloud_config_preserve
.get("config-files", ()):
2870 for index
in range(0, len(new_cloud_config
["config-files"])):
2871 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
2872 new_cloud_config
["config-files"][index
] = file
2875 new_cloud_config
["config-files"].append(file)
2876 if not new_cloud_config
["config-files"]:
2877 del new_cloud_config
["config-files"]
2878 return new_cloud_config
2881 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
2882 datacenter_id
= None
2883 datacenter_name
= None
2886 if datacenter_tenant_id
:
2887 thread_id
= datacenter_tenant_id
2888 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
2890 where_
={"td.nfvo_tenant_id": tenant_id
}
2891 if datacenter_id_name
:
2892 if utils
.check_valid_uuid(datacenter_id_name
):
2893 datacenter_id
= datacenter_id_name
2894 where_
["dt.datacenter_id"] = datacenter_id
2896 datacenter_name
= datacenter_id_name
2897 where_
["d.name"] = datacenter_name
2898 if datacenter_tenant_id
:
2899 where_
["dt.uuid"] = datacenter_tenant_id
2900 datacenters
= mydb
.get_rows(
2901 SELECT
=("dt.uuid as datacenter_tenant_id",),
2902 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
2903 "join datacenters as d on d.uuid=dt.datacenter_id",
2905 if len(datacenters
) > 1:
2906 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
2908 thread_id
= datacenters
[0]["datacenter_tenant_id"]
2909 thread
= vim_threads
["running"].get(thread_id
)
2911 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
2912 return thread_id
, thread
2913 except db_base_Exception
as e
:
2914 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
2917 def get_datacenter_uuid(mydb
, tenant_id
, datacenter_id_name
):
2919 if utils
.check_valid_uuid(datacenter_id_name
):
2920 WHERE_dict
['d.uuid'] = datacenter_id_name
2922 WHERE_dict
['d.name'] = datacenter_id_name
2925 WHERE_dict
['nfvo_tenant_id'] = tenant_id
2926 from_
= "tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join datacenter_tenants as" \
2927 " dt on td.datacenter_tenant_id=dt.uuid"
2929 from_
= 'datacenters as d'
2930 vimaccounts
= mydb
.get_rows(FROM
=from_
, SELECT
=("d.uuid as uuid, d.name as name",), WHERE
=WHERE_dict
)
2931 if len(vimaccounts
) == 0:
2932 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
2933 elif len(vimaccounts
)>1:
2934 #print "nfvo.datacenter_action() error. Several datacenters found"
2935 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
2936 return vimaccounts
[0]["uuid"], vimaccounts
[0]["name"]
2939 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
2940 datacenter_id
= None
2941 datacenter_name
= None
2942 if datacenter_id_name
:
2943 if utils
.check_valid_uuid(datacenter_id_name
):
2944 datacenter_id
= datacenter_id_name
2946 datacenter_name
= datacenter_id_name
2947 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
2949 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), httperrors
.Not_Found
)
2951 #print "nfvo.datacenter_action() error. Several datacenters found"
2952 raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors
.Conflict
)
2953 return vims
.keys()[0], vims
.values()[0]
2957 '''Takes dict d and updates it with the values in dict u.'''
2958 '''It merges all depth levels'''
2959 for k
, v
in u
.iteritems():
2960 if isinstance(v
, collections
.Mapping
):
2961 r
= update(d
.get(k
, {}), v
)
2968 def create_instance(mydb
, tenant_id
, instance_dict
):
2969 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2970 # logger.debug("Creating instance...")
2971 scenario
= instance_dict
["scenario"]
2973 # find main datacenter
2975 myvim_threads_id
= {}
2976 datacenter
= instance_dict
.get("datacenter")
2977 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2978 myvims
[default_datacenter_id
] = vim
2979 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
2980 tenant
= mydb
.get_rows_by_id('nfvo_tenants', tenant_id
)
2981 # myvim_tenant = myvim['tenant_id']
2984 # print "Checking that the scenario exists and getting the scenario dictionary"
2985 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, datacenter_vim_id
=myvim_threads_id
[default_datacenter_id
],
2986 datacenter_id
=default_datacenter_id
)
2988 # logger.debug(">>>>>> Dictionaries before merging")
2989 # logger.debug(">>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
2990 # logger.debug(">>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
2992 db_instance_vnfs
= []
2993 db_instance_vms
= []
2994 db_instance_interfaces
= []
2995 db_instance_sfis
= []
2996 db_instance_sfs
= []
2997 db_instance_classifications
= []
2998 db_instance_sfps
= []
3003 instance_name
= instance_dict
["name"]
3004 instance_uuid
= str(uuid4())
3005 uuid_list
.append(instance_uuid
)
3006 db_instance_scenario
= {
3007 "uuid": instance_uuid
,
3008 "name": instance_name
,
3009 "tenant_id": tenant_id
,
3010 "scenario_id": scenarioDict
['uuid'],
3011 "datacenter_id": default_datacenter_id
,
3012 # filled bellow 'datacenter_tenant_id'
3013 "description": instance_dict
.get("description"),
3015 if scenarioDict
.get("cloud-config"):
3016 db_instance_scenario
["cloud_config"] = yaml
.safe_dump(scenarioDict
["cloud-config"],
3017 default_flow_style
=True, width
=256)
3018 instance_action_id
= get_task_id()
3019 db_instance_action
= {
3020 "uuid": instance_action_id
, # same uuid for the instance and the action on create
3021 "tenant_id": tenant_id
,
3022 "instance_id": instance_uuid
,
3023 "description": "CREATE",
3026 # Auxiliary dictionaries from x to y
3027 sce_net2instance
= {}
3028 net2task_id
= {'scenario': {}}
3030 def ip_profile_IM2RO(ip_profile_im
):
3031 # translate from input format to database format
3033 if 'subnet-address' in ip_profile_im
:
3034 ip_profile_ro
['subnet_address'] = ip_profile_im
['subnet-address']
3035 if 'ip-version' in ip_profile_im
:
3036 ip_profile_ro
['ip_version'] = ip_profile_im
['ip-version']
3037 if 'gateway-address' in ip_profile_im
:
3038 ip_profile_ro
['gateway_address'] = ip_profile_im
['gateway-address']
3039 if 'dns-address' in ip_profile_im
:
3040 ip_profile_ro
['dns_address'] = ip_profile_im
['dns-address']
3041 if isinstance(ip_profile_ro
['dns_address'], (list, tuple)):
3042 ip_profile_ro
['dns_address'] = ";".join(ip_profile_ro
['dns_address'])
3043 if 'dhcp' in ip_profile_im
:
3044 ip_profile_ro
['dhcp_start_address'] = ip_profile_im
['dhcp'].get('start-address')
3045 ip_profile_ro
['dhcp_enabled'] = ip_profile_im
['dhcp'].get('enabled', True)
3046 ip_profile_ro
['dhcp_count'] = ip_profile_im
['dhcp'].get('count')
3047 return ip_profile_ro
3049 # logger.debug("Creating instance from scenario-dict:\n%s",
3050 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
3052 # 0 check correct parameters
3053 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).iteritems():
3054 for scenario_net
in scenarioDict
['nets']:
3055 if net_name
== scenario_net
.get("name") or net_name
== scenario_net
.get("osm_id") or net_name
== scenario_net
.get("uuid"):
3058 raise NfvoException("Invalid scenario network name or id '{}' at instance:networks".format(net_name
),
3059 httperrors
.Bad_Request
)
3060 if "sites" not in net_instance_desc
:
3061 net_instance_desc
["sites"] = [ {} ]
3062 site_without_datacenter_field
= False
3063 for site
in net_instance_desc
["sites"]:
3064 if site
.get("datacenter"):
3065 site
["datacenter"], _
= get_datacenter_uuid(mydb
, tenant_id
, site
["datacenter"])
3066 if site
["datacenter"] not in myvims
:
3067 # Add this datacenter to myvims
3068 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
3070 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
3071 site
["datacenter"] = d
# change name to id
3073 if site_without_datacenter_field
:
3074 raise NfvoException("Found more than one entries without datacenter field at "
3075 "instance:networks:{}:sites".format(net_name
), httperrors
.Bad_Request
)
3076 site_without_datacenter_field
= True
3077 site
["datacenter"] = default_datacenter_id
# change name to id
3079 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
3080 for scenario_vnf
in scenarioDict
['vnfs']:
3081 if vnf_name
== scenario_vnf
['member_vnf_index'] or vnf_name
== scenario_vnf
['uuid'] or vnf_name
== scenario_vnf
['name']:
3084 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_name
), httperrors
.Bad_Request
)
3085 if "datacenter" in vnf_instance_desc
:
3086 # Add this datacenter to myvims
3087 vnf_instance_desc
["datacenter"], _
= get_datacenter_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3088 if vnf_instance_desc
["datacenter"] not in myvims
:
3089 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3091 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
3092 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
3094 for net_id
, net_instance_desc
in vnf_instance_desc
.get("networks", {}).iteritems():
3095 for scenario_net
in scenario_vnf
['nets']:
3096 if net_id
== scenario_net
['osm_id'] or net_id
== scenario_net
['uuid'] or net_id
== scenario_net
["name"]:
3099 raise NfvoException("Invalid net id or name '{}' at instance:vnfs:networks".format(net_id
), httperrors
.Bad_Request
)
3100 if net_instance_desc
.get("vim-network-name"):
3101 scenario_net
["vim-network-name"] = net_instance_desc
["vim-network-name"]
3102 if net_instance_desc
.get("name"):
3103 scenario_net
["name"] = net_instance_desc
["name"]
3104 if 'ip-profile' in net_instance_desc
:
3105 ipprofile_db
= ip_profile_IM2RO(net_instance_desc
['ip-profile'])
3106 if 'ip_profile' not in scenario_net
:
3107 scenario_net
['ip_profile'] = ipprofile_db
3109 update(scenario_net
['ip_profile'], ipprofile_db
)
3111 for vdu_id
, vdu_instance_desc
in vnf_instance_desc
.get("vdus", {}).iteritems():
3112 for scenario_vm
in scenario_vnf
['vms']:
3113 if vdu_id
== scenario_vm
['osm_id'] or vdu_id
== scenario_vm
["name"]:
3116 raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id
), httperrors
.Bad_Request
)
3117 scenario_vm
["instance_parameters"] = vdu_instance_desc
3118 for iface_id
, iface_instance_desc
in vdu_instance_desc
.get("interfaces", {}).iteritems():
3119 for scenario_interface
in scenario_vm
['interfaces']:
3120 if iface_id
== scenario_interface
['internal_name'] or iface_id
== scenario_interface
["external_name"]:
3121 scenario_interface
.update(iface_instance_desc
)
3124 raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id
), httperrors
.Bad_Request
)
3126 # 0.1 parse cloud-config parameters
3127 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
3129 # 0.2 merge instance information into scenario
3130 # Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
3131 # However, this is not possible yet.
3132 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).iteritems():
3133 for scenario_net
in scenarioDict
['nets']:
3134 if net_name
== scenario_net
["name"]:
3135 if 'ip-profile' in net_instance_desc
:
3136 ipprofile_db
= ip_profile_IM2RO(net_instance_desc
['ip-profile'])
3137 if 'ip_profile' not in scenario_net
:
3138 scenario_net
['ip_profile'] = ipprofile_db
3140 update(scenario_net
['ip_profile'], ipprofile_db
)
3141 for interface
in net_instance_desc
.get('interfaces', ()):
3142 if 'ip_address' in interface
:
3143 for vnf
in scenarioDict
['vnfs']:
3144 if interface
['vnf'] == vnf
['name']:
3145 for vnf_interface
in vnf
['interfaces']:
3146 if interface
['vnf_interface'] == vnf_interface
['external_name']:
3147 vnf_interface
['ip_address'] = interface
['ip_address']
3149 # logger.debug(">>>>>>>> Merged dictionary")
3150 # logger.debug("Creating instance scenario-dict MERGED:\n%s",
3151 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
3153 # 1. Creating new nets (sce_nets) in the VIM"
3154 number_mgmt_networks
= 0
3155 db_instance_nets
= []
3156 for sce_net
in scenarioDict
['nets']:
3157 # get involved datacenters where this network need to be created
3158 involved_datacenters
= []
3159 for sce_vnf
in scenarioDict
.get("vnfs"):
3160 vnf_datacenter
= sce_vnf
.get("datacenter", default_datacenter_id
)
3161 if vnf_datacenter
in involved_datacenters
:
3163 if sce_vnf
.get("interfaces"):
3164 for sce_vnf_ifaces
in sce_vnf
["interfaces"]:
3165 if sce_vnf_ifaces
.get("sce_net_id") == sce_net
["uuid"]:
3166 involved_datacenters
.append(vnf_datacenter
)
3170 if instance_dict
.get("networks") and instance_dict
["networks"].get(sce_net
["name"]):
3171 descriptor_net
= instance_dict
["networks"][sce_net
["name"]]
3172 net_name
= descriptor_net
.get("vim-network-name")
3173 sce_net2instance
[sce_net
['uuid']] = {}
3174 net2task_id
['scenario'][sce_net
['uuid']] = {}
3176 if sce_net
["external"]:
3177 number_mgmt_networks
+= 1
3179 for datacenter_id
in involved_datacenters
:
3181 netmap_create
= None
3182 if descriptor_net
.get("sites"):
3183 for site
in descriptor_net
["sites"]:
3184 if site
.get("datacenter") == datacenter_id
:
3185 netmap_use
= site
.get("netmap-use")
3186 netmap_create
= site
.get("netmap-create")
3189 vim
= myvims
[datacenter_id
]
3190 myvim_thread_id
= myvim_threads_id
[datacenter_id
]
3192 net_type
= sce_net
['type']
3193 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} # 'shared': True
3196 if sce_net
["external"]:
3197 net_name
= sce_net
["name"]
3199 net_name
= "{}-{}".format(instance_name
, sce_net
["name"])
3200 net_name
= net_name
[:255] # limit length
3202 if netmap_use
or netmap_create
:
3203 create_network
= False
3204 lookfor_network
= False
3206 lookfor_network
= True
3207 if utils
.check_valid_uuid(netmap_use
):
3208 lookfor_filter
["id"] = netmap_use
3210 lookfor_filter
["name"] = netmap_use
3212 create_network
= True
3213 net_vim_name
= net_name
3214 if isinstance(netmap_create
, str):
3215 net_vim_name
= netmap_create
3216 elif sce_net
.get("vim_network_name"):
3217 create_network
= False
3218 lookfor_network
= True
3219 lookfor_filter
["name"] = sce_net
.get("vim_network_name")
3220 elif sce_net
["external"]:
3221 if sce_net
['vim_id'] is not None:
3222 # there is a netmap at datacenter_nets database # TODO REVISE!!!!
3223 create_network
= False
3224 lookfor_network
= True
3225 lookfor_filter
["id"] = sce_net
['vim_id']
3226 elif vim
["config"].get("management_network_id") or vim
["config"].get("management_network_name"):
3227 if number_mgmt_networks
> 1:
3228 raise NfvoException("Found several VLD of type mgmt. "
3229 "You must concrete what vim-network must be use for each one",
3230 httperrors
.Bad_Request
)
3231 create_network
= False
3232 lookfor_network
= True
3233 if vim
["config"].get("management_network_id"):
3234 lookfor_filter
["id"] = vim
["config"]["management_network_id"]
3236 lookfor_filter
["name"] = vim
["config"]["management_network_name"]
3238 # There is not a netmap, look at datacenter for a net with this name and create if not found
3239 create_network
= True
3240 lookfor_network
= True
3241 lookfor_filter
["name"] = sce_net
["name"]
3242 net_vim_name
= sce_net
["name"]
3244 net_vim_name
= net_name
3245 create_network
= True
3246 lookfor_network
= False
3250 task_action
= "CREATE"
3251 task_extra
["params"] = (net_vim_name
, net_type
, sce_net
.get('ip_profile', None))
3253 task_extra
["find"] = (lookfor_filter
,)
3254 elif lookfor_network
:
3255 task_action
= "FIND"
3256 task_extra
["params"] = (lookfor_filter
,)
3258 # fill database content
3259 net_uuid
= str(uuid4())
3260 uuid_list
.append(net_uuid
)
3261 sce_net2instance
[sce_net
['uuid']][datacenter_id
] = net_uuid
3265 "instance_scenario_id": instance_uuid
,
3266 "sce_net_id": sce_net
["uuid"],
3267 "created": create_network
,
3268 'datacenter_id': datacenter_id
,
3269 'datacenter_tenant_id': myvim_thread_id
,
3270 'status': 'BUILD' # if create_network else "ACTIVE"
3272 db_instance_nets
.append(db_net
)
3274 "instance_action_id": instance_action_id
,
3275 "status": "SCHEDULED",
3276 "task_index": task_index
,
3277 "datacenter_vim_id": myvim_thread_id
,
3278 "action": task_action
,
3279 "item": "instance_nets",
3280 "item_id": net_uuid
,
3281 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
3283 net2task_id
['scenario'][sce_net
['uuid']][datacenter_id
] = task_index
3285 db_vim_actions
.append(db_vim_action
)
3287 if 'ip_profile' in sce_net
:
3289 'instance_net_id': net_uuid
,
3290 'ip_version': sce_net
['ip_profile']['ip_version'],
3291 'subnet_address': sce_net
['ip_profile']['subnet_address'],
3292 'gateway_address': sce_net
['ip_profile']['gateway_address'],
3293 'dns_address': sce_net
['ip_profile']['dns_address'],
3294 'dhcp_enabled': sce_net
['ip_profile']['dhcp_enabled'],
3295 'dhcp_start_address': sce_net
['ip_profile']['dhcp_start_address'],
3296 'dhcp_count': sce_net
['ip_profile']['dhcp_count'],
3298 db_ip_profiles
.append(db_ip_profile
)
3302 "default_datacenter_id": default_datacenter_id
,
3303 "myvim_threads_id": myvim_threads_id
,
3304 "instance_uuid": instance_uuid
,
3305 "instance_name": instance_name
,
3306 "instance_action_id": instance_action_id
,
3308 "cloud_config": cloud_config
,
3309 "RO_pub_key": tenant
[0].get('RO_pub_key'),
3312 "task_index": task_index
,
3313 "uuid_list": uuid_list
,
3314 "db_instance_nets": db_instance_nets
,
3315 "db_vim_actions": db_vim_actions
,
3316 "db_ip_profiles": db_ip_profiles
,
3317 "db_instance_vnfs": db_instance_vnfs
,
3318 "db_instance_vms": db_instance_vms
,
3319 "db_instance_interfaces": db_instance_interfaces
,
3320 "net2task_id": net2task_id
,
3321 "sce_net2instance": sce_net2instance
,
3323 # sce_vnf_list = sorted(scenarioDict['vnfs'], key=lambda k: k['name'])
3324 for sce_vnf
in scenarioDict
['vnfs']: # sce_vnf_list:
3325 instantiate_vnf(mydb
, sce_vnf
, vnf_params
, vnf_params_out
, rollbackList
)
3326 task_index
= vnf_params_out
["task_index"]
3327 uuid_list
= vnf_params_out
["uuid_list"]
3330 # task_depends_on = []
3331 for vnffg
in scenarioDict
['vnffgs']:
3332 for rsp
in vnffg
['rsps']:
3334 for cp
in rsp
['connection_points']:
3335 count
= mydb
.get_rows(
3336 SELECT
=('vms.count'),
3337 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_rsp_hops as h on interfaces.uuid=h.interface_id",
3338 WHERE
={'h.uuid': cp
['uuid']})[0]['count']
3339 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == cp
['sce_vnf_id']), None)
3340 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3342 for instance_vm
in instance_vms
:
3343 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3345 dependencies
.append(action
['task_index'])
3346 # TODO: throw exception if count != len(instance_vms)
3347 # TODO: and action shouldn't ever be None
3349 for i
in range(count
):
3351 sfi_uuid
= str(uuid4())
3352 uuid_list
.append(sfi_uuid
)
3355 "instance_scenario_id": instance_uuid
,
3356 'sce_rsp_hop_id': cp
['uuid'],
3357 'datacenter_id': datacenter_id
,
3358 'datacenter_tenant_id': myvim_thread_id
,
3359 "vim_sfi_id": None, # vim thread will populate
3361 db_instance_sfis
.append(db_sfi
)
3363 "instance_action_id": instance_action_id
,
3364 "task_index": task_index
,
3365 "datacenter_vim_id": myvim_thread_id
,
3367 "status": "SCHEDULED",
3368 "item": "instance_sfis",
3369 "item_id": sfi_uuid
,
3370 "extra": yaml
.safe_dump({"params": "", "depends_on": [dependencies
[i
]]},
3371 default_flow_style
=True, width
=256)
3373 sfis_created
.append(task_index
)
3375 db_vim_actions
.append(db_vim_action
)
3377 sf_uuid
= str(uuid4())
3378 uuid_list
.append(sf_uuid
)
3381 "instance_scenario_id": instance_uuid
,
3382 'sce_rsp_hop_id': cp
['uuid'],
3383 'datacenter_id': datacenter_id
,
3384 'datacenter_tenant_id': myvim_thread_id
,
3385 "vim_sf_id": None, # vim thread will populate
3387 db_instance_sfs
.append(db_sf
)
3389 "instance_action_id": instance_action_id
,
3390 "task_index": task_index
,
3391 "datacenter_vim_id": myvim_thread_id
,
3393 "status": "SCHEDULED",
3394 "item": "instance_sfs",
3396 "extra": yaml
.safe_dump({"params": "", "depends_on": sfis_created
},
3397 default_flow_style
=True, width
=256)
3399 sfs_created
.append(task_index
)
3401 db_vim_actions
.append(db_vim_action
)
3402 classifier
= rsp
['classifier']
3404 # TODO the following ~13 lines can be reused for the sfi case
3405 count
= mydb
.get_rows(
3406 SELECT
=('vms.count'),
3407 FROM
="vms join interfaces on vms.uuid=interfaces.vm_id join sce_classifiers as c on interfaces.uuid=c.interface_id",
3408 WHERE
={'c.uuid': classifier
['uuid']})[0]['count']
3409 instance_vnf
= next((item
for item
in db_instance_vnfs
if item
['sce_vnf_id'] == classifier
['sce_vnf_id']), None)
3410 instance_vms
= [item
for item
in db_instance_vms
if item
['instance_vnf_id'] == instance_vnf
['uuid']]
3412 for instance_vm
in instance_vms
:
3413 action
= next((item
for item
in db_vim_actions
if item
['item_id'] == instance_vm
['uuid']), None)
3415 dependencies
.append(action
['task_index'])
3416 # TODO: throw exception if count != len(instance_vms)
3417 # TODO: and action shouldn't ever be None
3418 classifications_created
= []
3419 for i
in range(count
):
3420 for match
in classifier
['matches']:
3421 # create classifications
3422 classification_uuid
= str(uuid4())
3423 uuid_list
.append(classification_uuid
)
3424 db_classification
= {
3425 "uuid": classification_uuid
,
3426 "instance_scenario_id": instance_uuid
,
3427 'sce_classifier_match_id': match
['uuid'],
3428 'datacenter_id': datacenter_id
,
3429 'datacenter_tenant_id': myvim_thread_id
,
3430 "vim_classification_id": None, # vim thread will populate
3432 db_instance_classifications
.append(db_classification
)
3433 classification_params
= {
3434 "ip_proto": match
["ip_proto"],
3435 "source_ip": match
["source_ip"],
3436 "destination_ip": match
["destination_ip"],
3437 "source_port": match
["source_port"],
3438 "destination_port": match
["destination_port"]
3441 "instance_action_id": instance_action_id
,
3442 "task_index": task_index
,
3443 "datacenter_vim_id": myvim_thread_id
,
3445 "status": "SCHEDULED",
3446 "item": "instance_classifications",
3447 "item_id": classification_uuid
,
3448 "extra": yaml
.safe_dump({"params": classification_params
, "depends_on": [dependencies
[i
]]},
3449 default_flow_style
=True, width
=256)
3451 classifications_created
.append(task_index
)
3453 db_vim_actions
.append(db_vim_action
)
3456 sfp_uuid
= str(uuid4())
3457 uuid_list
.append(sfp_uuid
)
3460 "instance_scenario_id": instance_uuid
,
3461 'sce_rsp_id': rsp
['uuid'],
3462 'datacenter_id': datacenter_id
,
3463 'datacenter_tenant_id': myvim_thread_id
,
3464 "vim_sfp_id": None, # vim thread will populate
3466 db_instance_sfps
.append(db_sfp
)
3468 "instance_action_id": instance_action_id
,
3469 "task_index": task_index
,
3470 "datacenter_vim_id": myvim_thread_id
,
3472 "status": "SCHEDULED",
3473 "item": "instance_sfps",
3474 "item_id": sfp_uuid
,
3475 "extra": yaml
.safe_dump({"params": "", "depends_on": sfs_created
+ classifications_created
},
3476 default_flow_style
=True, width
=256)
3479 db_vim_actions
.append(db_vim_action
)
3480 db_instance_action
["number_tasks"] = task_index
3483 wan_links
= wim_engine
.derive_wan_links(db_instance_nets
, tenant_id
)
3484 wim_actions
= wim_engine
.create_actions(wan_links
)
3485 wim_actions
, db_instance_action
= (
3486 wim_engine
.incorporate_actions(wim_actions
, db_instance_action
))
3489 scenarioDict
["datacenter2tenant"] = myvim_threads_id
3491 db_instance_scenario
['datacenter_tenant_id'] = myvim_threads_id
[default_datacenter_id
]
3492 db_instance_scenario
['datacenter_id'] = default_datacenter_id
3494 {"instance_scenarios": db_instance_scenario
},
3495 {"instance_vnfs": db_instance_vnfs
},
3496 {"instance_nets": db_instance_nets
},
3497 {"ip_profiles": db_ip_profiles
},
3498 {"instance_vms": db_instance_vms
},
3499 {"instance_interfaces": db_instance_interfaces
},
3500 {"instance_actions": db_instance_action
},
3501 {"instance_sfis": db_instance_sfis
},
3502 {"instance_sfs": db_instance_sfs
},
3503 {"instance_classifications": db_instance_classifications
},
3504 {"instance_sfps": db_instance_sfps
},
3505 {"instance_wim_nets": wan_links
},
3506 {"vim_wim_actions": db_vim_actions
+ wim_actions
}
3509 logger
.debug("create_instance done DB tables: %s",
3510 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
3511 mydb
.new_rows(db_tables
, uuid_list
)
3512 for myvim_thread_id
in myvim_threads_id
.values():
3513 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
3515 wim_engine
.dispatch(wim_actions
)
3517 returned_instance
= mydb
.get_instance_scenario(instance_uuid
)
3518 returned_instance
["action_id"] = instance_action_id
3519 return returned_instance
3520 except (NfvoException
, vimconn
.vimconnException
, db_base_Exception
) as e
:
3521 message
= rollback(mydb
, myvims
, rollbackList
)
3522 if isinstance(e
, db_base_Exception
):
3523 error_text
= "database Exception"
3524 elif isinstance(e
, vimconn
.vimconnException
):
3525 error_text
= "VIM Exception"
3527 error_text
= "Exception"
3528 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
3529 # logger.error("create_instance: %s", error_text)
3531 raise NfvoException(error_text
, e
.http_code
)
3534 def instantiate_vnf(mydb
, sce_vnf
, params
, params_out
, rollbackList
):
3535 default_datacenter_id
= params
["default_datacenter_id"]
3536 myvim_threads_id
= params
["myvim_threads_id"]
3537 instance_uuid
= params
["instance_uuid"]
3538 instance_name
= params
["instance_name"]
3539 instance_action_id
= params
["instance_action_id"]
3540 myvims
= params
["myvims"]
3541 cloud_config
= params
["cloud_config"]
3542 RO_pub_key
= params
["RO_pub_key"]
3544 task_index
= params_out
["task_index"]
3545 uuid_list
= params_out
["uuid_list"]
3546 db_instance_nets
= params_out
["db_instance_nets"]
3547 db_vim_actions
= params_out
["db_vim_actions"]
3548 db_ip_profiles
= params_out
["db_ip_profiles"]
3549 db_instance_vnfs
= params_out
["db_instance_vnfs"]
3550 db_instance_vms
= params_out
["db_instance_vms"]
3551 db_instance_interfaces
= params_out
["db_instance_interfaces"]
3552 net2task_id
= params_out
["net2task_id"]
3553 sce_net2instance
= params_out
["sce_net2instance"]
3555 vnf_net2instance
= {}
3557 # 2. Creating new nets (vnf internal nets) in the VIM"
3558 # For each vnf net, we create it and we add it to instanceNetlist.
3559 if sce_vnf
.get("datacenter"):
3560 datacenter_id
= sce_vnf
["datacenter"]
3561 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
3563 datacenter_id
= default_datacenter_id
3564 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
3565 for net
in sce_vnf
['nets']:
3567 # descriptor_net = instance_dict.get("vnfs", {}).get(sce_vnf["name"], {})
3568 # net_name = descriptor_net.get("name")
3571 net_name
= "{}-{}".format(instance_name
, net
["name"])
3572 net_name
= net_name
[:255] # limit length
3573 net_type
= net
['type']
3575 if sce_vnf
['uuid'] not in vnf_net2instance
:
3576 vnf_net2instance
[sce_vnf
['uuid']] = {}
3577 if sce_vnf
['uuid'] not in net2task_id
:
3578 net2task_id
[sce_vnf
['uuid']] = {}
3579 net2task_id
[sce_vnf
['uuid']][net
['uuid']] = task_index
3581 # fill database content
3582 net_uuid
= str(uuid4())
3583 uuid_list
.append(net_uuid
)
3584 vnf_net2instance
[sce_vnf
['uuid']][net
['uuid']] = net_uuid
3588 "instance_scenario_id": instance_uuid
,
3589 "net_id": net
["uuid"],
3591 'datacenter_id': datacenter_id
,
3592 'datacenter_tenant_id': myvim_thread_id
,
3594 db_instance_nets
.append(db_net
)
3596 if net
.get("vim-network-name"):
3597 lookfor_filter
= {"name": net
["vim-network-name"]}
3598 task_action
= "FIND"
3599 task_extra
= {"params": (lookfor_filter
,)}
3601 task_action
= "CREATE"
3602 task_extra
= {"params": (net_name
, net_type
, net
.get('ip_profile', None))}
3605 "instance_action_id": instance_action_id
,
3606 "task_index": task_index
,
3607 "datacenter_vim_id": myvim_thread_id
,
3608 "status": "SCHEDULED",
3609 "action": task_action
,
3610 "item": "instance_nets",
3611 "item_id": net_uuid
,
3612 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
3615 db_vim_actions
.append(db_vim_action
)
3617 if 'ip_profile' in net
:
3619 'instance_net_id': net_uuid
,
3620 'ip_version': net
['ip_profile']['ip_version'],
3621 'subnet_address': net
['ip_profile']['subnet_address'],
3622 'gateway_address': net
['ip_profile']['gateway_address'],
3623 'dns_address': net
['ip_profile']['dns_address'],
3624 'dhcp_enabled': net
['ip_profile']['dhcp_enabled'],
3625 'dhcp_start_address': net
['ip_profile']['dhcp_start_address'],
3626 'dhcp_count': net
['ip_profile']['dhcp_count'],
3628 db_ip_profiles
.append(db_ip_profile
)
3630 # print "vnf_net2instance:"
3631 # print yaml.safe_dump(vnf_net2instance, indent=4, default_flow_style=False)
3633 # 3. Creating new vm instances in the VIM
3634 # myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
3636 if sce_vnf
.get('mgmt_access'):
3637 ssh_access
= sce_vnf
['mgmt_access'].get('config-access', {}).get('ssh-access')
3638 vnf_availability_zones
= []
3639 for vm
in sce_vnf
['vms']:
3640 vm_av
= vm
.get('availability_zone')
3641 if vm_av
and vm_av
not in vnf_availability_zones
:
3642 vnf_availability_zones
.append(vm_av
)
3644 # check if there is enough availability zones available at vim level.
3645 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
3646 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
3647 raise NfvoException('No enough availability zones at VIM for this deployment', httperrors
.Bad_Request
)
3649 if sce_vnf
.get("datacenter"):
3650 vim
= myvims
[sce_vnf
["datacenter"]]
3651 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
3652 datacenter_id
= sce_vnf
["datacenter"]
3654 vim
= myvims
[default_datacenter_id
]
3655 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
3656 datacenter_id
= default_datacenter_id
3657 sce_vnf
["datacenter_id"] = datacenter_id
3660 vnf_uuid
= str(uuid4())
3661 uuid_list
.append(vnf_uuid
)
3664 'instance_scenario_id': instance_uuid
,
3665 'vnf_id': sce_vnf
['vnf_id'],
3666 'sce_vnf_id': sce_vnf
['uuid'],
3667 'datacenter_id': datacenter_id
,
3668 'datacenter_tenant_id': myvim_thread_id
,
3670 db_instance_vnfs
.append(db_instance_vnf
)
3672 for vm
in sce_vnf
['vms']:
3674 sce_vnf_name
= sce_vnf
['member_vnf_index'] if sce_vnf
['member_vnf_index'] else sce_vnf
['name']
3675 myVMDict
['name'] = "{}-{}-{}".format(instance_name
[:64], sce_vnf_name
[:64], vm
["name"][:64])
3676 myVMDict
['description'] = myVMDict
['name'][0:99]
3678 # myVMDict['start'] = "no"
3679 if vm
.get("instance_parameters") and vm
["instance_parameters"].get("name"):
3680 myVMDict
['name'] = vm
["instance_parameters"].get("name")
3681 myVMDict
['name'] = myVMDict
['name'][0:255] # limit name length
3682 # create image at vim in case it not exist
3683 image_uuid
= vm
['image_id']
3684 if vm
.get("image_list"):
3685 for alternative_image
in vm
["image_list"]:
3686 if alternative_image
["vim_type"] == vim
["config"]["_vim_type_internal"]:
3687 image_uuid
= alternative_image
['image_id']
3689 image_dict
= mydb
.get_table_by_uuid_name("images", image_uuid
)
3690 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
3691 vm
['vim_image_id'] = image_id
3693 # create flavor at vim in case it not exist
3694 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
3695 if flavor_dict
['extended'] != None:
3696 flavor_dict
['extended'] = yaml
.load(flavor_dict
['extended'])
3697 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
3699 # Obtain information for additional disks
3700 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',),
3701 WHERE
={'vim_id': flavor_id
})
3702 if not extended_flavor_dict
:
3703 raise NfvoException("flavor '{}' not found".format(flavor_id
), httperrors
.Not_Found
)
3705 # extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
3706 myVMDict
['disks'] = None
3707 extended_info
= extended_flavor_dict
[0]['extended']
3708 if extended_info
!= None:
3709 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
3710 if 'disks' in extended_flavor_dict_yaml
:
3711 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
3712 if vm
.get("instance_parameters") and vm
["instance_parameters"].get("devices"):
3713 for disk
in myVMDict
['disks']:
3714 if disk
.get("name") in vm
["instance_parameters"]["devices"]:
3715 disk
.update(vm
["instance_parameters"]["devices"][disk
.get("name")])
3717 vm
['vim_flavor_id'] = flavor_id
3718 myVMDict
['imageRef'] = vm
['vim_image_id']
3719 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
3720 myVMDict
['availability_zone'] = vm
.get('availability_zone')
3721 myVMDict
['networks'] = []
3722 task_depends_on
= []
3723 # TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
3725 for iface
in vm
['interfaces']:
3727 if iface
['type'] == "data":
3728 netDict
['type'] = iface
['model']
3729 elif "model" in iface
and iface
["model"] != None:
3730 netDict
['model'] = iface
['model']
3731 # TODO in future, remove this because mac_address will not be set, and the type of PV,VF
3732 # is obtained from iterface table model
3733 # discover type of interface looking at flavor
3734 for numa
in flavor_dict
.get('extended', {}).get('numas', []):
3735 for flavor_iface
in numa
.get('interfaces', []):
3736 if flavor_iface
.get('name') == iface
['internal_name']:
3737 if flavor_iface
['dedicated'] == 'yes':
3738 netDict
['type'] = "PF" # passthrough
3739 elif flavor_iface
['dedicated'] == 'no':
3740 netDict
['type'] = "VF" # siov
3741 elif flavor_iface
['dedicated'] == 'yes:sriov':
3742 netDict
['type'] = "VFnotShared" # sriov but only one sriov on the PF
3743 netDict
["mac_address"] = flavor_iface
.get("mac_address")
3745 netDict
["use"] = iface
['type']
3746 if netDict
["use"] == "data" and not netDict
.get("type"):
3747 # print "netDict", netDict
3748 # print "iface", iface
3749 e_text
= "Cannot determine the interface type PF or VF of VNF '{}' VM '{}' iface '{}'".fromat(
3750 sce_vnf
['name'], vm
['name'], iface
['internal_name'])
3751 if flavor_dict
.get('extended') == None:
3752 raise NfvoException(e_text
+ "After database migration some information is not available. \
3753 Try to delete and create the scenarios and VNFs again", httperrors
.Conflict
)
3755 raise NfvoException(e_text
, httperrors
.Internal_Server_Error
)
3756 if netDict
["use"] == "mgmt" or netDict
["use"] == "bridge":
3757 netDict
["type"] = "virtual"
3758 if iface
.get("vpci"):
3759 netDict
['vpci'] = iface
['vpci']
3760 if iface
.get("mac"):
3761 netDict
['mac_address'] = iface
['mac']
3762 if iface
.get("mac_address"):
3763 netDict
['mac_address'] = iface
['mac_address']
3764 if iface
.get("ip_address"):
3765 netDict
['ip_address'] = iface
['ip_address']
3766 if iface
.get("port-security") is not None:
3767 netDict
['port_security'] = iface
['port-security']
3768 if iface
.get("floating-ip") is not None:
3769 netDict
['floating_ip'] = iface
['floating-ip']
3770 netDict
['name'] = iface
['internal_name']
3771 if iface
['net_id'] is None:
3772 for vnf_iface
in sce_vnf
["interfaces"]:
3775 if vnf_iface
['interface_id'] == iface
['uuid']:
3776 netDict
['net_id'] = "TASK-{}".format(
3777 net2task_id
['scenario'][vnf_iface
['sce_net_id']][datacenter_id
])
3778 instance_net_id
= sce_net2instance
[vnf_iface
['sce_net_id']][datacenter_id
]
3779 task_depends_on
.append(net2task_id
['scenario'][vnf_iface
['sce_net_id']][datacenter_id
])
3782 netDict
['net_id'] = "TASK-{}".format(net2task_id
[sce_vnf
['uuid']][iface
['net_id']])
3783 instance_net_id
= vnf_net2instance
[sce_vnf
['uuid']][iface
['net_id']]
3784 task_depends_on
.append(net2task_id
[sce_vnf
['uuid']][iface
['net_id']])
3785 # skip bridge ifaces not connected to any net
3786 if 'net_id' not in netDict
or netDict
['net_id'] == None:
3788 myVMDict
['networks'].append(netDict
)
3791 # 'instance_vm_id': instance_vm_uuid,
3792 "instance_net_id": instance_net_id
,
3793 'interface_id': iface
['uuid'],
3794 # 'vim_interface_id': ,
3795 'type': 'external' if iface
['external_name'] is not None else 'internal',
3796 'ip_address': iface
.get('ip_address'),
3797 'mac_address': iface
.get('mac'),
3798 'floating_ip': int(iface
.get('floating-ip', False)),
3799 'port_security': int(iface
.get('port-security', True))
3801 db_vm_ifaces
.append(db_vm_iface
)
3802 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3803 # print myVMDict['name']
3804 # print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
3805 # print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
3806 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3808 # We add the RO key to cloud_config if vnf will need ssh access
3809 cloud_config_vm
= cloud_config
3810 if ssh_access
and ssh_access
['required'] and ssh_access
['default-user'] and tenant
[0].get('RO_pub_key'):
3811 RO_key
= {"key-pairs": [tenant
[0]['RO_pub_key']]}
3812 cloud_config_vm
= unify_cloud_config(cloud_config_vm
, RO_key
)
3813 if vm
.get("boot_data"):
3814 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config_vm
)
3816 if myVMDict
.get('availability_zone'):
3817 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
3820 for vm_index
in range(0, vm
.get('count', 1)):
3821 vm_name
= myVMDict
['name'] + "-" + str(vm_index
+1)
3822 task_params
= (vm_name
, myVMDict
['description'], myVMDict
.get('start', None),
3823 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'], cloud_config_vm
,
3824 myVMDict
['disks'], av_index
, vnf_availability_zones
)
3825 # put interface uuid back to scenario[vnfs][vms[[interfaces]
3826 for net
in myVMDict
['networks']:
3828 for iface
in vm
['interfaces']:
3829 if net
["name"] == iface
["internal_name"]:
3830 iface
["vim_id"] = net
["vim_id"]
3832 vm_uuid
= str(uuid4())
3833 uuid_list
.append(vm_uuid
)
3836 'instance_vnf_id': vnf_uuid
,
3837 # TODO delete "vim_vm_id": vm_id,
3838 "vm_id": vm
["uuid"],
3839 "vim_name": vm_name
,
3842 db_instance_vms
.append(db_vm
)
3845 for db_vm_iface
in db_vm_ifaces
:
3846 iface_uuid
= str(uuid4())
3847 uuid_list
.append(iface_uuid
)
3848 db_vm_iface_instance
= {
3850 "instance_vm_id": vm_uuid
3852 db_vm_iface_instance
.update(db_vm_iface
)
3853 if db_vm_iface_instance
.get("ip_address"): # increment ip_address
3854 ip
= db_vm_iface_instance
.get("ip_address")
3859 ip
= ip
[i
:] + str(int(ip
[:i
]) + 1)
3860 db_vm_iface_instance
["ip_address"] = ip
3862 db_vm_iface_instance
["ip_address"] = None
3863 db_instance_interfaces
.append(db_vm_iface_instance
)
3864 myVMDict
['networks'][iface_index
]["uuid"] = iface_uuid
3868 "instance_action_id": instance_action_id
,
3869 "task_index": task_index
,
3870 "datacenter_vim_id": myvim_thread_id
,
3872 "status": "SCHEDULED",
3873 "item": "instance_vms",
3875 "extra": yaml
.safe_dump({"params": task_params
, "depends_on": task_depends_on
},
3876 default_flow_style
=True, width
=256)
3879 db_vim_actions
.append(db_vim_action
)
3880 params_out
["task_index"] = task_index
3881 params_out
["uuid_list"] = uuid_list
3884 def delete_instance(mydb
, tenant_id
, instance_id
):
3885 # print "Checking that the instance_id exists and getting the instance dictionary"
3886 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
3887 # print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
3888 tenant_id
= instanceDict
["tenant_id"]
3891 # We need to retrieve the WIM Actions now, before the instance_scenario is
3892 # deleted. The reason for that is that: ON CASCADE rules will delete the
3893 # instance_wim_nets record in the database
3894 wim_actions
= wim_engine
.delete_actions(instance_scenario_id
=instance_id
)
3897 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
3898 # 1. Delete from Database
3899 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
3901 # 2. delete from VIM
3905 vimthread_affected
= {}
3906 net2vm_dependencies
= {}
3909 instance_action_id
= get_task_id()
3911 db_instance_action
= {
3912 "uuid": instance_action_id
, # same uuid for the instance and the action on create
3913 "tenant_id": tenant_id
,
3914 "instance_id": instance_id
,
3915 "description": "DELETE",
3916 # "number_tasks": 0 # filled bellow
3921 for sce_vnf
in instanceDict
['vnfs']:
3922 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
3923 vimthread_affected
[sce_vnf
["datacenter_tenant_id"]] = None
3924 if datacenter_key
not in myvims
:
3926 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
3927 except NfvoException
as e
:
3928 logger
.error(str(e
))
3930 myvim_threads
[datacenter_key
] = myvim_thread
3931 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
3932 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
3934 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
3935 sce_vnf
["datacenter_tenant_id"]))
3936 myvims
[datacenter_key
] = None
3938 myvims
[datacenter_key
] = vims
.values()[0]
3939 myvim
= myvims
[datacenter_key
]
3940 myvim_thread
= myvim_threads
[datacenter_key
]
3941 for vm
in sce_vnf
['vms']:
3943 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
3946 "instance_action_id": instance_action_id
,
3947 "task_index": task_index
,
3948 "datacenter_vim_id": sce_vnf
["datacenter_tenant_id"],
3950 "status": "SCHEDULED",
3951 "item": "instance_vms",
3952 "item_id": vm
["uuid"],
3953 "extra": yaml
.safe_dump({"params": vm
["interfaces"]},
3954 default_flow_style
=True, width
=256)
3956 db_vim_actions
.append(db_vim_action
)
3957 for interface
in vm
["interfaces"]:
3958 if not interface
.get("instance_net_id"):
3960 if interface
["instance_net_id"] not in net2vm_dependencies
:
3961 net2vm_dependencies
[interface
["instance_net_id"]] = []
3962 net2vm_dependencies
[interface
["instance_net_id"]].append(task_index
)
3967 for net
in instanceDict
['nets']:
3968 vimthread_affected
[net
["datacenter_tenant_id"]] = None
3969 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
3970 if datacenter_key
not in myvims
:
3972 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
3973 except NfvoException
as e
:
3974 logger
.error(str(e
))
3976 myvim_threads
[datacenter_key
] = myvim_thread
3977 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
3978 datacenter_tenant_id
=net
["datacenter_tenant_id"])
3980 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
3981 myvims
[datacenter_key
] = None
3983 myvims
[datacenter_key
] = vims
.values()[0]
3984 myvim
= myvims
[datacenter_key
]
3985 myvim_thread
= myvim_threads
[datacenter_key
]
3988 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
3990 extra
= {"params": (net
['vim_net_id'], net
['sdn_net_id'])}
3991 if net2vm_dependencies
.get(net
["uuid"]):
3992 extra
["depends_on"] = net2vm_dependencies
[net
["uuid"]]
3994 "instance_action_id": instance_action_id
,
3995 "task_index": task_index
,
3996 "datacenter_vim_id": net
["datacenter_tenant_id"],
3998 "status": "SCHEDULED",
3999 "item": "instance_nets",
4000 "item_id": net
["uuid"],
4001 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4004 db_vim_actions
.append(db_vim_action
)
4006 # 2.3 deleting VNFFGs
4008 for sfp
in instanceDict
.get('sfps', ()):
4009 vimthread_affected
[sfp
["datacenter_tenant_id"]] = None
4010 datacenter_key
= (sfp
["datacenter_id"], sfp
["datacenter_tenant_id"])
4011 if datacenter_key
not in myvims
:
4013 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sfp
["datacenter_id"], sfp
["datacenter_tenant_id"])
4014 except NfvoException
as e
:
4015 logger
.error(str(e
))
4017 myvim_threads
[datacenter_key
] = myvim_thread
4018 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sfp
["datacenter_id"],
4019 datacenter_tenant_id
=sfp
["datacenter_tenant_id"])
4021 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfp
["datacenter_id"], sfp
["datacenter_tenant_id"]))
4022 myvims
[datacenter_key
] = None
4024 myvims
[datacenter_key
] = vims
.values()[0]
4025 myvim
= myvims
[datacenter_key
]
4026 myvim_thread
= myvim_threads
[datacenter_key
]
4029 error_msg
+= "\n vim_sfp_id={} cannot be deleted because datacenter={} not found".format(sfp
['vim_sfp_id'], sfp
["datacenter_id"])
4031 extra
= {"params": (sfp
['vim_sfp_id'])}
4033 "instance_action_id": instance_action_id
,
4034 "task_index": task_index
,
4035 "datacenter_vim_id": sfp
["datacenter_tenant_id"],
4037 "status": "SCHEDULED",
4038 "item": "instance_sfps",
4039 "item_id": sfp
["uuid"],
4040 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4043 db_vim_actions
.append(db_vim_action
)
4045 for sf
in instanceDict
.get('sfs', ()):
4046 vimthread_affected
[sf
["datacenter_tenant_id"]] = None
4047 datacenter_key
= (sf
["datacenter_id"], sf
["datacenter_tenant_id"])
4048 if datacenter_key
not in myvims
:
4050 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sf
["datacenter_id"], sf
["datacenter_tenant_id"])
4051 except NfvoException
as e
:
4052 logger
.error(str(e
))
4054 myvim_threads
[datacenter_key
] = myvim_thread
4055 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sf
["datacenter_id"],
4056 datacenter_tenant_id
=sf
["datacenter_tenant_id"])
4058 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sf
["datacenter_id"], sf
["datacenter_tenant_id"]))
4059 myvims
[datacenter_key
] = None
4061 myvims
[datacenter_key
] = vims
.values()[0]
4062 myvim
= myvims
[datacenter_key
]
4063 myvim_thread
= myvim_threads
[datacenter_key
]
4066 error_msg
+= "\n vim_sf_id={} cannot be deleted because datacenter={} not found".format(sf
['vim_sf_id'], sf
["datacenter_id"])
4068 extra
= {"params": (sf
['vim_sf_id'])}
4070 "instance_action_id": instance_action_id
,
4071 "task_index": task_index
,
4072 "datacenter_vim_id": sf
["datacenter_tenant_id"],
4074 "status": "SCHEDULED",
4075 "item": "instance_sfs",
4076 "item_id": sf
["uuid"],
4077 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4080 db_vim_actions
.append(db_vim_action
)
4082 for sfi
in instanceDict
.get('sfis', ()):
4083 vimthread_affected
[sfi
["datacenter_tenant_id"]] = None
4084 datacenter_key
= (sfi
["datacenter_id"], sfi
["datacenter_tenant_id"])
4085 if datacenter_key
not in myvims
:
4087 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sfi
["datacenter_id"], sfi
["datacenter_tenant_id"])
4088 except NfvoException
as e
:
4089 logger
.error(str(e
))
4091 myvim_threads
[datacenter_key
] = myvim_thread
4092 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sfi
["datacenter_id"],
4093 datacenter_tenant_id
=sfi
["datacenter_tenant_id"])
4095 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfi
["datacenter_id"], sfi
["datacenter_tenant_id"]))
4096 myvims
[datacenter_key
] = None
4098 myvims
[datacenter_key
] = vims
.values()[0]
4099 myvim
= myvims
[datacenter_key
]
4100 myvim_thread
= myvim_threads
[datacenter_key
]
4103 error_msg
+= "\n vim_sfi_id={} cannot be deleted because datacenter={} not found".format(sfi
['vim_sfi_id'], sfi
["datacenter_id"])
4105 extra
= {"params": (sfi
['vim_sfi_id'])}
4107 "instance_action_id": instance_action_id
,
4108 "task_index": task_index
,
4109 "datacenter_vim_id": sfi
["datacenter_tenant_id"],
4111 "status": "SCHEDULED",
4112 "item": "instance_sfis",
4113 "item_id": sfi
["uuid"],
4114 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4117 db_vim_actions
.append(db_vim_action
)
4119 for classification
in instanceDict
['classifications']:
4120 vimthread_affected
[classification
["datacenter_tenant_id"]] = None
4121 datacenter_key
= (classification
["datacenter_id"], classification
["datacenter_tenant_id"])
4122 if datacenter_key
not in myvims
:
4124 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, classification
["datacenter_id"], classification
["datacenter_tenant_id"])
4125 except NfvoException
as e
:
4126 logger
.error(str(e
))
4128 myvim_threads
[datacenter_key
] = myvim_thread
4129 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=classification
["datacenter_id"],
4130 datacenter_tenant_id
=classification
["datacenter_tenant_id"])
4132 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(classification
["datacenter_id"], classification
["datacenter_tenant_id"]))
4133 myvims
[datacenter_key
] = None
4135 myvims
[datacenter_key
] = vims
.values()[0]
4136 myvim
= myvims
[datacenter_key
]
4137 myvim_thread
= myvim_threads
[datacenter_key
]
4140 error_msg
+= "\n vim_classification_id={} cannot be deleted because datacenter={} not found".format(classification
['vim_classification_id'], classification
["datacenter_id"])
4142 extra
= {"params": (classification
['vim_classification_id'])}
4144 "instance_action_id": instance_action_id
,
4145 "task_index": task_index
,
4146 "datacenter_vim_id": classification
["datacenter_tenant_id"],
4148 "status": "SCHEDULED",
4149 "item": "instance_classifications",
4150 "item_id": classification
["uuid"],
4151 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
4154 db_vim_actions
.append(db_vim_action
)
4156 db_instance_action
["number_tasks"] = task_index
4159 wim_actions
, db_instance_action
= (
4160 wim_engine
.incorporate_actions(wim_actions
, db_instance_action
))
4164 {"instance_actions": db_instance_action
},
4165 {"vim_wim_actions": db_vim_actions
+ wim_actions
}
4168 logger
.debug("delete_instance done DB tables: %s",
4169 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
4170 mydb
.new_rows(db_tables
, ())
4171 for myvim_thread_id
in vimthread_affected
.keys():
4172 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
4174 wim_engine
.dispatch(wim_actions
)
4176 if len(error_msg
) > 0:
4177 return 'action_id={} instance {} deleted but some elements could not be deleted, or already deleted '\
4178 '(error: 404) from VIM: {}'.format(instance_action_id
, message
, error_msg
)
4180 return "action_id={} instance {} deleted".format(instance_action_id
, message
)
4182 def get_instance_id(mydb
, tenant_id
, instance_id
):
4184 #check valid tenant_id
4185 check_tenant(mydb
, tenant_id
)
4188 instance_dict
= mydb
.get_instance_scenario(instance_id
, tenant_id
, verbose
=True)
4189 for net
in instance_dict
["nets"]:
4190 if net
.get("sdn_net_id"):
4191 net_sdn
= ovim
.show_network(net
["sdn_net_id"])
4193 "admin_state_up": net_sdn
.get("admin_state_up"),
4194 "flows": net_sdn
.get("flows"),
4195 "last_error": net_sdn
.get("last_error"),
4196 "ports": net_sdn
.get("ports"),
4197 "type": net_sdn
.get("type"),
4198 "status": net_sdn
.get("status"),
4199 "vlan": net_sdn
.get("vlan"),
4201 return instance_dict
4203 @deprecated("Instance is automatically refreshed by vim_threads")
4204 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
4205 '''Refreshes a scenario instance. It modifies instanceDict'''
4207 - 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
4210 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
4211 # #print "nfvo.refresh_instance begins"
4212 # #print json.dumps(instanceDict, indent=4)
4214 # #print "Getting the VIM URL and the VIM tenant_id"
4217 # # 1. Getting VIM vm and net list
4218 # vms_updated = [] #List of VM instance uuids in openmano that were updated
4221 # for sce_vnf in instanceDict['vnfs']:
4222 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
4223 # if datacenter_key not in vm_list:
4224 # vm_list[datacenter_key] = []
4225 # if datacenter_key not in myvims:
4226 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
4227 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
4228 # if len(vims) == 0:
4229 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
4230 # myvims[datacenter_key] = None
4232 # myvims[datacenter_key] = vims.values()[0]
4233 # for vm in sce_vnf['vms']:
4234 # vm_list[datacenter_key].append(vm['vim_vm_id'])
4235 # vms_notupdated.append(vm["uuid"])
4237 # nets_updated = [] #List of VM instance uuids in openmano that were updated
4238 # nets_notupdated=[]
4240 # for net in instanceDict['nets']:
4241 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
4242 # if datacenter_key not in net_list:
4243 # net_list[datacenter_key] = []
4244 # if datacenter_key not in myvims:
4245 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
4246 # datacenter_tenant_id=net["datacenter_tenant_id"])
4247 # if len(vims) == 0:
4248 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
4249 # myvims[datacenter_key] = None
4251 # myvims[datacenter_key] = vims.values()[0]
4253 # net_list[datacenter_key].append(net['vim_net_id'])
4254 # nets_notupdated.append(net["uuid"])
4256 # # 1. Getting the status of all VMs
4258 # for datacenter_key in myvims:
4259 # if not vm_list.get(datacenter_key):
4263 # if not myvims[datacenter_key]:
4264 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
4267 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
4269 # except vimconn.vimconnException as e:
4270 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
4271 # failed_message = str(e)
4273 # for vm in vm_list[datacenter_key]:
4274 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
4276 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
4277 # for sce_vnf in instanceDict['vnfs']:
4278 # for vm in sce_vnf['vms']:
4279 # vm_id = vm['vim_vm_id']
4280 # interfaces = vm_dict[vm_id].pop('interfaces', [])
4281 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
4282 # has_mgmt_iface = False
4283 # for iface in vm["interfaces"]:
4284 # if iface["type"]=="mgmt":
4285 # has_mgmt_iface = True
4286 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
4287 # vm_dict[vm_id]['status'] = "ACTIVE"
4288 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
4289 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
4290 # 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'):
4291 # vm['status'] = vm_dict[vm_id]['status']
4292 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
4293 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
4294 # # 2.1. Update in openmano DB the VMs whose status changed
4296 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
4297 # vms_notupdated.remove(vm["uuid"])
4299 # vms_updated.append(vm["uuid"])
4300 # except db_base_Exception as e:
4301 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
4302 # # 2.2. Update in openmano DB the interface VMs
4303 # for interface in interfaces:
4304 # #translate from vim_net_id to instance_net_id
4305 # network_id_list=[]
4306 # for net in instanceDict['nets']:
4307 # if net["vim_net_id"] == interface["vim_net_id"]:
4308 # network_id_list.append(net["uuid"])
4309 # if not network_id_list:
4311 # del interface["vim_net_id"]
4313 # for network_id in network_id_list:
4314 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
4315 # except db_base_Exception as e:
4316 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
4318 # # 3. Getting the status of all nets
4320 # for datacenter_key in myvims:
4321 # if not net_list.get(datacenter_key):
4324 # failed_message = ""
4325 # if not myvims[datacenter_key]:
4326 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
4329 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
4331 # except vimconn.vimconnException as e:
4332 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
4333 # failed_message = str(e)
4335 # for net in net_list[datacenter_key]:
4336 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
4338 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
4339 # # TODO: update nets inside a vnf
4340 # for net in instanceDict['nets']:
4341 # net_id = net['vim_net_id']
4342 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
4343 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
4344 # 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'):
4345 # net['status'] = net_dict[net_id]['status']
4346 # net['error_msg'] = net_dict[net_id].get('error_msg')
4347 # net['vim_info'] = net_dict[net_id].get('vim_info')
4348 # # 5.1. Update in openmano DB the nets whose status changed
4350 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
4351 # nets_notupdated.remove(net["uuid"])
4353 # nets_updated.append(net["uuid"])
4354 # except db_base_Exception as e:
4355 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
4357 # # Returns appropriate output
4358 # #print "nfvo.refresh_instance finishes"
4359 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
4360 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
4361 instance_id
= instanceDict
['uuid']
4362 # if len(vms_notupdated)+len(nets_notupdated)>0:
4363 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
4364 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
4366 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
4368 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
4369 #print "Checking that the instance_id exists and getting the instance dictionary"
4370 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
4371 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
4373 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
4374 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
4376 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), httperrors
.Not_Found
)
4377 myvim
= vims
.values()[0]
4382 myvim_threads_id
= {}
4383 if action_dict
.get("vdu-scaling"):
4384 db_instance_vms
= []
4386 db_instance_interfaces
= []
4387 instance_action_id
= get_task_id()
4388 db_instance_action
= {
4389 "uuid": instance_action_id
, # same uuid for the instance and the action on create
4390 "tenant_id": nfvo_tenant
,
4391 "instance_id": instance_id
,
4392 "description": "SCALE",
4394 vm_result
["instance_action_id"] = instance_action_id
4396 for vdu
in action_dict
["vdu-scaling"]:
4397 vdu_id
= vdu
.get("vdu-id")
4398 osm_vdu_id
= vdu
.get("osm_vdu_id")
4399 member_vnf_index
= vdu
.get("member-vnf-index")
4400 vdu_count
= vdu
.get("count", 1)
4402 target_vm
= mydb
.get_rows(
4403 FROM
="instance_vms as vms join instance_vnfs as vnfs on vms.instance_vnf_id=vnfs.uuid",
4404 WHERE
={"vms.uuid": vdu_id
},
4405 ORDER_BY
="vms.created_at"
4408 raise NfvoException("Cannot find the vdu with id {}".format(vdu_id
), httperrors
.Not_Found
)
4410 if not osm_vdu_id
and not member_vnf_index
:
4411 raise NfvoException("Invalid imput vdu parameters. Must supply either 'vdu-id' of 'osm_vdu_id','member-vnf-index'")
4412 target_vm
= mydb
.get_rows(
4413 # SELECT=("ivms.uuid", "ivnfs.datacenter_id", "ivnfs.datacenter_tenant_id"),
4414 FROM
="instance_vms as ivms join instance_vnfs as ivnfs on ivms.instance_vnf_id=ivnfs.uuid"\
4415 " join sce_vnfs as svnfs on ivnfs.sce_vnf_id=svnfs.uuid"\
4416 " join vms on ivms.vm_id=vms.uuid",
4417 WHERE
={"vms.osm_id": osm_vdu_id
, "svnfs.member_vnf_index": member_vnf_index
},
4418 ORDER_BY
="ivms.created_at"
4421 raise NfvoException("Cannot find the vdu with osm_vdu_id {} and member-vnf-index {}".format(osm_vdu_id
, member_vnf_index
), httperrors
.Not_Found
)
4422 vdu_id
= target_vm
[-1]["uuid"]
4423 vm_result
[vdu_id
] = {"created": [], "deleted": [], "description": "scheduled"}
4424 target_vm
= target_vm
[-1]
4425 datacenter
= target_vm
["datacenter_id"]
4426 myvim_threads_id
[datacenter
], _
= get_vim_thread(mydb
, nfvo_tenant
, datacenter
)
4427 if vdu
["type"] == "delete":
4429 vm_interfaces
= None
4430 for sce_vnf
in instanceDict
['vnfs']:
4431 for vm
in sce_vnf
['vms']:
4432 if vm
["uuid"] == vdu_id
:
4433 vm_interfaces
= vm
["interfaces"]
4437 "instance_action_id": instance_action_id
,
4438 "task_index": task_index
,
4439 "datacenter_vim_id": target_vm
["datacenter_tenant_id"],
4441 "status": "SCHEDULED",
4442 "item": "instance_vms",
4443 "item_id": target_vm
["uuid"],
4444 "extra": yaml
.safe_dump({"params": vm_interfaces
},
4445 default_flow_style
=True, width
=256)
4448 db_vim_actions
.append(db_vim_action
)
4449 vm_result
[vdu_id
]["deleted"].append(vdu_id
)
4450 # delete from database
4451 db_instance_vms
.append({"TO-DELETE": vdu_id
})
4453 else: # vdu["type"] == "create":
4455 where
= {"item": "instance_vms", "item_id": target_vm
["uuid"], "action": "CREATE"}
4457 vim_action_to_clone
= mydb
.get_rows(FROM
="vim_actions", WHERE
=where
)
4458 if not vim_action_to_clone
:
4459 raise NfvoException("Cannot find the vim_action at database with {}".format(where
), httperrors
.Internal_Server_Error
)
4460 vim_action_to_clone
= vim_action_to_clone
[0]
4461 extra
= yaml
.safe_load(vim_action_to_clone
["extra"])
4463 # generate a new depends_on. Convert format TASK-Y into new format TASK-ACTION-XXXX.XXXX.Y
4464 # TODO do the same for flavor and image when available
4465 task_depends_on
= []
4466 task_params
= extra
["params"]
4467 task_params_networks
= deepcopy(task_params
[5])
4468 for iface
in task_params
[5]:
4469 if iface
["net_id"].startswith("TASK-"):
4470 if "." not in iface
["net_id"]:
4471 task_depends_on
.append("{}.{}".format(vim_action_to_clone
["instance_action_id"],
4472 iface
["net_id"][5:]))
4473 iface
["net_id"] = "TASK-{}.{}".format(vim_action_to_clone
["instance_action_id"],
4474 iface
["net_id"][5:])
4476 task_depends_on
.append(iface
["net_id"][5:])
4477 if "mac_address" in iface
:
4478 del iface
["mac_address"]
4480 vm_ifaces_to_clone
= mydb
.get_rows(FROM
="instance_interfaces", WHERE
={"instance_vm_id": target_vm
["uuid"]})
4481 for index
in range(0, vdu_count
):
4482 vm_uuid
= str(uuid4())
4483 vm_name
= target_vm
.get('vim_name')
4485 suffix
= vm_name
.rfind("-")
4486 vm_name
= vm_name
[:suffix
+1] + str(1 + int(vm_name
[suffix
+1:]))
4491 'instance_vnf_id': target_vm
['instance_vnf_id'],
4492 'vm_id': target_vm
['vm_id'],
4495 db_instance_vms
.append(db_instance_vm
)
4497 for vm_iface
in vm_ifaces_to_clone
:
4498 iface_uuid
= str(uuid4())
4499 iface2iface
[vm_iface
["uuid"]] = iface_uuid
4502 'instance_vm_id': vm_uuid
,
4503 "instance_net_id": vm_iface
["instance_net_id"],
4504 'interface_id': vm_iface
['interface_id'],
4505 'type': vm_iface
['type'],
4506 'floating_ip': vm_iface
['floating_ip'],
4507 'port_security': vm_iface
['port_security']
4509 db_instance_interfaces
.append(db_vm_iface
)
4510 task_params_copy
= deepcopy(task_params
)
4511 for iface
in task_params_copy
[5]:
4512 iface
["uuid"] = iface2iface
[iface
["uuid"]]
4513 # increment ip_address
4514 if "ip_address" in iface
:
4515 ip
= iface
.get("ip_address")
4520 ip
= ip
[i
:] + str(int(ip
[:i
]) + 1)
4521 iface
["ip_address"] = ip
4523 iface
["ip_address"] = None
4525 task_params_copy
[0] = vm_name
4527 "instance_action_id": instance_action_id
,
4528 "task_index": task_index
,
4529 "datacenter_vim_id": vim_action_to_clone
["datacenter_vim_id"],
4531 "status": "SCHEDULED",
4532 "item": "instance_vms",
4536 # TODO examinar parametros, quitar MAC o incrementar. Incrementar IP y colocar las dependencias con ACTION-asdfasd.
4539 "extra": yaml
.safe_dump({"params": task_params_copy
, "depends_on": task_depends_on
}, default_flow_style
=True, width
=256)
4542 db_vim_actions
.append(db_vim_action
)
4543 vm_result
[vdu_id
]["created"].append(vm_uuid
)
4545 db_instance_action
["number_tasks"] = task_index
4547 {"instance_vms": db_instance_vms
},
4548 {"instance_interfaces": db_instance_interfaces
},
4549 {"instance_actions": db_instance_action
},
4551 # {"instance_sfis": db_instance_sfis},
4552 # {"instance_sfs": db_instance_sfs},
4553 # {"instance_classifications": db_instance_classifications},
4554 # {"instance_sfps": db_instance_sfps},
4555 {"vim_actions": db_vim_actions
}
4557 logger
.debug("create_vdu done DB tables: %s",
4558 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
4559 mydb
.new_rows(db_tables
, [])
4560 for myvim_thread
in myvim_threads_id
.values():
4561 vim_threads
["running"][myvim_thread
].insert_task(db_vim_actions
)
4565 input_vnfs
= action_dict
.pop("vnfs", [])
4566 input_vms
= action_dict
.pop("vms", [])
4567 action_over_all
= True if not input_vnfs
and not input_vms
else False
4568 for sce_vnf
in instanceDict
['vnfs']:
4569 for vm
in sce_vnf
['vms']:
4570 if not action_over_all
and sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
4571 sce_vnf
['member_vnf_index'] not in input_vnfs
and \
4572 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
4575 if "add_public_key" in action_dict
:
4577 if sce_vnf
.get('mgmt_access'):
4578 mgmt_access
= yaml
.load(sce_vnf
['mgmt_access'])
4579 ssh_access
= mgmt_access
['config-access']['ssh-access']
4580 tenant
= mydb
.get_rows_by_id('nfvo_tenants', nfvo_tenant
)
4582 if ssh_access
['required'] and ssh_access
['default-user']:
4583 if 'ip_address' in vm
:
4584 mgmt_ip
= vm
['ip_address'].split(';')
4585 password
= mgmt_access
['config-access'].get('password')
4586 priv_RO_key
= decrypt_key(tenant
[0]['encrypted_RO_priv_key'], tenant
[0]['uuid'])
4587 myvim
.inject_user_key(mgmt_ip
[0], ssh_access
['default-user'],
4588 action_dict
['add_public_key'],
4589 password
=password
, ro_key
=priv_RO_key
)
4591 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4592 httperrors
.Internal_Server_Error
)
4594 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4595 httperrors
.Internal_Server_Error
)
4597 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
4598 httperrors
.Internal_Server_Error
)
4600 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
4601 if "console" in action_dict
:
4602 if not global_config
["http_console_proxy"]:
4603 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4604 "description": "{protocol}//{ip}:{port}/{suffix}".format(
4605 protocol
=data
["protocol"],
4606 ip
= data
["server"],
4607 port
= data
["port"],
4608 suffix
= data
["suffix"]),
4612 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
4613 vm_result
[ vm
['uuid'] ] = {"vim_result": -httperrors
.Unauthorized
,
4614 "description": "this console is only reachable by local interface",
4619 #print "console data", data
4621 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
4622 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
4623 "description": "{protocol}//{ip}:{port}/{suffix}".format(
4624 protocol
=data
["protocol"],
4625 ip
= global_config
["http_console_host"],
4626 port
= console_thread
.port
,
4627 suffix
= data
["suffix"]),
4631 except NfvoException
as e
:
4632 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
4636 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
4638 except vimconn
.vimconnException
as e
:
4639 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
4642 if vm_ok
==0: #all goes wrong
4647 def instance_action_get(mydb
, nfvo_tenant
, instance_id
, action_id
):
4649 if nfvo_tenant
and nfvo_tenant
!= "any":
4650 filter["tenant_id"] = nfvo_tenant
4651 if instance_id
and instance_id
!= "any":
4652 filter["instance_id"] = instance_id
4654 filter["uuid"] = action_id
4655 rows
= mydb
.get_rows(FROM
="instance_actions", WHERE
=filter)
4658 raise NfvoException("Not found any action with this criteria", httperrors
.Not_Found
)
4659 vim_wim_actions
= mydb
.get_rows(FROM
="vim_wim_actions", WHERE
={"instance_action_id": action_id
})
4660 rows
[0]["vim_wim_actions"] = vim_wim_actions
4661 return {"actions": rows
}
4664 def create_or_use_console_proxy_thread(console_server
, console_port
):
4665 #look for a non-used port
4666 console_thread_key
= console_server
+ ":" + str(console_port
)
4667 if console_thread_key
in global_config
["console_thread"]:
4668 #global_config["console_thread"][console_thread_key].start_timeout()
4669 return global_config
["console_thread"][console_thread_key
]
4671 for port
in global_config
["console_port_iterator"]():
4672 #print "create_or_use_console_proxy_thread() port:", port
4673 if port
in global_config
["console_ports"]:
4676 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
4678 global_config
["console_thread"][console_thread_key
] = clithread
4679 global_config
["console_ports"][port
] = console_thread_key
4681 except cli
.ConsoleProxyExceptionPortUsed
as e
:
4682 #port used, try with onoher
4684 except cli
.ConsoleProxyException
as e
:
4685 raise NfvoException(str(e
), httperrors
.Bad_Request
)
4686 raise NfvoException("Not found any free 'http_console_ports'", httperrors
.Conflict
)
4689 def check_tenant(mydb
, tenant_id
):
4690 '''check that tenant exists at database'''
4691 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
4693 raise NfvoException("tenant '{}' not found".format(tenant_id
), httperrors
.Not_Found
)
4696 def new_tenant(mydb
, tenant_dict
):
4698 tenant_uuid
= str(uuid4())
4699 tenant_dict
['uuid'] = tenant_uuid
4701 pub_key
, priv_key
= create_RO_keypair(tenant_uuid
)
4702 tenant_dict
['RO_pub_key'] = pub_key
4703 tenant_dict
['encrypted_RO_priv_key'] = priv_key
4704 mydb
.new_row("nfvo_tenants", tenant_dict
, confidential_data
=True)
4705 except db_base_Exception
as e
:
4706 raise NfvoException("Error creating the new tenant: {} ".format(tenant_dict
['name']) + str(e
), e
.http_code
)
4709 def delete_tenant(mydb
, tenant
):
4710 #get nfvo_tenant info
4712 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
4713 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
4714 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
4717 def new_datacenter(mydb
, datacenter_descriptor
):
4718 sdn_port_mapping
= None
4719 if "config" in datacenter_descriptor
:
4720 sdn_port_mapping
= datacenter_descriptor
["config"].pop("sdn-port-mapping", None)
4721 datacenter_descriptor
["config"] = yaml
.safe_dump(datacenter_descriptor
["config"], default_flow_style
=True,
4723 # Check that datacenter-type is correct
4724 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
4725 # module_info = None
4727 module
= "vimconn_" + datacenter_type
4728 pkg
= __import__("osm_ro." + module
)
4729 # vim_conn = getattr(pkg, module)
4730 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
4731 except (IOError, ImportError):
4732 # if module_info and module_info[0]:
4733 # file.close(module_info[0])
4734 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}.py' not installed".format(datacenter_type
,
4736 httperrors
.Bad_Request
)
4738 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True, confidential_data
=True)
4739 if sdn_port_mapping
:
4741 datacenter_sdn_port_mapping_set(mydb
, None, datacenter_id
, sdn_port_mapping
)
4742 except Exception as e
:
4743 mydb
.delete_row_by_id("datacenters", datacenter_id
) # Rollback
4745 return datacenter_id
4748 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
4749 # obtain data, check that only one exist
4750 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
4753 datacenter_id
= datacenter
['uuid']
4754 where
= {'uuid': datacenter
['uuid']}
4755 remove_port_mapping
= False
4756 new_sdn_port_mapping
= None
4757 if "config" in datacenter_descriptor
:
4758 if datacenter_descriptor
['config'] != None:
4760 new_config_dict
= datacenter_descriptor
["config"]
4761 if "sdn-port-mapping" in new_config_dict
:
4762 remove_port_mapping
= True
4763 new_sdn_port_mapping
= new_config_dict
.pop("sdn-port-mapping")
4764 # delete null fields
4766 for k
in new_config_dict
:
4767 if new_config_dict
[k
] is None:
4769 if k
== 'sdn-controller':
4770 remove_port_mapping
= True
4772 config_text
= datacenter
.get("config")
4775 config_dict
= yaml
.load(config_text
)
4776 config_dict
.update(new_config_dict
)
4777 # delete null fields
4780 except Exception as e
:
4781 raise NfvoException("Bad format at datacenter:config " + str(e
), httperrors
.Bad_Request
)
4783 datacenter_descriptor
["config"] = yaml
.safe_dump(config_dict
, default_flow_style
=True, width
=256)
4785 datacenter_descriptor
["config"] = None
4786 if remove_port_mapping
:
4788 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_id
)
4789 except ovimException
as e
:
4790 raise NfvoException("Error deleting datacenter-port-mapping " + str(e
), HTTP_Conflict
)
4792 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
4793 if new_sdn_port_mapping
:
4795 datacenter_sdn_port_mapping_set(mydb
, None, datacenter_id
, new_sdn_port_mapping
)
4796 except ovimException
as e
:
4798 mydb
.update_rows('datacenters', datacenter
, where
)
4799 raise NfvoException("Error adding datacenter-port-mapping " + str(e
), HTTP_Conflict
)
4800 return datacenter_id
4803 def delete_datacenter(mydb
, datacenter
):
4804 #get nfvo_tenant info
4805 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
4806 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
4808 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_dict
['uuid'])
4809 except ovimException
as e
:
4810 raise NfvoException("Error deleting datacenter-port-mapping " + str(e
))
4811 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
4814 def create_vim_account(mydb
, nfvo_tenant
, datacenter_id
, name
=None, vim_id
=None, vim_tenant
=None, vim_tenant_name
=None,
4815 vim_username
=None, vim_password
=None, config
=None):
4816 # get datacenter info
4818 if not datacenter_id
:
4820 raise NfvoException("You must provide 'vim_id", http_code
=httperrors
.Bad_Request
)
4821 datacenter_id
= vim_id
4822 datacenter_id
, datacenter_name
= get_datacenter_uuid(mydb
, None, datacenter_id
)
4824 create_vim_tenant
= True if not vim_tenant
and not vim_tenant_name
else False
4826 # get nfvo_tenant info
4827 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
4828 if vim_tenant_name
==None:
4829 vim_tenant_name
=tenant_dict
['name']
4831 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
4832 # #check that this association does not exist before
4833 # tenants_datacenters = mydb.get_rows(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict)
4834 # if len(tenants_datacenters)>0:
4835 # raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id, tenant_dict['uuid']), httperrors.Conflict)
4837 vim_tenant_id_exist_atdb
=False
4838 if not create_vim_tenant
:
4839 where_
={"datacenter_id": datacenter_id
}
4840 if vim_tenant
!=None:
4841 where_
["vim_tenant_id"] = vim_tenant
4842 if vim_tenant_name
!=None:
4843 where_
["vim_tenant_name"] = vim_tenant_name
4844 #check if vim_tenant_id is already at database
4845 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
4846 if len(datacenter_tenants_dict
)>=1:
4847 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
4848 vim_tenant_id_exist_atdb
=True
4849 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
4851 datacenter_tenants_dict
= {}
4852 #insert at table datacenter_tenants
4853 else: #if vim_tenant==None:
4854 #create tenant at VIM if not provided
4856 _
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
, vim_user
=vim_username
,
4857 vim_passwd
=vim_password
)
4858 datacenter_name
= myvim
["name"]
4859 vim_tenant
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
4860 except vimconn
.vimconnException
as e
:
4861 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), httperrors
.Internal_Server_Error
)
4862 datacenter_tenants_dict
= {}
4863 datacenter_tenants_dict
["created"]="true"
4865 #fill datacenter_tenants table
4866 if not vim_tenant_id_exist_atdb
:
4867 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant
4868 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
4869 datacenter_tenants_dict
["user"] = vim_username
4870 datacenter_tenants_dict
["passwd"] = vim_password
4871 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
4873 datacenter_tenants_dict
["name"] = name
4875 datacenter_tenants_dict
["name"] = datacenter_name
4877 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
4878 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True, confidential_data
=True)
4879 datacenter_tenants_dict
["uuid"] = id_
4881 #fill tenants_datacenters table
4882 datacenter_tenant_id
= datacenter_tenants_dict
["uuid"]
4883 tenants_datacenter_dict
["datacenter_tenant_id"] = datacenter_tenant_id
4884 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
4887 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
4888 new_thread
= vim_thread
.vim_thread(task_lock
, thread_name
, datacenter_name
, datacenter_tenant_id
,
4889 db
=db
, db_lock
=db_lock
, ovim
=ovim
)
4891 thread_id
= datacenter_tenants_dict
["uuid"]
4892 vim_threads
["running"][thread_id
] = new_thread
4894 except vimconn
.vimconnException
as e
:
4895 raise NfvoException(str(e
), httperrors
.Bad_Request
)
4898 def edit_vim_account(mydb
, nfvo_tenant
, datacenter_tenant_id
, datacenter_id
=None, name
=None, vim_tenant
=None,
4899 vim_tenant_name
=None, vim_username
=None, vim_password
=None, config
=None):
4901 # get vim_account; check is valid for this tenant
4902 from_
= "datacenter_tenants as dt JOIN tenants_datacenters as td ON dt.uuid=td.datacenter_tenant_id"
4903 where_
= {"td.nfvo_tenant_id": nfvo_tenant
}
4904 if datacenter_tenant_id
:
4905 where_
["dt.uuid"] = datacenter_tenant_id
4907 where_
["dt.datacenter_id"] = datacenter_id
4908 vim_accounts
= mydb
.get_rows(SELECT
="dt.uuid as uuid, config", FROM
=from_
, WHERE
=where_
)
4909 if not vim_accounts
:
4910 raise NfvoException("vim_account not found for this tenant", http_code
=httperrors
.Not_Found
)
4911 elif len(vim_accounts
) > 1:
4912 raise NfvoException("found more than one vim_account for this tenant", http_code
=httperrors
.Conflict
)
4913 datacenter_tenant_id
= vim_accounts
[0]["uuid"]
4914 original_config
= vim_accounts
[0]["config"]
4918 original_config_dict
= yaml
.load(original_config
)
4919 original_config_dict
.update(config
)
4920 update
["config"] = yaml
.safe_dump(original_config_dict
, default_flow_style
=True, width
=256)
4922 update_
['name'] = name
4924 update_
['vim_tenant_id'] = vim_tenant
4926 update_
['vim_tenant_name'] = vim_tenant_name
4928 update_
['user'] = vim_username
4930 update_
['passwd'] = vim_password
4932 mydb
.update_rows("datacenter_tenants", UPDATE
=update_
, WHERE
={"uuid": datacenter_tenant_id
})
4934 vim_threads
["running"][datacenter_tenant_id
].insert_task("reload")
4935 return datacenter_tenant_id
4937 def delete_vim_account(mydb
, tenant_id
, vim_account_id
, datacenter
=None):
4938 #get nfvo_tenant info
4939 if not tenant_id
or tenant_id
=="any":
4942 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
4943 tenant_uuid
= tenant_dict
['uuid']
4945 #check that this association exist before
4946 tenants_datacenter_dict
= {}
4948 datacenter_id
, _
= get_datacenter_uuid(mydb
, tenant_uuid
, datacenter
)
4949 tenants_datacenter_dict
["datacenter_id"] = datacenter_id
4950 elif vim_account_id
:
4951 tenants_datacenter_dict
["datacenter_tenant_id"] = vim_account_id
4953 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
4954 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
4955 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
4956 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), httperrors
.Not_Found
)
4958 #delete this association
4959 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
4961 #get vim_tenant info and deletes
4963 for tenant_datacenter_item
in tenant_datacenter_list
:
4964 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
4965 #try to delete vim:tenant
4967 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
4968 if vim_tenant_dict
['created']=='true':
4969 #delete tenant at VIM if created by NFVO
4971 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4972 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
4973 except vimconn
.vimconnException
as e
:
4974 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
4975 logger
.warn(warning
)
4976 except db_base_Exception
as e
:
4977 logger
.error("Cannot delete datacenter_tenants " + str(e
))
4978 pass # the error will be caused because dependencies, vim_tenant can not be deleted
4979 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
4980 thread
= vim_threads
["running"].get(thread_id
)
4982 thread
.insert_task("exit")
4983 vim_threads
["deleting"][thread_id
] = thread
4984 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
4987 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
4989 #get datacenter info
4990 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4992 if 'net-update' in action_dict
:
4994 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
4996 except vimconn
.vimconnException
as e
:
4997 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
4998 raise NfvoException(str(e
), httperrors
.Internal_Server_Error
)
4999 #update nets Change from VIM format to NFVO format
5002 net_nfvo
={'datacenter_id': datacenter_id
}
5003 net_nfvo
['name'] = net
['name']
5004 #net_nfvo['description']= net['name']
5005 net_nfvo
['vim_net_id'] = net
['id']
5006 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
5007 net_nfvo
['shared'] = net
['shared']
5008 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
5009 net_list
.append(net_nfvo
)
5010 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
5011 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
5013 elif 'net-edit' in action_dict
:
5014 net
= action_dict
['net-edit'].pop('net')
5015 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
5016 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
5017 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
5019 elif 'net-delete' in action_dict
:
5020 net
= action_dict
['net-deelte'].get('net')
5021 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
5022 result
= mydb
.delete_row(FROM
='datacenter_nets',
5023 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
5027 raise NfvoException("Unknown action " + str(action_dict
), httperrors
.Bad_Request
)
5030 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
5031 #get datacenter info
5032 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5034 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
5035 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
5036 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
5040 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
5041 #get datacenter info
5042 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5045 action_dict
= action_dict
["netmap"]
5046 if 'vim_id' in action_dict
:
5047 filter_dict
["id"] = action_dict
['vim_id']
5048 if 'vim_name' in action_dict
:
5049 filter_dict
["name"] = action_dict
['vim_name']
5051 filter_dict
["shared"] = True
5054 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
5055 except vimconn
.vimconnException
as e
:
5056 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
5057 raise NfvoException(str(e
), httperrors
.Internal_Server_Error
)
5058 if len(vim_nets
)>1 and action_dict
:
5059 raise NfvoException("more than two networks found, specify with vim_id", httperrors
.Conflict
)
5060 elif len(vim_nets
)==0: # and action_dict:
5061 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), httperrors
.Not_Found
)
5063 for net
in vim_nets
:
5064 net_nfvo
={'datacenter_id': datacenter_id
}
5065 if action_dict
and "name" in action_dict
:
5066 net_nfvo
['name'] = action_dict
['name']
5068 net_nfvo
['name'] = net
['name']
5069 #net_nfvo['description']= net['name']
5070 net_nfvo
['vim_net_id'] = net
['id']
5071 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
5072 net_nfvo
['shared'] = net
['shared']
5073 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
5075 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
5076 net_nfvo
["status"] = "OK"
5077 net_nfvo
["uuid"] = net_id
5078 except db_base_Exception
as e
:
5082 net_nfvo
["status"] = "FAIL: " + str(e
)
5083 net_list
.append(net_nfvo
)
5086 def get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
):
5087 # obtain all network data
5089 if utils
.check_valid_uuid(network_id
):
5090 filter_dict
= {"id": network_id
}
5092 filter_dict
= {"name": network_id
}
5094 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5095 network
= myvim
.get_network_list(filter_dict
=filter_dict
)
5096 except vimconn
.vimconnException
as e
:
5097 raise NfvoException("Not possible to get_sdn_net_id from VIM: {}".format(str(e
)), e
.http_code
)
5099 # ensure the network is defined
5100 if len(network
) == 0:
5101 raise NfvoException("Network {} is not present in the system".format(network_id
),
5102 httperrors
.Bad_Request
)
5104 # ensure there is only one network with the provided name
5105 if len(network
) > 1:
5106 raise NfvoException("Multiple networks present in vim identified by {}".format(network_id
), httperrors
.Bad_Request
)
5108 # ensure it is a dataplane network
5109 if network
[0]['type'] != 'data':
5112 # ensure we use the id
5113 network_id
= network
[0]['id']
5115 # search in dabase mano_db in table instance nets for the sdn_net_id that corresponds to the vim_net_id==network_id
5116 # and with instance_scenario_id==NULL
5117 #search_dict = {'vim_net_id': network_id, 'instance_scenario_id': None}
5118 search_dict
= {'vim_net_id': network_id
}
5121 #sdn_network_id = mydb.get_rows(SELECT=('sdn_net_id',), FROM='instance_nets', WHERE=search_dict)[0]['sdn_net_id']
5122 result
= mydb
.get_rows(SELECT
=('sdn_net_id',), FROM
='instance_nets', WHERE
=search_dict
)
5123 except db_base_Exception
as e
:
5124 raise NfvoException("db_base_Exception obtaining SDN network to associated to vim network {}".format(
5125 network_id
) + str(e
), e
.http_code
)
5129 if net
['sdn_net_id'] != None:
5131 sdn_net_id
= net
['sdn_net_id']
5133 if sdn_net_counter
== 0:
5135 elif sdn_net_counter
== 1:
5138 raise NfvoException("More than one SDN network is associated to vim network {}".format(
5139 network_id
), httperrors
.Internal_Server_Error
)
5141 def get_sdn_controller_id(mydb
, datacenter
):
5142 # Obtain sdn controller id
5143 config
= mydb
.get_rows(SELECT
=('config',), FROM
='datacenters', WHERE
={'uuid': datacenter
})[0].get('config', '{}')
5147 return yaml
.load(config
).get('sdn-controller')
5149 def vim_net_sdn_attach(mydb
, tenant_id
, datacenter
, network_id
, descriptor
):
5151 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
5152 if not sdn_network_id
:
5153 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
), httperrors
.Internal_Server_Error
)
5155 #Obtain sdn controller id
5156 controller_id
= get_sdn_controller_id(mydb
, datacenter
)
5157 if not controller_id
:
5158 raise NfvoException("No SDN controller is set for datacenter {}".format(datacenter
), httperrors
.Internal_Server_Error
)
5160 #Obtain sdn controller info
5161 sdn_controller
= ovim
.show_of_controller(controller_id
)
5164 'name': 'external_port',
5165 'net_id': sdn_network_id
,
5166 'ofc_id': controller_id
,
5167 'switch_dpid': sdn_controller
['dpid'],
5168 'switch_port': descriptor
['port']
5171 if 'vlan' in descriptor
:
5172 port_data
['vlan'] = descriptor
['vlan']
5173 if 'mac' in descriptor
:
5174 port_data
['mac'] = descriptor
['mac']
5176 result
= ovim
.new_port(port_data
)
5177 except ovimException
as e
:
5178 raise NfvoException("ovimException attaching SDN network {} to vim network {}".format(
5179 sdn_network_id
, network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5180 except db_base_Exception
as e
:
5181 raise NfvoException("db_base_Exception attaching SDN network to vim network {}".format(
5182 network_id
) + str(e
), e
.http_code
)
5184 return 'Port uuid: '+ result
5186 def vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, network_id
, port_id
=None):
5188 filter = {'uuid': port_id
}
5190 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
5191 if not sdn_network_id
:
5192 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
),
5193 httperrors
.Internal_Server_Error
)
5194 #in case no port_id is specified only ports marked as 'external_port' will be detached
5195 filter = {'name': 'external_port', 'net_id': sdn_network_id
}
5198 port_list
= ovim
.get_ports(columns
={'uuid'}, filter=filter)
5199 except ovimException
as e
:
5200 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
5201 httperrors
.Internal_Server_Error
)
5203 if len(port_list
) == 0:
5204 raise NfvoException("No ports attached to the network {} were found with the requested criteria".format(network_id
),
5205 httperrors
.Bad_Request
)
5208 for port
in port_list
:
5210 port_uuid_list
.append(port
['uuid'])
5211 ovim
.delete_port(port
['uuid'])
5212 except ovimException
as e
:
5213 raise NfvoException("ovimException deleting port {} for net {}. ".format(port
['uuid'], network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5215 return 'Detached ports uuid: {}'.format(','.join(port_uuid_list
))
5217 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
5218 #get datacenter info
5219 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5222 if utils
.check_valid_uuid(name
):
5223 filter_dict
["id"] = name
5225 filter_dict
["name"] = name
5227 if item
=="networks":
5228 #filter_dict['tenant_id'] = myvim['tenant_id']
5229 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
5231 if len(content
) == 0:
5232 raise NfvoException("Network {} is not present in the system. ".format(name
),
5233 httperrors
.Bad_Request
)
5235 #Update the networks with the attached ports
5237 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, net
['id'])
5238 if sdn_network_id
!= None:
5240 #port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan'}, filter={'name': 'external_port', 'net_id': sdn_network_id})
5241 port_list
= ovim
.get_ports(columns
={'uuid', 'switch_port', 'vlan','name'}, filter={'net_id': sdn_network_id
})
5242 except ovimException
as e
:
5243 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
), httperrors
.Internal_Server_Error
)
5244 #Remove field name and if port name is external_port save it as 'type'
5245 for port
in port_list
:
5246 if port
['name'] == 'external_port':
5247 port
['type'] = "External"
5249 net
['sdn_network_id'] = sdn_network_id
5250 net
['sdn_attached_ports'] = port_list
5252 elif item
=="tenants":
5253 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
5254 elif item
== "images":
5256 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
5258 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5259 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
5260 if name
and len(content
)==1:
5261 return {item
[:-1]: content
[0]}
5262 elif name
and len(content
)==0:
5263 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
5266 return {item
: content
}
5267 except vimconn
.vimconnException
as e
:
5268 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
5269 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
5272 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
5273 #get datacenter info
5274 if tenant_id
== "any":
5277 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5279 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
5280 logger
.debug("vim_action_delete vim response: " + str(content
))
5281 items
= content
.values()[0]
5282 if type(items
)==list and len(items
)==0:
5283 raise NfvoException("Not found " + item
, httperrors
.Not_Found
)
5284 elif type(items
)==list and len(items
)>1:
5285 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), httperrors
.Not_Found
)
5286 else: # it is a dict
5287 item_id
= items
["id"]
5288 item_name
= str(items
.get("name"))
5291 if item
=="networks":
5292 # If there is a SDN network associated to the vim-network, proceed to clear the relationship and delete it
5293 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, item_id
)
5294 if sdn_network_id
!= None:
5295 #Delete any port attachment to this network
5297 port_list
= ovim
.get_ports(columns
={'uuid'}, filter={'net_id': sdn_network_id
})
5298 except ovimException
as e
:
5299 raise NfvoException(
5300 "ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
5301 httperrors
.Internal_Server_Error
)
5303 # By calling one by one all ports to be detached we ensure that not only the external_ports get detached
5304 for port
in port_list
:
5305 vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, item_id
, port
['uuid'])
5307 #Delete from 'instance_nets' the correspondence between the vim-net-id and the sdn-net-id
5309 mydb
.delete_row(FROM
='instance_nets', WHERE
={'instance_scenario_id': None, 'sdn_net_id': sdn_network_id
, 'vim_net_id': item_id
})
5310 except db_base_Exception
as e
:
5311 raise NfvoException("Error deleting correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
5312 str(e
), e
.http_code
)
5314 #Delete the SDN network
5316 ovim
.delete_network(sdn_network_id
)
5317 except ovimException
as e
:
5318 logger
.error("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
), exc_info
=True)
5319 raise NfvoException("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
),
5320 httperrors
.Internal_Server_Error
)
5322 content
= myvim
.delete_network(item_id
)
5323 elif item
=="tenants":
5324 content
= myvim
.delete_tenant(item_id
)
5325 elif item
== "images":
5326 content
= myvim
.delete_image(item_id
)
5328 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5329 except vimconn
.vimconnException
as e
:
5330 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
5331 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
5333 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
5336 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
5337 #get datacenter info
5338 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
5339 if tenant_id
== "any":
5341 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
5343 if item
=="networks":
5344 net
= descriptor
["network"]
5345 net_name
= net
.pop("name")
5346 net_type
= net
.pop("type", "bridge")
5347 net_public
= net
.pop("shared", False)
5348 net_ipprofile
= net
.pop("ip_profile", None)
5349 net_vlan
= net
.pop("vlan", None)
5350 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
5352 #If the datacenter has a SDN controller defined and the network is of dataplane type, then create the sdn network
5353 if get_sdn_controller_id(mydb
, datacenter
) != None and (net_type
== 'data' or net_type
== 'ptp'):
5354 #obtain datacenter_tenant_id
5355 datacenter_tenant_id
= mydb
.get_rows(SELECT
=('uuid',),
5356 FROM
='datacenter_tenants',
5357 WHERE
={'datacenter_id': datacenter
})[0]['uuid']
5360 sdn_network
['vlan'] = net_vlan
5361 sdn_network
['type'] = net_type
5362 sdn_network
['name'] = net_name
5363 sdn_network
['region'] = datacenter_tenant_id
5364 ovim_content
= ovim
.new_network(sdn_network
)
5365 except ovimException
as e
:
5366 logger
.error("ovimException creating SDN network={} ".format(
5367 sdn_network
) + str(e
), exc_info
=True)
5368 raise NfvoException("ovimException creating SDN network={} ".format(sdn_network
) + str(e
),
5369 httperrors
.Internal_Server_Error
)
5371 # Save entry in in dabase mano_db in table instance_nets to stablish a dictionary vim_net_id <->sdn_net_id
5372 # use instance_scenario_id=None to distinguish from real instaces of nets
5373 correspondence
= {'instance_scenario_id': None,
5374 'sdn_net_id': ovim_content
,
5375 'vim_net_id': content
,
5376 'datacenter_tenant_id': datacenter_tenant_id
5379 mydb
.new_row('instance_nets', correspondence
, add_uuid
=True)
5380 except db_base_Exception
as e
:
5381 raise NfvoException("Error saving correspondence for VIM/SDN dataplane networks{}: {}".format(
5382 correspondence
, e
), e
.http_code
)
5383 elif item
=="tenants":
5384 tenant
= descriptor
["tenant"]
5385 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
5387 raise NfvoException(item
+ "?", httperrors
.Method_Not_Allowed
)
5388 except vimconn
.vimconnException
as e
:
5389 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
5391 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
5393 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
5394 data
= ovim
.new_of_controller(sdn_controller
)
5395 logger
.debug('New SDN controller created with uuid {}'.format(data
))
5398 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
5399 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
5400 msg
= 'SDN controller {} updated'.format(data
)
5404 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
5405 if controller_id
== None:
5406 data
= ovim
.get_of_controllers()
5408 data
= ovim
.show_of_controller(controller_id
)
5410 msg
= 'SDN controller list:\n {}'.format(data
)
5414 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
5415 select_
= ('uuid', 'config')
5416 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
5417 for datacenter
in datacenters
:
5418 if datacenter
['config']:
5419 config
= yaml
.load(datacenter
['config'])
5420 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
5421 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), httperrors
.Conflict
)
5423 data
= ovim
.delete_of_controller(controller_id
)
5424 msg
= 'SDN controller {} deleted'.format(data
)
5428 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
5429 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
5430 if len(controller
) < 1:
5431 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), httperrors
.Not_Found
)
5434 sdn_controller_id
= yaml
.load(controller
[0]["config"])["sdn-controller"]
5436 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), httperrors
.Bad_Request
)
5438 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
5439 switch_dpid
= sdn_controller
["dpid"]
5442 for compute_node
in sdn_port_mapping
:
5443 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
5445 element
["compute_node"] = compute_node
["compute_node"]
5446 for port
in compute_node
["ports"]:
5447 pci
= port
.get("pci")
5448 element
["switch_port"] = port
.get("switch_port")
5449 element
["switch_mac"] = port
.get("switch_mac")
5450 if not pci
or not (element
["switch_port"] or element
["switch_mac"]):
5451 raise NfvoException ("The mapping must contain the 'pci' and at least one of the elements 'switch_port'"
5452 " or 'switch_mac'", httperrors
.Bad_Request
)
5453 for pci_expanded
in utils
.expand_brackets(pci
):
5454 element
["pci"] = pci_expanded
5455 maps
.append(dict(element
))
5457 return ovim
.set_of_port_mapping(maps
, ofc_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, region
=datacenter_id
)
5459 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
5460 maps
= ovim
.get_of_port_mappings(db_filter
={"region": datacenter_id
})
5463 "sdn-controller": None,
5464 "datacenter-id": datacenter_id
,
5466 "ports_mapping": list()
5469 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
5470 if datacenter
['config']:
5471 config
= yaml
.load(datacenter
['config'])
5472 if 'sdn-controller' in config
:
5473 controller_id
= config
['sdn-controller']
5474 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
5475 result
["sdn-controller"] = controller_id
5476 result
["dpid"] = sdn_controller
["dpid"]
5478 if result
["sdn-controller"] == None:
5479 raise NfvoException("SDN controller is not defined for datacenter {}".format(datacenter_id
), httperrors
.Bad_Request
)
5480 if result
["dpid"] == None:
5481 raise NfvoException("It was not possible to determine DPID for SDN controller {}".format(result
["sdn-controller"]),
5482 httperrors
.Internal_Server_Error
)
5487 ports_correspondence_dict
= dict()
5489 if result
["sdn-controller"] != link
["ofc_id"]:
5490 raise NfvoException("The sdn-controller specified for different port mappings differ", httperrors
.Internal_Server_Error
)
5491 if result
["dpid"] != link
["switch_dpid"]:
5492 raise NfvoException("The dpid specified for different port mappings differ", httperrors
.Internal_Server_Error
)
5494 element
["pci"] = link
["pci"]
5495 if link
["switch_port"]:
5496 element
["switch_port"] = link
["switch_port"]
5497 if link
["switch_mac"]:
5498 element
["switch_mac"] = link
["switch_mac"]
5500 if not link
["compute_node"] in ports_correspondence_dict
:
5502 content
["compute_node"] = link
["compute_node"]
5503 content
["ports"] = list()
5504 ports_correspondence_dict
[link
["compute_node"]] = content
5506 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
5508 for key
in sorted(ports_correspondence_dict
):
5509 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
5513 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
5514 return ovim
.clear_of_port_mapping(db_filter
={"region":datacenter_id
})
5516 def create_RO_keypair(tenant_id
):
5518 Creates a public / private keys for a RO tenant and returns their values
5520 tenant_id: ID of the tenant
5522 public_key: Public key for the RO tenant
5523 private_key: Encrypted private key for RO tenant
5527 key
= RSA
.generate(bits
)
5529 public_key
= key
.publickey().exportKey('OpenSSH')
5530 if isinstance(public_key
, ValueError):
5531 raise NfvoException("Unable to create public key: {}".format(public_key
), httperrors
.Internal_Server_Error
)
5532 private_key
= key
.exportKey(passphrase
=tenant_id
, pkcs
=8)
5533 except (ValueError, NameError) as e
:
5534 raise NfvoException("Unable to create private key: {}".format(e
), httperrors
.Internal_Server_Error
)
5535 return public_key
, private_key
5537 def decrypt_key (key
, tenant_id
):
5539 Decrypts an encrypted RSA key
5541 key: Private key to be decrypted
5542 tenant_id: ID of the tenant
5544 unencrypted_key: Unencrypted private key for RO tenant
5547 key
= RSA
.importKey(key
,tenant_id
)
5548 unencrypted_key
= key
.exportKey('PEM')
5549 if isinstance(unencrypted_key
, ValueError):
5550 raise NfvoException("Unable to decrypt the private key: {}".format(unencrypted_key
), httperrors
.Internal_Server_Error
)
5551 except ValueError as e
:
5552 raise NfvoException("Unable to decrypt the private key: {}".format(e
), httperrors
.Internal_Server_Error
)
5553 return unencrypted_key