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 . import vim_thread
35 from .db_base
import HTTP_Unauthorized
, HTTP_Bad_Request
, HTTP_Internal_Server_Error
, HTTP_Not_Found
,\
36 HTTP_Conflict
, HTTP_Method_Not_Allowed
37 from . 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 itertools
import chain
57 global vimconn_imported
59 global default_volume_size
60 default_volume_size
= '5' #size in GB
65 vimconn_imported
= {} # dictionary with VIM type as key, loaded module as value
66 vim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-VIMs
67 vim_persistent_info
= {}
68 logger
= logging
.getLogger('openmano.nfvo')
74 class NfvoException(Exception):
75 def __init__(self
, message
, http_code
):
76 self
.http_code
= http_code
77 Exception.__init
__(self
, message
)
83 if task_id
<= last_task_id
:
84 task_id
= last_task_id
+ 0.000001
85 last_task_id
= task_id
86 return "ACTION-{:.6f}".format(task_id
)
87 # return (t.strftime("%Y%m%dT%H%M%S.{}%Z", t.localtime(task_id))).format(int((task_id % 1)*1e6))
90 def new_task(name
, params
, depends
=None):
92 task_id
= get_task_id()
93 task
= {"status": "enqueued", "id": task_id
, "name": name
, "params": params
}
95 task
["depends"] = depends
100 return True if id[:5] == "TASK-" else False
103 def get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_name
, tenant_id
):
104 name
= datacenter_name
[:16]
105 if name
not in vim_threads
["names"]:
106 vim_threads
["names"].append(name
)
108 name
= datacenter_name
[:16] + "." + tenant_name
[:16]
109 if name
not in vim_threads
["names"]:
110 vim_threads
["names"].append(name
)
112 name
= datacenter_id
+ "-" + tenant_id
113 vim_threads
["names"].append(name
)
117 def start_service(mydb
):
118 global db
, global_config
119 db
= nfvo_db
.nfvo_db()
120 db
.connect(global_config
['db_host'], global_config
['db_user'], global_config
['db_passwd'], global_config
['db_name'])
123 # Initialize openvim for SDN control
124 # TODO: Avoid static configuration by adding new parameters to openmanod.cfg
125 # TODO: review ovim.py to delete not needed configuration
126 ovim_configuration
= {
127 'logger_name': 'openmano.ovim',
128 'network_vlan_range_start': 1000,
129 'network_vlan_range_end': 4096,
130 'db_name': global_config
["db_ovim_name"],
131 'db_host': global_config
["db_ovim_host"],
132 'db_user': global_config
["db_ovim_user"],
133 'db_passwd': global_config
["db_ovim_passwd"],
136 'network_type': 'bridge',
137 #TODO: log_level_of should not be needed. To be modified in ovim
138 'log_level_of': 'DEBUG'
141 ovim
= ovim_module
.ovim(ovim_configuration
)
144 from_
= 'tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join '\
145 'datacenter_tenants as dt on td.datacenter_tenant_id=dt.uuid'
146 select_
= ('type', 'd.config as config', 'd.uuid as datacenter_id', 'vim_url', 'vim_url_admin',
147 'd.name as datacenter_name', 'dt.uuid as datacenter_tenant_id',
148 'dt.vim_tenant_name as vim_tenant_name', 'dt.vim_tenant_id as vim_tenant_id',
149 'user', 'passwd', 'dt.config as dt_config', 'nfvo_tenant_id')
150 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
)
152 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
153 'datacenter_id': vim
.get('datacenter_id')}
155 extra
.update(yaml
.load(vim
["config"]))
156 if vim
.get('dt_config'):
157 extra
.update(yaml
.load(vim
["dt_config"]))
158 if vim
["type"] not in vimconn_imported
:
161 module
= "vimconn_" + vim
["type"]
162 pkg
= __import__("osm_ro." + module
)
163 vim_conn
= getattr(pkg
, module
)
164 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
165 # vim_conn = imp.load_module(vim["type"], *module_info)
166 vimconn_imported
[vim
["type"]] = vim_conn
167 except (IOError, ImportError) as e
:
168 # if module_info and module_info[0]:
169 # file.close(module_info[0])
170 raise NfvoException("Unknown vim type '{}'. Cannot open file '{}.py'; {}: {}".format(
171 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
173 thread_id
= vim
['datacenter_tenant_id']
174 vim_persistent_info
[thread_id
] = {}
177 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
178 myvim
= vimconn_imported
[ vim
["type"] ].vimconnector(
179 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
180 tenant_id
=vim
['vim_tenant_id'], tenant_name
=vim
['vim_tenant_name'],
181 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
182 user
=vim
['user'], passwd
=vim
['passwd'],
183 config
=extra
, persistent_info
=vim_persistent_info
[thread_id
]
185 except vimconn
.vimconnException
as e
:
187 logger
.error("Cannot launch thread for VIM {} '{}': {}".format(vim
['datacenter_name'],
188 vim
['datacenter_id'], e
))
189 except Exception as e
:
190 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, e
),
191 HTTP_Internal_Server_Error
)
192 thread_name
= get_non_used_vim_name(vim
['datacenter_name'], vim
['vim_tenant_id'], vim
['vim_tenant_name'],
193 vim
['vim_tenant_id'])
194 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, vim
['datacenter_name'],
195 vim
['datacenter_tenant_id'], db
=db
, db_lock
=db_lock
, ovim
=ovim
)
197 vim_threads
["running"][thread_id
] = new_thread
198 except db_base_Exception
as e
:
199 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
200 except ovim_module
.ovimException
as e
:
202 if message
[:22] == "DATABASE wrong version":
203 message
= "DATABASE wrong version of lib_osm_openvim {msg} -d{dbname} -u{dbuser} -p{dbpass} {ver}' "\
204 "at host {dbhost}".format(
205 msg
=message
[22:-3], dbname
=global_config
["db_ovim_name"],
206 dbuser
=global_config
["db_ovim_user"], dbpass
=global_config
["db_ovim_passwd"],
207 ver
=message
[-3:-1], dbhost
=global_config
["db_ovim_host"])
208 raise NfvoException(message
, HTTP_Bad_Request
)
212 global ovim
, global_config
215 for thread_id
,thread
in list(vim_threads
["running"].items()):
216 thread
.insert_task("exit")
217 vim_threads
["deleting"][thread_id
] = thread
218 vim_threads
["running"] = {}
219 if global_config
and global_config
.get("console_thread"):
220 for thread
in global_config
["console_thread"]:
221 thread
.terminate
= True
224 return ("openmanod version {} {}\n(c) Copyright Telefonica".format(global_config
["version"],
225 global_config
["version_date"] ))
228 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
230 return result, content:
231 <0, error_text upon error
232 nb_records, flavor_list on success
235 WHERE_dict
['vnf_id'] = vnf_id
236 if nfvo_tenant
is not None:
237 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
239 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
240 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
241 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
242 #print "get_flavor_list result:", result
243 #print "get_flavor_list content:", content
245 for flavor
in flavors
:
246 flavorList
.append(flavor
['flavor_id'])
250 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
252 return result, content:
253 <0, error_text upon error
254 nb_records, flavor_list on success
257 WHERE_dict
['vnf_id'] = vnf_id
258 if nfvo_tenant
is not None:
259 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
261 #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
262 images
= mydb
.get_rows(FROM
='vms join images on vms.image_id=images.uuid',SELECT
=('image_id',),WHERE
=WHERE_dict
)
265 imageList
.append(image
['image_id'])
269 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
270 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None):
271 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
272 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
273 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
274 raise exception upon error
277 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
278 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
279 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
280 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
281 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
282 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
283 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
284 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'
285 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
286 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
287 'user','passwd', 'dt.config as dt_config')
289 from_
= 'datacenters as d'
290 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
292 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
295 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
296 'datacenter_id': vim
.get('datacenter_id')}
298 extra
.update(yaml
.load(vim
["config"]))
299 if vim
.get('dt_config'):
300 extra
.update(yaml
.load(vim
["dt_config"]))
301 if vim
["type"] not in vimconn_imported
:
304 module
= "vimconn_" + vim
["type"]
305 pkg
= __import__("osm_ro." + module
)
306 vim_conn
= getattr(pkg
, module
)
307 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
308 # vim_conn = imp.load_module(vim["type"], *module_info)
309 vimconn_imported
[vim
["type"]] = vim_conn
310 except (IOError, ImportError) as e
:
311 # if module_info and module_info[0]:
312 # file.close(module_info[0])
313 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
314 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
317 if 'datacenter_tenant_id' in vim
:
318 thread_id
= vim
["datacenter_tenant_id"]
319 if thread_id
not in vim_persistent_info
:
320 vim_persistent_info
[thread_id
] = {}
321 persistent_info
= vim_persistent_info
[thread_id
]
325 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
326 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
327 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
328 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
),
329 tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
330 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
331 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
332 config
=extra
, persistent_info
=persistent_info
334 except Exception as e
:
335 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
337 except db_base_Exception
as e
:
338 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
341 def rollback(mydb
, vims
, rollback_list
):
343 #delete things by reverse order
344 for i
in range(len(rollback_list
)-1, -1, -1):
345 item
= rollback_list
[i
]
346 if item
["where"]=="vim":
347 if item
["vim_id"] not in vims
:
349 if is_task_id(item
["uuid"]):
351 vim
= vims
[item
["vim_id"]]
353 if item
["what"]=="image":
354 vim
.delete_image(item
["uuid"])
355 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_vim_id": vim
["id"], "vim_id":item
["uuid"]})
356 elif item
["what"]=="flavor":
357 vim
.delete_flavor(item
["uuid"])
358 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
359 elif item
["what"]=="network":
360 vim
.delete_network(item
["uuid"])
361 elif item
["what"]=="vm":
362 vim
.delete_vminstance(item
["uuid"])
363 except vimconn
.vimconnException
as e
:
364 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
365 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
366 except db_base_Exception
as e
:
367 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
371 if item
["what"]=="image":
372 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
373 elif item
["what"]=="flavor":
374 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
375 except db_base_Exception
as e
:
376 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
377 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
378 if len(undeleted_items
)==0:
379 return True," Rollback successful."
381 return False," Rollback fails to delete: " + str(undeleted_items
)
384 def check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1):
386 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
388 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
390 #dataplane interfaces
391 for numa
in vnfc
.get("numas",() ):
392 for interface
in numa
.get("interfaces",()):
393 if interface
["name"] in name_dict
:
395 "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
396 vnfc
["name"], interface
["name"]),
398 name_dict
[ interface
["name"] ] = "underlay"
400 for interface
in vnfc
.get("bridge-ifaces",() ):
401 if interface
["name"] in name_dict
:
403 "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
404 vnfc
["name"], interface
["name"]),
406 name_dict
[ interface
["name"] ] = "overlay"
407 vnfc_interfaces
[ vnfc
["name"] ] = name_dict
408 # check bood-data info
409 # if "boot-data" in vnfc:
410 # # check that user-data is incompatible with users and config-files
411 # if (vnfc["boot-data"].get("users") or vnfc["boot-data"].get("config-files")) and vnfc["boot-data"].get("user-data"):
412 # raise NfvoException(
413 # "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
416 #check if the info in external_connections matches with the one in the vnfcs
418 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
419 if external_connection
["name"] in name_list
:
421 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
422 external_connection
["name"]),
424 name_list
.append(external_connection
["name"])
425 if external_connection
["VNFC"] not in vnfc_interfaces
:
427 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
428 external_connection
["name"], external_connection
["VNFC"]),
431 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
433 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
434 external_connection
["name"],
435 external_connection
["local_iface_name"]),
438 #check if the info in internal_connections matches with the one in the vnfcs
440 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
441 if internal_connection
["name"] in name_list
:
443 "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection".format(
444 internal_connection
["name"]),
446 name_list
.append(internal_connection
["name"])
447 #We should check that internal-connections of type "ptp" have only 2 elements
449 if len(internal_connection
["elements"])>2 and (internal_connection
.get("type") == "ptp" or internal_connection
.get("type") == "e-line"):
451 "Error at 'vnf:internal-connections[name:'{}']:elements', size must be 2 for a '{}' type. Consider change it to '{}' type".format(
452 internal_connection
["name"],
453 'ptp' if vnf_descriptor_version
==1 else 'e-line',
454 'data' if vnf_descriptor_version
==1 else "e-lan"),
456 for port
in internal_connection
["elements"]:
458 iface
= port
["local_iface_name"]
459 if vnf
not in vnfc_interfaces
:
461 "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
462 internal_connection
["name"], vnf
),
464 if iface
not in vnfc_interfaces
[ vnf
]:
466 "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
467 internal_connection
["name"], iface
),
469 return -HTTP_Bad_Request
,
470 if vnf_descriptor_version
==1 and "type" not in internal_connection
:
471 if vnfc_interfaces
[vnf
][iface
] == "overlay":
472 internal_connection
["type"] = "bridge"
474 internal_connection
["type"] = "data"
475 if vnf_descriptor_version
==2 and "implementation" not in internal_connection
:
476 if vnfc_interfaces
[vnf
][iface
] == "overlay":
477 internal_connection
["implementation"] = "overlay"
479 internal_connection
["implementation"] = "underlay"
480 if (internal_connection
.get("type") == "data" or internal_connection
.get("type") == "ptp" or \
481 internal_connection
.get("implementation") == "underlay") and vnfc_interfaces
[vnf
][iface
] == "overlay":
483 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
484 internal_connection
["name"],
485 iface
, 'bridge' if vnf_descriptor_version
==1 else 'overlay',
486 'data' if vnf_descriptor_version
==1 else 'underlay'),
488 if (internal_connection
.get("type") == "bridge" or internal_connection
.get("implementation") == "overlay") and \
489 vnfc_interfaces
[vnf
][iface
] == "underlay":
491 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
492 internal_connection
["name"], iface
,
493 'data' if vnf_descriptor_version
==1 else 'underlay',
494 'bridge' if vnf_descriptor_version
==1 else 'overlay'),
498 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=None):
500 if only_create_at_vim
:
501 image_mano_id
= image_dict
['uuid']
502 if return_on_error
== None:
503 return_on_error
= True
505 if image_dict
['location']:
506 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
508 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
510 image_mano_id
= images
[0]['uuid']
512 #create image in MANO DB
513 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
514 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
515 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
517 #temp_image_dict['location'] = image_dict.get('new_location') if image_dict['location'] is None
518 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
519 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
520 #create image at every vim
521 for vim_id
,vim
in vims
.items():
522 datacenter_vim_id
= vim
["config"]["datacenter_tenant_id"]
523 image_created
="false"
525 image_db
= mydb
.get_rows(FROM
="datacenters_images",
526 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'image_id': image_mano_id
})
527 #look at VIM if this image exist
529 if image_dict
['location'] is not None:
530 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
533 filter_dict
['name'] = image_dict
['universal_name']
534 if image_dict
.get('checksum') != None:
535 filter_dict
['checksum'] = image_dict
['checksum']
536 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
537 vim_images
= vim
.get_image_list(filter_dict
)
538 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
539 if len(vim_images
) > 1:
540 raise vimconn
.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict
)), HTTP_Conflict
)
541 elif len(vim_images
) == 0:
542 raise vimconn
.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict
)))
544 #logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
545 image_vim_id
= vim_images
[0]['id']
547 except vimconn
.vimconnNotFoundException
as e
:
548 #Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
550 #image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
551 if image_dict
['location']:
552 image_vim_id
= vim
.new_image(image_dict
)
553 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
556 #If we reach this point, then the image has image name, and optionally checksum, and could not be found
557 raise vimconn
.vimconnException(str(e
))
558 except vimconn
.vimconnException
as e
:
560 logger
.error("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
563 logger
.warn("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
565 except vimconn
.vimconnException
as e
:
567 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
569 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
572 #if we reach here, the image has been created or existed
574 #add new vim_id at datacenters_images
575 mydb
.new_row('datacenters_images', {'datacenter_vim_id': datacenter_vim_id
,
576 'image_id':image_mano_id
,
577 'vim_id': image_vim_id
,
578 'created':image_created
})
579 elif image_db
[0]["vim_id"]!=image_vim_id
:
580 #modify existing vim_id at datacenters_images
581 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_vim_id':vim_id
, 'image_id':image_mano_id
})
583 return image_vim_id
if only_create_at_vim
else image_mano_id
586 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
587 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
588 'ram':flavor_dict
.get('ram'),
589 'vcpus':flavor_dict
.get('vcpus'),
591 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
592 del flavor_dict
['extended']
593 if 'extended' in flavor_dict
:
594 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
596 #look if flavor exist
597 if only_create_at_vim
:
598 flavor_mano_id
= flavor_dict
['uuid']
599 if return_on_error
== None:
600 return_on_error
= True
602 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
604 flavor_mano_id
= flavors
[0]['uuid']
607 #create one by one the images of aditional disks
608 dev_image_list
=[] #list of images
609 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
611 for device
in flavor_dict
['extended'].get('devices',[]):
612 if "image" not in device
and "image name" not in device
:
615 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
616 image_dict
['universal_name']=device
.get('image name')
617 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
618 image_dict
['location']=device
.get('image')
619 #image_dict['new_location']=vnfc.get('image location')
620 image_dict
['checksum']=device
.get('image checksum')
621 image_metadata_dict
= device
.get('image metadata', None)
622 image_metadata_str
= None
623 if image_metadata_dict
!= None:
624 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
625 image_dict
['metadata']=image_metadata_str
626 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
627 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
628 dev_image_list
.append(image_id
)
630 temp_flavor_dict
['name'] = flavor_dict
['name']
631 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
632 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
633 flavor_mano_id
= content
634 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
635 #create flavor at every vim
636 if 'uuid' in flavor_dict
:
637 del flavor_dict
['uuid']
639 for vim_id
,vim
in list(vims
.items()):
640 datacenter_vim_id
= vim
["config"]["datacenter_tenant_id"]
641 flavor_created
="false"
643 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors",
644 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
})
645 #look at VIM if this flavor exist SKIPPED
646 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
648 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
652 # Create the flavor in VIM
653 # Translate images at devices from MANO id to VIM id
655 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
656 # make a copy of original devices
659 for device
in flavor_dict
["extended"].get("devices",[]):
662 devices_original
.append(dev
)
663 if 'image' in device
:
665 if 'image metadata' in device
:
666 del device
['image metadata']
667 if 'image checksum' in device
:
668 del device
['image checksum']
670 for index
in range(0,len(devices_original
)) :
671 device
=devices_original
[index
]
672 if "image" not in device
and "image name" not in device
:
674 disk_list
.append({'size': device
.get('size', default_volume_size
)})
677 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
678 image_dict
['universal_name']=device
.get('image name')
679 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
680 image_dict
['location']=device
.get('image')
681 # image_dict['new_location']=device.get('image location')
682 image_dict
['checksum']=device
.get('image checksum')
683 image_metadata_dict
= device
.get('image metadata', None)
684 image_metadata_str
= None
685 if image_metadata_dict
!= None:
686 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
687 image_dict
['metadata']=image_metadata_str
688 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
689 image_dict
["uuid"]=image_mano_id
690 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
692 #save disk information (image must be based on and size
693 disk_list
.append({'image_id': image_vim_id
, 'size': device
.get('size', default_volume_size
)})
695 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
698 #check that this vim_id exist in VIM, if not create
699 flavor_vim_id
=flavor_db
[0]["vim_id"]
701 vim
.get_flavor(flavor_vim_id
)
702 continue #flavor exist
703 except vimconn
.vimconnException
:
705 #create flavor at vim
706 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
709 flavor_vim_id
=vim
.get_flavor_id_from_data(flavor_dict
)
710 flavor_create
="false"
711 except vimconn
.vimconnException
as e
:
714 if not flavor_vim_id
:
715 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
716 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
717 flavor_created
="true"
718 except vimconn
.vimconnException
as e
:
720 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
722 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
725 #if reach here the flavor has been create or exist
726 if len(flavor_db
)==0:
727 #add new vim_id at datacenters_flavors
728 extended_devices_yaml
= None
729 if len(disk_list
) > 0:
730 extended_devices
= dict()
731 extended_devices
['disks'] = disk_list
732 extended_devices_yaml
= yaml
.safe_dump(extended_devices
,default_flow_style
=True,width
=256)
733 mydb
.new_row('datacenters_flavors',
734 {'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
, 'vim_id': flavor_vim_id
,
735 'created': flavor_created
, 'extended': extended_devices_yaml
})
736 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
737 #modify existing vim_id at datacenters_flavors
738 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
},
739 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
})
741 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
744 def get_str(obj
, field
, length
):
746 Obtain the str value,
751 value
= obj
.get(field
)
752 if value
is not None:
753 value
= str(value
)[:length
]
756 def _lookfor_or_create_image(db_image
, mydb
, descriptor
):
758 fill image content at db_image dictionary. Check if the image with this image and checksum exist
759 :param db_image: dictionary to insert data
760 :param mydb: database connector
761 :param descriptor: yang descriptor
762 :return: uuid if the image exist at DB, or None if a new image must be created with the data filled at db_image
765 db_image
["name"] = get_str(descriptor
, "image", 255)
766 db_image
["checksum"] = get_str(descriptor
, "image-checksum", 32)
767 if not db_image
["checksum"]: # Ensure that if empty string, None is stored
768 db_image
["checksum"] = None
769 if db_image
["name"].startswith("/"):
770 db_image
["location"] = db_image
["name"]
771 existing_images
= mydb
.get_rows(FROM
="images", WHERE
={'location': db_image
["location"]})
773 db_image
["universal_name"] = db_image
["name"]
774 existing_images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name': db_image
['universal_name'],
775 'checksum': db_image
['checksum']})
777 return existing_images
[0]["uuid"]
779 image_uuid
= str(uuid4())
780 db_image
["uuid"] = image_uuid
783 def new_vnfd_v3(mydb
, tenant_id
, vnf_descriptor
):
785 Parses an OSM IM vnfd_catalog and insert at DB
788 :param vnf_descriptor:
789 :return: The list of cretated vnf ids
792 myvnfd
= vnfd_catalog
.vnfd()
794 pybindJSONDecoder
.load_ietf_json(vnf_descriptor
, None, None, obj
=myvnfd
)
795 except Exception as e
:
796 raise NfvoException("Error. Invalid VNF descriptor format " + str(e
), HTTP_Bad_Request
)
806 vnfd_catalog_descriptor
= vnf_descriptor
.get("vnfd:vnfd-catalog")
807 if not vnfd_catalog_descriptor
:
808 vnfd_catalog_descriptor
= vnf_descriptor
.get("vnfd-catalog")
809 vnfd_descriptor_list
= vnfd_catalog_descriptor
.get("vnfd")
810 if not vnfd_descriptor_list
:
811 vnfd_descriptor_list
= vnfd_catalog_descriptor
.get("vnfd:vnfd")
812 for vnfd_yang
in myvnfd
.vnfd_catalog
.vnfd
.values():
813 vnfd
= vnfd_yang
.get()
816 vnf_uuid
= str(uuid4())
817 uuid_list
.append(vnf_uuid
)
818 vnfd_uuid_list
.append(vnf_uuid
)
821 "osm_id": get_str(vnfd
, "id", 255),
822 "name": get_str(vnfd
, "name", 255),
823 "description": get_str(vnfd
, "description", 255),
824 "tenant_id": tenant_id
,
825 "vendor": get_str(vnfd
, "vendor", 255),
826 "short_name": get_str(vnfd
, "short-name", 255),
827 "descriptor": str(vnf_descriptor
)[:60000]
830 for vnfd_descriptor
in vnfd_descriptor_list
:
831 if vnfd_descriptor
["id"] == str(vnfd
["id"]):
834 # table nets (internal-vld)
835 net_id2uuid
= {} # for mapping interface with network
836 for vld
in vnfd
.get("internal-vld").values():
837 net_uuid
= str(uuid4())
838 uuid_list
.append(net_uuid
)
840 "name": get_str(vld
, "name", 255),
843 "description": get_str(vld
, "description", 255),
844 "type": "bridge", # TODO adjust depending on connection point type
846 net_id2uuid
[vld
.get("id")] = net_uuid
847 db_nets
.append(db_net
)
851 vdu_id2db_table_index
= {}
852 for vdu
in vnfd
.get("vdu").values():
853 vm_uuid
= str(uuid4())
854 uuid_list
.append(vm_uuid
)
857 "osm_id": get_str(vdu
, "id", 255),
858 "name": get_str(vdu
, "name", 255),
859 "description": get_str(vdu
, "description", 255),
862 vdu_id2uuid
[db_vm
["osm_id"]] = vm_uuid
863 vdu_id2db_table_index
[db_vm
["osm_id"]] = db_vms_index
865 db_vm
["count"] = int(vdu
["count"])
868 image_present
= False
872 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, vdu
)
874 image_uuid
= db_image
["uuid"]
875 db_images
.append(db_image
)
876 db_vm
["image_id"] = image_uuid
880 if vdu
.get("volumes"):
881 for volume_key
in sorted(vdu
["volumes"]):
882 volume
= vdu
["volumes"][volume_key
]
883 if not image_present
:
884 # Convert the first volume to vnfc.image
887 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, volume
)
889 image_uuid
= db_image
["uuid"]
890 db_images
.append(db_image
)
891 db_vm
["image_id"] = image_uuid
893 # Add Openmano devices
895 device
["type"] = str(volume
.get("device-type"))
896 if volume
.get("size"):
897 device
["size"] = int(volume
["size"])
898 if volume
.get("image"):
899 device
["image name"] = str(volume
["image"])
900 if volume
.get("image-checksum"):
901 device
["image checksum"] = str(volume
["image-checksum"])
902 devices
.append(device
)
906 "name": get_str(vdu
, "name", 250) + "-flv",
907 "vcpus": int(vdu
["vm-flavor"].get("vcpu-count", 1)),
908 "ram": int(vdu
["vm-flavor"].get("memory-mb", 1)),
909 "disk": int(vdu
["vm-flavor"].get("storage-gb", 1)),
915 extended
["devices"] = devices
916 if vdu
.get("guest-epa"): # TODO or dedicated_int:
918 if vdu
["guest-epa"].get("numa-node-policy"): # TODO or dedicated_int:
919 numa_node_policy
= vdu
["guest-epa"].get("numa-node-policy")
920 if numa_node_policy
.get("node"):
921 numa_node
= numa_node_policy
["node"]['0']
922 if numa_node
.get("num-cores"):
923 numa
["cores"] = numa_node
["num-cores"]
925 if numa_node
.get("paired-threads"):
926 if numa_node
["paired-threads"].get("num-paired-threads"):
927 numa
["paired-threads"] = int(numa_node
["paired-threads"]["num-paired-threads"])
929 if len(numa_node
["paired-threads"].get("paired-thread-ids")):
930 numa
["paired-threads-id"] = []
931 for pair
in numa_node
["paired-threads"]["paired-thread-ids"].values():
932 numa
["paired-threads-id"].append(
933 (str(pair
["thread-a"]), str(pair
["thread-b"]))
935 if numa_node
.get("num-threads"):
936 numa
["threads"] = int(numa_node
["num-threads"])
938 if numa_node
.get("memory-mb"):
939 numa
["memory"] = max(int(numa_node
["memory-mb"] / 1024), 1)
940 if vdu
["guest-epa"].get("mempage-size"):
941 if vdu
["guest-epa"]["mempage-size"] != "SMALL":
942 numa
["memory"] = max(int(db_flavor
["ram"] / 1024), 1)
943 if vdu
["guest-epa"].get("cpu-pinning-policy") and not epa_vcpu_set
:
944 if vdu
["guest-epa"]["cpu-pinning-policy"] == "DEDICATED":
945 if vdu
["guest-epa"].get("cpu-thread-pinning-policy") and \
946 vdu
["guest-epa"]["cpu-thread-pinning-policy"] != "PREFER":
947 numa
["cores"] = max(db_flavor
["vcpus"], 1)
949 numa
["threads"] = max(db_flavor
["vcpus"], 1)
951 extended
["numas"] = [numa
]
953 extended_text
= yaml
.safe_dump(extended
, default_flow_style
=True, width
=256)
954 db_flavor
["extended"] = extended_text
955 # look if flavor exist
957 temp_flavor_dict
= {'disk': db_flavor
.get('disk', 1),
958 'ram': db_flavor
.get('ram'),
959 'vcpus': db_flavor
.get('vcpus'),
960 'extended': db_flavor
.get('extended')
962 existing_flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
964 flavor_uuid
= existing_flavors
[0]["uuid"]
966 flavor_uuid
= str(uuid4())
967 uuid_list
.append(flavor_uuid
)
968 db_flavor
["uuid"] = flavor_uuid
969 db_flavors
.append(db_flavor
)
970 db_vm
["flavor_id"] = flavor_uuid
974 if vdu
.get("cloud-init"):
975 boot_data
["user-data"] = str(vdu
["cloud-init"])
976 elif vdu
.get("cloud-init-file"):
977 # TODO Where this file content is present???
978 # boot_data["user-data"] = vnfd_yang.files[vdu["cloud-init-file"]]
979 boot_data
["user-data"] = str(vdu
["cloud-init-file"])
981 if vdu
.get("supplemental-boot-data"):
982 if vdu
["supplemental-boot-data"].get('boot-data-drive'):
983 boot_data
['boot-data-drive'] = True
984 if vdu
["supplemental-boot-data"].get('config-file'):
985 om_cfgfile_list
= list()
986 for custom_config_file
in vdu
["supplemental-boot-data"]['config-file'].values():
987 # TODO Where this file content is present???
988 cfg_source
= str(custom_config_file
["source"])
989 om_cfgfile_list
.append({"dest": custom_config_file
["dest"],
990 "content": cfg_source
})
991 boot_data
['config-files'] = om_cfgfile_list
993 db_vm
["boot_data"] = yaml
.safe_dump(boot_data
, default_flow_style
=True, width
=256)
998 # table interfaces (internal/external interfaces)
999 cp_name2iface_uuid
= {}
1000 cp_name2vm_uuid
= {}
1001 # for iface in chain(vdu.get("internal-interface").itervalues(), vdu.get("external-interface").itervalues()):
1002 for iface
in vdu
.get("interface").values():
1003 iface_uuid
= str(uuid4())
1004 uuid_list
.append(iface_uuid
)
1007 "internal_name": get_str(iface
, "name", 255),
1010 if iface
.get("virtual-interface").get("vpci"):
1011 db_interface
["vpci"] = get_str(iface
.get("virtual-interface"), "vpci", 12)
1013 if iface
.get("virtual-interface").get("bandwidth"):
1014 bps
= int(iface
.get("virtual-interface").get("bandwidth"))
1015 db_interface
["bw"] = bps
/1000
1017 if iface
.get("virtual-interface").get("type") == "OM-MGMT":
1018 db_interface
["type"] = "mgmt"
1019 elif iface
.get("virtual-interface").get("type") in ("VIRTIO", "E1000"):
1020 db_interface
["type"] = "bridge"
1021 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1022 elif iface
.get("virtual-interface").get("type") in ("SR-IOV", "PCI-PASSTHROUGH"):
1023 db_interface
["type"] = "data"
1024 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1026 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vdu[{}]':'interface':'virtual"
1027 "-interface':'type':'{}'. Interface type is not supported".format(
1028 str(vnfd
["id"])[:255], str(vdu
["id"])[:255],
1029 iface
.get("virtual-interface").get("type")),
1032 if iface
.get("external-connection-point-ref"):
1034 cp
= vnfd
.get("connection-point")[iface
.get("external-connection-point-ref")]
1035 db_interface
["external_name"] = get_str(cp
, "name", 255)
1036 cp_name2iface_uuid
[db_interface
["external_name"]] = iface_uuid
1037 cp_name2vm_uuid
[db_interface
["external_name"]] = vm_uuid
1038 for cp_descriptor
in vnfd_descriptor
["connection-point"]:
1039 if cp_descriptor
["name"] == db_interface
["external_name"]:
1041 if str(cp_descriptor
.get("port-security-enabled")).lower() == "false":
1042 db_interface
["port_security"] = 0
1043 elif str(cp_descriptor
.get("port-security-enabled")).lower() == "true":
1044 db_interface
["port_security"] = 1
1046 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1047 "'interface[{iface}]':'vnfd-connection-point-ref':'{cp}' is not present"
1048 " at connection-point".format(
1049 vnf
=vnfd
["id"], vdu
=vdu
["id"], iface
=iface
["name"],
1050 cp
=iface
.get("vnfd-connection-point-ref")),
1052 elif iface
.get("internal-connection-point-ref"):
1054 for vld
in vnfd
.get("internal-vld").values():
1055 for cp
in vld
.get("internal-connection-point").values():
1056 if cp
.get("id-ref") == iface
.get("internal-connection-point-ref"):
1057 db_interface
["net_id"] = net_id2uuid
[vld
.get("id")]
1058 for cp_descriptor
in vnfd_descriptor
["connection-point"]:
1059 if cp_descriptor
["name"] == db_interface
["external_name"]:
1061 if str(cp_descriptor
.get("port-security-enabled")).lower() == "false":
1062 db_interface
["port_security"] = 0
1063 elif str(cp_descriptor
.get("port-security-enabled")).lower() == "true":
1064 db_interface
["port_security"] = 1
1067 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1068 "'interface[{iface}]':'vdu-internal-connection-point-ref':'{cp}' is not"
1069 " referenced by any internal-vld".format(
1070 vnf
=vnfd
["id"], vdu
=vdu
["id"], iface
=iface
["name"],
1071 cp
=iface
.get("vdu-internal-connection-point-ref")),
1073 if iface
.get("position") is not None:
1074 db_interface
["created_at"] = int(iface
.get("position")) - 1000
1075 db_interfaces
.append(db_interface
)
1077 # VNF affinity and antiaffinity
1078 for pg
in vnfd
.get("placement-groups").values():
1079 pg_name
= get_str(pg
, "name", 255)
1080 for vdu
in pg
.get("member-vdus").values():
1081 vdu_id
= get_str(vdu
, "member-vdu-ref", 255)
1082 if vdu_id
not in vdu_id2db_table_index
:
1083 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'placement-groups[{pg}]':"
1084 "'member-vdus':'{vdu}'. Reference to a non-existing vdu".format(
1085 vnf
=vnfd
["id"], pg
=pg_name
, vdu
=vdu_id
),
1087 db_vms
[vdu_id2db_table_index
[vdu_id
]]["availability_zone"] = pg_name
1088 # TODO consider the case of isolation and not colocation
1089 # if pg.get("strategy") == "ISOLATION":
1091 # VNF mgmt configuration
1093 if vnfd
["mgmt-interface"].get("vdu-id"):
1094 if vnfd
["mgmt-interface"]["vdu-id"] not in vdu_id2uuid
:
1095 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'vdu-id':"
1096 "'{vdu}'. Reference to a non-existing vdu".format(
1097 vnf
=vnfd
["id"], vdu
=vnfd
["mgmt-interface"]["vdu-id"]),
1099 mgmt_access
["vm_id"] = vdu_id2uuid
[vnfd
["mgmt-interface"]["vdu-id"]]
1100 if vnfd
["mgmt-interface"].get("ip-address"):
1101 mgmt_access
["ip-address"] = str(vnfd
["mgmt-interface"].get("ip-address"))
1102 if vnfd
["mgmt-interface"].get("cp"):
1103 if vnfd
["mgmt-interface"]["cp"] not in cp_name2iface_uuid
:
1104 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'cp':'{cp}'. "
1105 "Reference to a non-existing connection-point".format(
1106 vnf
=vnfd
["id"], cp
=vnfd
["mgmt-interface"]["cp"]),
1108 mgmt_access
["vm_id"] = cp_name2vm_uuid
[vnfd
["mgmt-interface"]["cp"]]
1109 mgmt_access
["interface_id"] = cp_name2iface_uuid
[vnfd
["mgmt-interface"]["cp"]]
1110 default_user
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1114 mgmt_access
["default_user"] = default_user
1115 required
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1118 mgmt_access
["required"] = required
1121 db_vnf
["mgmt_access"] = yaml
.safe_dump(mgmt_access
, default_flow_style
=True, width
=256)
1125 db_vnfs
.append(db_vnf
)
1129 {"images": db_images
},
1130 {"flavors": db_flavors
},
1132 {"interfaces": db_interfaces
},
1135 logger
.debug("create_vnf Deployment done vnfDict: %s",
1136 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
1137 mydb
.new_rows(db_tables
, uuid_list
)
1138 return vnfd_uuid_list
1139 except NfvoException
:
1141 except Exception as e
:
1142 logger
.error("Exception {}".format(e
))
1143 raise # NfvoException("Exception {}".format(e), HTTP_Bad_Request)
1146 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
1147 global global_config
1149 # Step 1. Check the VNF descriptor
1150 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
1151 # Step 2. Check tenant exist
1153 if tenant_id
!= "any":
1154 check_tenant(mydb
, tenant_id
)
1155 if "tenant_id" in vnf_descriptor
["vnf"]:
1156 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1157 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1160 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1161 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1162 if global_config
["auto_push_VNF_to_VIMs"]:
1163 vims
= get_vim(mydb
, tenant_id
)
1165 # Step 4. Review the descriptor and add missing fields
1166 #print vnf_descriptor
1167 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1168 vnf_name
= vnf_descriptor
['vnf']['name']
1169 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1170 if "physical" in vnf_descriptor
['vnf']:
1171 del vnf_descriptor
['vnf']['physical']
1172 #print vnf_descriptor
1174 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1175 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1176 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1178 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1179 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1180 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1182 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1183 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1185 VNFCitem
["name"] = vnfc
['name']
1186 VNFCitem
["availability_zone"] = vnfc
.get('availability_zone')
1187 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
1189 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1192 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1193 myflavorDict
["description"] = VNFCitem
["description"]
1194 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1195 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1196 myflavorDict
["disk"] = vnfc
.get("disk", 1)
1197 myflavorDict
["extended"] = {}
1199 devices
= vnfc
.get("devices")
1201 myflavorDict
["extended"]["devices"] = devices
1204 # 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
1205 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1207 # Previous code has been commented
1208 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1209 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1210 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1211 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1213 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1215 # print "Error creating flavor: unknown processor model. Rollback successful."
1216 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1218 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1219 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1221 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1222 myflavorDict
['extended']['numas'] = vnfc
['numas']
1226 # Step 6.2 New flavors are created in the VIM
1227 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1229 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1230 VNFCitem
["flavor_id"] = flavor_id
1231 VNFCDict
[vnfc
['name']] = VNFCitem
1233 logger
.debug("Creating new images in the VIM for each VNFC")
1234 # Step 6.3 New images are created in the VIM
1235 #For each VNFC, we must create the appropriate image.
1236 #This "for" loop might be integrated with the previous one
1237 #In case this integration is made, the VNFCDict might become a VNFClist.
1238 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1239 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1241 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1242 image_dict
['universal_name']=vnfc
.get('image name')
1243 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1244 image_dict
['location']=vnfc
.get('VNFC image')
1245 #image_dict['new_location']=vnfc.get('image location')
1246 image_dict
['checksum']=vnfc
.get('image checksum')
1247 image_metadata_dict
= vnfc
.get('image metadata', None)
1248 image_metadata_str
= None
1249 if image_metadata_dict
is not None:
1250 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1251 image_dict
['metadata']=image_metadata_str
1252 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1253 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1254 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1255 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1256 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1257 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1258 if vnfc
.get("boot-data"):
1259 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1262 # Step 7. Storing the VNF descriptor in the repository
1263 if "descriptor" not in vnf_descriptor
["vnf"]:
1264 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1266 # Step 8. Adding the VNF to the NFVO DB
1267 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1269 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1270 _
, message
= rollback(mydb
, vims
, rollback_list
)
1271 if isinstance(e
, db_base_Exception
):
1272 error_text
= "Exception at database"
1273 elif isinstance(e
, KeyError):
1274 error_text
= "KeyError exception "
1275 e
.http_code
= HTTP_Internal_Server_Error
1277 error_text
= "Exception at VIM"
1278 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1279 #logger.error("start_scenario %s", error_text)
1280 raise NfvoException(error_text
, e
.http_code
)
1283 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
1284 global global_config
1286 # Step 1. Check the VNF descriptor
1287 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
1288 # Step 2. Check tenant exist
1290 if tenant_id
!= "any":
1291 check_tenant(mydb
, tenant_id
)
1292 if "tenant_id" in vnf_descriptor
["vnf"]:
1293 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1294 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1297 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1298 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1299 if global_config
["auto_push_VNF_to_VIMs"]:
1300 vims
= get_vim(mydb
, tenant_id
)
1302 # Step 4. Review the descriptor and add missing fields
1303 #print vnf_descriptor
1304 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1305 vnf_name
= vnf_descriptor
['vnf']['name']
1306 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1307 if "physical" in vnf_descriptor
['vnf']:
1308 del vnf_descriptor
['vnf']['physical']
1309 #print vnf_descriptor
1311 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1312 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1313 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1315 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1316 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1317 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1319 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1320 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1322 VNFCitem
["name"] = vnfc
['name']
1323 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
1325 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1328 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1329 myflavorDict
["description"] = VNFCitem
["description"]
1330 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1331 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1332 myflavorDict
["disk"] = vnfc
.get("disk", 1)
1333 myflavorDict
["extended"] = {}
1335 devices
= vnfc
.get("devices")
1337 myflavorDict
["extended"]["devices"] = devices
1340 # 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
1341 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1343 # Previous code has been commented
1344 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1345 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1346 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1347 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1349 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1351 # print "Error creating flavor: unknown processor model. Rollback successful."
1352 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1354 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1355 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1357 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1358 myflavorDict
['extended']['numas'] = vnfc
['numas']
1362 # Step 6.2 New flavors are created in the VIM
1363 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1365 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1366 VNFCitem
["flavor_id"] = flavor_id
1367 VNFCDict
[vnfc
['name']] = VNFCitem
1369 logger
.debug("Creating new images in the VIM for each VNFC")
1370 # Step 6.3 New images are created in the VIM
1371 #For each VNFC, we must create the appropriate image.
1372 #This "for" loop might be integrated with the previous one
1373 #In case this integration is made, the VNFCDict might become a VNFClist.
1374 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1375 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1377 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1378 image_dict
['universal_name']=vnfc
.get('image name')
1379 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1380 image_dict
['location']=vnfc
.get('VNFC image')
1381 #image_dict['new_location']=vnfc.get('image location')
1382 image_dict
['checksum']=vnfc
.get('image checksum')
1383 image_metadata_dict
= vnfc
.get('image metadata', None)
1384 image_metadata_str
= None
1385 if image_metadata_dict
is not None:
1386 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1387 image_dict
['metadata']=image_metadata_str
1388 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1389 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1390 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1391 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1392 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1393 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1394 if vnfc
.get("boot-data"):
1395 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1397 # Step 7. Storing the VNF descriptor in the repository
1398 if "descriptor" not in vnf_descriptor
["vnf"]:
1399 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1401 # Step 8. Adding the VNF to the NFVO DB
1402 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1404 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1405 _
, message
= rollback(mydb
, vims
, rollback_list
)
1406 if isinstance(e
, db_base_Exception
):
1407 error_text
= "Exception at database"
1408 elif isinstance(e
, KeyError):
1409 error_text
= "KeyError exception "
1410 e
.http_code
= HTTP_Internal_Server_Error
1412 error_text
= "Exception at VIM"
1413 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1414 #logger.error("start_scenario %s", error_text)
1415 raise NfvoException(error_text
, e
.http_code
)
1418 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
1419 #check valid tenant_id
1420 check_tenant(mydb
, tenant_id
)
1423 if tenant_id
!= "any":
1424 where_or
["tenant_id"] = tenant_id
1425 where_or
["public"] = True
1426 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1428 vnf_id
= vnf
["uuid"]
1429 filter_keys
= ('uuid', 'name', 'description', 'public', "tenant_id", "osm_id", "created_at")
1430 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.items() if k
in filter_keys
)
1431 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
1432 data
={'vnf' : filtered_content
}
1434 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
1435 SELECT
=('vms.uuid as uuid', 'vms.osm_id as osm_id', 'vms.name as name', 'vms.description as description',
1437 WHERE
={'vnfs.uuid': vnf_id
} )
1439 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1440 # change boot_data into boot-data
1442 if vm
.get("boot_data"):
1443 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
1446 data
['vnf']['VNFC'] = content
1447 #TODO: GET all the information from a VNFC and include it in the output.
1450 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
1451 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
1452 WHERE
={'vnfs.uuid': vnf_id
} )
1453 data
['vnf']['nets'] = content
1455 #GET ip-profile for each net
1456 for net
in data
['vnf']['nets']:
1457 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1458 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1459 WHERE
={'net_id': net
["uuid"]} )
1460 if len(ipprofiles
)==1:
1461 net
["ip_profile"] = ipprofiles
[0]
1462 elif len(ipprofiles
)>1:
1463 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
1466 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1468 #GET External Interfaces
1469 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1470 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1471 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1472 WHERE
={'vnfs.uuid': vnf_id
},
1473 WHERE_NOT
={'interfaces.external_name': None} )
1475 data
['vnf']['external-connections'] = content
1480 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1481 # Check tenant exist
1482 if tenant_id
!= "any":
1483 check_tenant(mydb
, tenant_id
)
1484 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1485 vims
= get_vim(mydb
, tenant_id
)
1489 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1491 if tenant_id
!= "any":
1492 where_or
["tenant_id"] = tenant_id
1493 where_or
["public"] = True
1494 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1495 vnf_id
= vnf
["uuid"]
1497 # "Getting the list of flavors and tenants of the VNF"
1498 flavorList
= get_flavorlist(mydb
, vnf_id
)
1499 if len(flavorList
)==0:
1500 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1502 imageList
= get_imagelist(mydb
, vnf_id
)
1503 if len(imageList
)==0:
1504 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1506 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1508 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1511 for flavor
in flavorList
:
1512 #check if flavor is used by other vnf
1514 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1516 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1518 #flavor not used, must be deleted
1520 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
1521 for flavor_vim
in c
:
1522 if flavor_vim
["datacenter_vim_id"] not in vims
: # TODO change to datacenter_tenant_id
1524 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
1526 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
1528 myvim
.delete_flavor(flavor_vim
["vim_id"])
1529 except vimconn
.vimconnNotFoundException
as e
:
1530 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
1531 except vimconn
.vimconnException
as e
:
1532 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1533 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1534 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
1535 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1536 mydb
.delete_row_by_id('flavors', flavor
)
1537 except db_base_Exception
as e
:
1538 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1539 undeletedItems
.append("flavor %s" % flavor
)
1542 for image
in imageList
:
1544 #check if image is used by other vnf
1545 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
1547 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1549 #image not used, must be deleted
1551 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1553 if image_vim
["datacenter_vim_id"] not in vims
: # TODO change to datacenter_tenant_id
1555 if image_vim
['created']=='false': #skip this image because not created by openmano
1557 myvim
=vims
[ image_vim
["datacenter_id"] ]
1559 myvim
.delete_image(image_vim
["vim_id"])
1560 except vimconn
.vimconnNotFoundException
as e
:
1561 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1562 except vimconn
.vimconnException
as e
:
1563 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1564 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1565 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1566 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1567 mydb
.delete_row_by_id('images', image
)
1568 except db_base_Exception
as e
:
1569 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1570 undeletedItems
.append("image %s" % image
)
1572 return vnf_id
+ " " + vnf
["name"]
1574 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1577 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1578 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1582 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
1583 myvim
= list(vims
.values())[0]
1584 result
,servers
= myvim
.get_hosts_info()
1586 return result
, servers
1587 topology
= {'name':myvim
['name'] , 'servers': servers
}
1588 return result
, topology
1591 def get_hosts(mydb
, nfvo_tenant_id
):
1592 vims
= get_vim(mydb
, nfvo_tenant_id
)
1594 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
1596 #print "nfvo.datacenter_action() error. Several datacenters found"
1597 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1598 myvim
= list(vims
.values())[0]
1600 hosts
= myvim
.get_hosts()
1601 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1603 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1605 server
={'name':host
['name'], 'vms':[]}
1606 for vm
in host
['instances']:
1607 #get internal name and model
1609 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1610 WHERE
={'vim_vm_id':vm
['id']} )
1612 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1614 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1616 except db_base_Exception
as e
:
1617 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1618 datacenter
['Datacenters'][0]['servers'].append(server
)
1619 #return -400, "en construccion"
1621 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1623 except vimconn
.vimconnException
as e
:
1624 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1627 def new_scenario(mydb
, tenant_id
, topo
):
1629 # result, vims = get_vim(mydb, tenant_id)
1631 # return result, vims
1633 if tenant_id
!= "any":
1634 check_tenant(mydb
, tenant_id
)
1635 if "tenant_id" in topo
:
1636 if topo
["tenant_id"] != tenant_id
:
1637 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1642 #1.1: get VNFs and external_networks (other_nets).
1644 other_nets
={} #external_networks, bridge_networks and data_networkds
1645 nodes
= topo
['topology']['nodes']
1646 for k
in list(nodes
.keys()):
1647 if nodes
[k
]['type'] == 'VNF':
1649 vnfs
[k
]['ifaces'] = {}
1650 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1651 other_nets
[k
] = nodes
[k
]
1652 other_nets
[k
]['external']=True
1653 elif nodes
[k
]['type'] == 'network':
1654 other_nets
[k
] = nodes
[k
]
1655 other_nets
[k
]['external']=False
1658 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1659 for name
,vnf
in list(vnfs
.items()):
1661 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1663 error_pos
= "'topology':'nodes':'" + name
+ "'"
1665 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1666 where
['uuid'] = vnf
['vnf_id']
1667 if 'VNF model' in vnf
:
1668 error_text
+= " 'VNF model' " + vnf
['VNF model']
1669 where
['name'] = vnf
['VNF model']
1671 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
1673 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1679 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1681 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1682 vnf
['uuid']=vnf_db
[0]['uuid']
1683 vnf
['description']=vnf_db
[0]['description']
1684 #get external interfaces
1685 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1686 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1687 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1688 for ext_iface
in ext_ifaces
:
1689 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1691 #1.4 get list of connections
1692 conections
= topo
['topology']['connections']
1693 conections_list
= []
1694 conections_list_name
= []
1695 for k
in list(conections
.keys()):
1696 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1697 ifaces_list
= list(conections
[k
]['nodes'].items())
1698 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1700 conection_pair_list
= [list(x
.items()) for x
in conections
[k
]['nodes']]
1701 for k2
in conection_pair_list
:
1704 con_type
= conections
[k
].get("type", "link")
1705 if con_type
!= "link":
1707 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
1708 other_nets
[k
] = {'external': False}
1709 if conections
[k
].get("graph"):
1710 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1711 ifaces_list
.append( (k
, None) )
1714 if con_type
== "external_network":
1715 other_nets
[k
]['external'] = True
1716 if conections
[k
].get("model"):
1717 other_nets
[k
]["model"] = conections
[k
]["model"]
1719 other_nets
[k
]["model"] = k
1720 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1721 other_nets
[k
]["model"] = con_type
1723 conections_list_name
.append(k
)
1724 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)
1725 #print set(ifaces_list)
1726 #check valid VNF and iface names
1727 for iface
in ifaces_list
:
1728 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1729 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1730 str(k
), iface
[0]), HTTP_Not_Found
)
1731 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1732 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1733 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
1735 #1.5 unify connections from the pair list to a consolidated list
1737 while index
< len(conections_list
):
1739 while index2
< len(conections_list
):
1740 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1741 conections_list
[index
] |
= conections_list
[index2
]
1742 del conections_list
[index2
]
1743 del conections_list_name
[index2
]
1746 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1748 #for k in conections_list:
1753 #1.6 Delete non external nets
1754 # for k in other_nets.keys():
1755 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1756 # for con in conections_list:
1758 # for index in range(0,len(con)):
1759 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1760 # for index in delete_indexes:
1763 #1.7: Check external_ports are present at database table datacenter_nets
1764 for k
,net
in list(other_nets
.items()):
1765 error_pos
= "'topology':'nodes':'" + k
+ "'"
1766 if net
['external']==False:
1767 if 'name' not in net
:
1769 if 'model' not in net
:
1770 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1771 if net
['model']=='bridge_net':
1772 net
['type']='bridge';
1773 elif net
['model']=='dataplane_net':
1776 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1778 #IF we do not want to check that external network exist at datacenter
1783 # if 'net_id' in net:
1784 # error_text += " 'net_id' " + net['net_id']
1785 # WHERE_['uuid'] = net['net_id']
1786 # if 'model' in net:
1787 # error_text += " 'model' " + net['model']
1788 # WHERE_['name'] = net['model']
1789 # if len(WHERE_) == 0:
1790 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1791 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1792 # FROM='datacenter_nets', WHERE=WHERE_ )
1794 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1796 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1797 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1799 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1800 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1801 # other_nets[k].update(net_db[0])
1804 net_nb
=0 #Number of nets
1805 for con
in conections_list
:
1806 #check if this is connected to a external net
1810 for index
in range(0,len(con
)):
1811 #check if this is connected to a external net
1812 for net_key
in list(other_nets
.keys()):
1813 if con
[index
][0]==net_key
:
1814 if other_net_index
>=0:
1815 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1816 #print "nfvo.new_scenario " + error_text
1817 raise NfvoException(error_text
, HTTP_Bad_Request
)
1819 other_net_index
= index
1820 net_target
= net_key
1822 #print "other_net_index", other_net_index
1824 if other_net_index
>=0:
1825 del con
[other_net_index
]
1826 #IF we do not want to check that external network exist at datacenter
1827 if other_nets
[net_target
]['external'] :
1828 if "name" not in other_nets
[net_target
]:
1829 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1830 if other_nets
[net_target
]["type"] == "external_network":
1831 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1832 other_nets
[net_target
]["type"] = "data"
1834 other_nets
[net_target
]["type"] = "bridge"
1836 # if other_nets[net_target]['external'] :
1837 # 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
1838 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1839 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1840 # print "nfvo.new_scenario " + error_text
1841 # return -HTTP_Bad_Request, error_text
1844 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1847 net_type_bridge
=False
1849 net_target
= "__-__net"+str(net_nb
)
1850 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
1851 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1854 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1855 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1856 if iface_type
=='mgmt' or iface_type
=='bridge':
1857 net_type_bridge
= True
1859 net_type_data
= True
1860 if net_type_bridge
and net_type_data
:
1861 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1862 #print "nfvo.new_scenario " + error_text
1863 raise NfvoException(error_text
, HTTP_Bad_Request
)
1864 elif net_type_bridge
:
1867 type_
='data' if len(con
)>2 else 'ptp'
1868 net_list
[net_target
]['type'] = type_
1871 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1872 #print "nfvo.new_scenario " + error_text
1874 raise NfvoException(error_text
, HTTP_Bad_Request
)
1876 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1877 #1.8.1 obtain management net
1878 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1879 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1880 #1.8.2 check all interfaces from all vnfs
1882 add_mgmt_net
= False
1883 for vnf
in list(vnfs
.values()):
1884 for iface
in list(vnf
['ifaces'].values()):
1885 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1886 #iface not connected
1887 iface
['net_key'] = 'mgmt'
1889 if add_mgmt_net
and 'mgmt' not in net_list
:
1890 net_list
['mgmt']=mgmt_net
[0]
1891 net_list
['mgmt']['external']=True
1892 net_list
['mgmt']['graph']={'visible':False}
1894 net_list
.update(other_nets
)
1896 #print 'net_list', net_list
1901 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1902 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1903 'tenant_id':tenant_id
, 'name':topo
['name'],
1904 'description':topo
.get('description',topo
['name']),
1905 'public': topo
.get('public', False)
1911 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
1912 """ This creates a new scenario for version 0.2 and 0.3"""
1913 scenario
= scenario_dict
["scenario"]
1914 if tenant_id
!= "any":
1915 check_tenant(mydb
, tenant_id
)
1916 if "tenant_id" in scenario
:
1917 if scenario
["tenant_id"] != tenant_id
:
1918 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1919 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1920 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1924 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
1925 for name
,vnf
in scenario
["vnfs"].items():
1927 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1929 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1931 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1932 where
['uuid'] = vnf
['vnf_id']
1933 if 'vnf_name' in vnf
:
1934 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1935 where
['name'] = vnf
['vnf_name']
1937 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1938 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
1943 if len(vnf_db
) == 0:
1944 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1945 elif len(vnf_db
) > 1:
1946 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1947 vnf
['uuid'] = vnf_db
[0]['uuid']
1948 vnf
['description'] = vnf_db
[0]['description']
1950 # get external interfaces
1951 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
1952 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1953 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name': None} )
1954 for ext_iface
in ext_ifaces
:
1955 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
1956 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1958 # 2: Insert net_key and ip_address at every vnf interface
1959 for net_name
, net
in list(scenario
["networks"].items()):
1960 net_type_bridge
= False
1961 net_type_data
= False
1962 for iface_dict
in net
["interfaces"]:
1963 if version
== "0.2":
1964 temp_dict
= iface_dict
1966 elif version
== "0.3":
1967 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
1968 ip_address
= iface_dict
.get('ip_address', None)
1969 for vnf
, iface
in list(temp_dict
.items()):
1970 if vnf
not in scenario
["vnfs"]:
1971 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
1973 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1974 raise NfvoException(error_text
, HTTP_Not_Found
)
1975 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1976 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
1977 .format(net_name
, iface
)
1978 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1979 raise NfvoException(error_text
, HTTP_Bad_Request
)
1980 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1981 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
1982 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1983 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1984 raise NfvoException(error_text
, HTTP_Bad_Request
)
1985 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1986 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
1987 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1988 if iface_type
== 'mgmt' or iface_type
== 'bridge':
1989 net_type_bridge
= True
1991 net_type_data
= True
1993 if net_type_bridge
and net_type_data
:
1994 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
1996 # logger.debug("nfvo.new_scenario " + error_text)
1997 raise NfvoException(error_text
, HTTP_Bad_Request
)
1998 elif net_type_bridge
:
2001 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
2003 if net
.get("implementation"): # for v0.3
2004 if type_
== "bridge" and net
["implementation"] == "underlay":
2005 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
2006 "'network':'{}'".format(net_name
)
2007 # logger.debug(error_text)
2008 raise NfvoException(error_text
, HTTP_Bad_Request
)
2009 elif type_
!= "bridge" and net
["implementation"] == "overlay":
2010 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
2011 "'network':'{}'".format(net_name
)
2012 # logger.debug(error_text)
2013 raise NfvoException(error_text
, HTTP_Bad_Request
)
2014 net
.pop("implementation")
2015 if "type" in net
and version
== "0.3": # for v0.3
2016 if type_
== "data" and net
["type"] == "e-line":
2017 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
2018 "'e-line' at 'network':'{}'".format(net_name
)
2019 # logger.debug(error_text)
2020 raise NfvoException(error_text
, HTTP_Bad_Request
)
2021 elif type_
== "ptp" and net
["type"] == "e-lan":
2025 net
['name'] = net_name
2026 net
['external'] = net
.get('external', False)
2028 # 3: insert at database
2029 scenario
["nets"] = scenario
["networks"]
2030 scenario
['tenant_id'] = tenant_id
2031 scenario_id
= mydb
.new_scenario(scenario
)
2035 def new_nsd_v3(mydb
, tenant_id
, nsd_descriptor
):
2037 Parses an OSM IM nsd_catalog and insert at DB
2040 :param nsd_descriptor:
2041 :return: The list of cretated NSD ids
2044 mynsd
= nsd_catalog
.nsd()
2046 pybindJSONDecoder
.load_ietf_json(nsd_descriptor
, None, None, obj
=mynsd
)
2047 except Exception as e
:
2048 raise NfvoException("Error. Invalid NS descriptor format: " + str(e
), HTTP_Bad_Request
)
2052 db_sce_interfaces
= []
2054 db_ip_profiles_index
= 0
2057 for nsd_yang
in mynsd
.nsd_catalog
.nsd
.values():
2058 nsd
= nsd_yang
.get()
2061 scenario_uuid
= str(uuid4())
2062 uuid_list
.append(scenario_uuid
)
2063 nsd_uuid_list
.append(scenario_uuid
)
2065 "uuid": scenario_uuid
,
2066 "osm_id": get_str(nsd
, "id", 255),
2067 "name": get_str(nsd
, "name", 255),
2068 "description": get_str(nsd
, "description", 255),
2069 "tenant_id": tenant_id
,
2070 "vendor": get_str(nsd
, "vendor", 255),
2071 "short_name": get_str(nsd
, "short-name", 255),
2072 "descriptor": str(nsd_descriptor
)[:60000],
2074 db_scenarios
.append(db_scenario
)
2076 # table sce_vnfs (constituent-vnfd)
2077 vnf_index2scevnf_uuid
= {}
2078 vnf_index2vnf_uuid
= {}
2079 for vnf
in nsd
.get("constituent-vnfd").values():
2080 existing_vnf
= mydb
.get_rows(FROM
="vnfs", WHERE
={'osm_id': str(vnf
["vnfd-id-ref"])[:255],
2081 'tenant_id': tenant_id
})
2082 if not existing_vnf
:
2083 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'constituent-vnfd':'vnfd-id-ref':"
2084 "'{}'. Reference to a non-existing VNFD in the catalog".format(
2085 str(nsd
["id"]), str(vnf
["vnfd-id-ref"])[:255]),
2087 sce_vnf_uuid
= str(uuid4())
2088 uuid_list
.append(sce_vnf_uuid
)
2090 "uuid": sce_vnf_uuid
,
2091 "scenario_id": scenario_uuid
,
2092 "name": existing_vnf
[0]["name"][:200] + "." + get_str(vnf
, "member-vnf-index", 5),
2093 "vnf_id": existing_vnf
[0]["uuid"],
2094 "member_vnf_index": int(vnf
["member-vnf-index"]),
2095 # TODO 'start-by-default': True
2097 vnf_index2scevnf_uuid
[int(vnf
['member-vnf-index'])] = sce_vnf_uuid
2098 vnf_index2vnf_uuid
[int(vnf
['member-vnf-index'])] = existing_vnf
[0]["uuid"]
2099 db_sce_vnfs
.append(db_sce_vnf
)
2101 # table ip_profiles (ip-profiles)
2102 ip_profile_name2db_table_index
= {}
2103 for ip_profile
in nsd
.get("ip-profiles").values():
2105 "ip_version": str(ip_profile
["ip-profile-params"].get("ip-version", "ipv4")),
2106 "subnet_address": str(ip_profile
["ip-profile-params"].get("subnet-address")),
2107 "gateway_address": str(ip_profile
["ip-profile-params"].get("gateway-address")),
2108 "dhcp_enabled": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("enabled", True)),
2109 "dhcp_start_address": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("start-address")),
2110 "dhcp_count": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("count")),
2113 for dns
in ip_profile
["ip-profile-params"]["dns-server"].values():
2114 dns_list
.append(str(dns
.get("address")))
2115 db_ip_profile
["dns_address"] = ";".join(dns_list
)
2116 if ip_profile
["ip-profile-params"].get('security-group'):
2117 db_ip_profile
["security_group"] = ip_profile
["ip-profile-params"]['security-group']
2118 ip_profile_name2db_table_index
[str(ip_profile
["name"])] = db_ip_profiles_index
2119 db_ip_profiles_index
+= 1
2120 db_ip_profiles
.append(db_ip_profile
)
2122 # table sce_nets (internal-vld)
2123 for vld
in nsd
.get("vld").values():
2124 sce_net_uuid
= str(uuid4())
2125 uuid_list
.append(sce_net_uuid
)
2127 "uuid": sce_net_uuid
,
2128 "name": get_str(vld
, "name", 255),
2129 "scenario_id": scenario_uuid
,
2131 "multipoint": not vld
.get("type") == "ELINE",
2133 "description": get_str(vld
, "description", 255),
2135 # guess type of network
2136 if vld
.get("mgmt-network"):
2137 db_sce_net
["type"] = "bridge"
2138 db_sce_net
["external"] = True
2139 elif vld
.get("provider-network").get("overlay-type") == "VLAN":
2140 db_sce_net
["type"] = "data"
2142 db_sce_net
["type"] = "bridge"
2143 db_sce_nets
.append(db_sce_net
)
2145 # ip-profile, link db_ip_profile with db_sce_net
2146 if vld
.get("ip-profile-ref"):
2147 ip_profile_name
= vld
.get("ip-profile-ref")
2148 if ip_profile_name
not in ip_profile_name2db_table_index
:
2149 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'ip-profile-ref':'{}'."
2150 " Reference to a non-existing 'ip_profiles'".format(
2151 str(nsd
["id"]), str(vld
["id"]), str(vld
["ip-profile-ref"])),
2153 db_ip_profiles
[ip_profile_name2db_table_index
[ip_profile_name
]]["sce_net_id"] = sce_net_uuid
2155 # table sce_interfaces (vld:vnfd-connection-point-ref)
2156 for iface
in vld
.get("vnfd-connection-point-ref").values():
2157 vnf_index
= int(iface
['member-vnf-index-ref'])
2158 # check correct parameters
2159 if vnf_index
not in vnf_index2vnf_uuid
:
2160 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2161 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2162 "'nsd':'constituent-vnfd'".format(
2163 str(nsd
["id"]), str(vld
["id"]), str(iface
["member-vnf-index-ref"])),
2166 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2167 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2168 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2169 'external_name': get_str(iface
, "vnfd-connection-point-ref",
2171 if not existing_ifaces
:
2172 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2173 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2174 "connection-point name at VNFD '{}'".format(
2175 str(nsd
["id"]), str(vld
["id"]), str(iface
["vnfd-connection-point-ref"]),
2176 str(iface
.get("vnfd-id-ref"))[:255]),
2178 interface_uuid
= existing_ifaces
[0]["uuid"]
2179 sce_interface_uuid
= str(uuid4())
2180 uuid_list
.append(sce_net_uuid
)
2181 db_sce_interface
= {
2182 "uuid": sce_interface_uuid
,
2183 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2184 "sce_net_id": sce_net_uuid
,
2185 "interface_id": interface_uuid
,
2186 # "ip_address": #TODO
2188 db_sce_interfaces
.append(db_sce_interface
)
2191 {"scenarios": db_scenarios
},
2192 {"sce_nets": db_sce_nets
},
2193 {"ip_profiles": db_ip_profiles
},
2194 {"sce_vnfs": db_sce_vnfs
},
2195 {"sce_interfaces": db_sce_interfaces
},
2198 logger
.debug("create_vnf Deployment done vnfDict: %s",
2199 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
2200 mydb
.new_rows(db_tables
, uuid_list
)
2201 return nsd_uuid_list
2202 except NfvoException
:
2204 except Exception as e
:
2205 logger
.error("Exception {}".format(e
))
2206 raise # NfvoException("Exception {}".format(e), HTTP_Bad_Request)
2209 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
2210 data
["uuid"] = scenario_id
2211 data
["tenant_id"] = tenant_id
2212 c
= mydb
.edit_scenario( data
)
2216 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
2217 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2218 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
2219 vims
= {datacenter_id
: myvim
}
2220 myvim_tenant
= myvim
['tenant_id']
2221 datacenter_name
= myvim
['name']
2225 #print "Checking that the scenario_id exists and getting the scenario dictionary"
2226 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
=datacenter_id
)
2227 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
2228 scenarioDict
['datacenter_id'] = datacenter_id
2229 #print '================scenarioDict======================='
2230 #print json.dumps(scenarioDict, indent=4)
2231 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
2233 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
2234 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2236 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
2237 auxNetDict
['scenario'] = {}
2239 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
2240 for sce_net
in scenarioDict
['nets']:
2241 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
2243 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
2244 myNetName
= myNetName
[0:255] #limit length
2245 myNetType
= sce_net
['type']
2247 myNetDict
["name"] = myNetName
2248 myNetDict
["type"] = myNetType
2249 myNetDict
["tenant_id"] = myvim_tenant
2250 myNetIPProfile
= sce_net
.get('ip_profile', None)
2252 #We should use the dictionary as input parameter for new_network
2254 if not sce_net
["external"]:
2255 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2256 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
2257 sce_net
['vim_id'] = network_id
2258 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
2259 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2260 sce_net
["created"] = True
2262 if sce_net
['vim_id'] == None:
2263 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
2264 _
, message
= rollback(mydb
, vims
, rollbackList
)
2265 logger
.error("nfvo.start_scenario: %s", error_text
)
2266 raise NfvoException(error_text
, HTTP_Bad_Request
)
2267 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
2268 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
2270 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
2271 #For each vnf net, we create it and we add it to instanceNetlist.
2273 for sce_vnf
in scenarioDict
['vnfs']:
2274 for net
in sce_vnf
['nets']:
2275 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
2277 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
2278 myNetName
= myNetName
[0:255] #limit length
2279 myNetType
= net
['type']
2281 myNetDict
["name"] = myNetName
2282 myNetDict
["type"] = myNetType
2283 myNetDict
["tenant_id"] = myvim_tenant
2284 myNetIPProfile
= net
.get('ip_profile', None)
2287 #We should use the dictionary as input parameter for new_network
2288 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2289 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
2290 net
['vim_id'] = network_id
2291 if sce_vnf
['uuid'] not in auxNetDict
:
2292 auxNetDict
[sce_vnf
['uuid']] = {}
2293 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
2294 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2295 net
["created"] = True
2297 #print "auxNetDict:"
2298 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2300 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
2301 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2303 for sce_vnf
in scenarioDict
['vnfs']:
2304 vnf_availability_zones
= []
2305 for vm
in sce_vnf
['vms']:
2306 vm_av
= vm
.get('availability_zone')
2307 if vm_av
and vm_av
not in vnf_availability_zones
:
2308 vnf_availability_zones
.append(vm_av
)
2310 # check if there is enough availability zones available at vim level.
2311 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
2312 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
2313 raise NfvoException('No enough availability zones at VIM for this deployment', HTTP_Bad_Request
)
2315 for vm
in sce_vnf
['vms']:
2318 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
2319 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
2320 #myVMDict['description'] = vm['description']
2321 myVMDict
['description'] = myVMDict
['name'][0:99]
2323 myVMDict
['start'] = "no"
2324 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2325 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
2327 #create image at vim in case it not exist
2328 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2329 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
2330 vm
['vim_image_id'] = image_id
2332 #create flavor at vim in case it not exist
2333 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2334 if flavor_dict
['extended']!=None:
2335 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2336 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
2337 vm
['vim_flavor_id'] = flavor_id
2340 myVMDict
['imageRef'] = vm
['vim_image_id']
2341 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2342 myVMDict
['networks'] = []
2343 for iface
in vm
['interfaces']:
2345 if iface
['type']=="data":
2346 netDict
['type'] = iface
['model']
2347 elif "model" in iface
and iface
["model"]!=None:
2348 netDict
['model']=iface
['model']
2349 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2350 #discover type of interface looking at flavor
2351 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2352 for flavor_iface
in numa
.get('interfaces',[]):
2353 if flavor_iface
.get('name') == iface
['internal_name']:
2354 if flavor_iface
['dedicated'] == 'yes':
2355 netDict
['type']="PF" #passthrough
2356 elif flavor_iface
['dedicated'] == 'no':
2357 netDict
['type']="VF" #siov
2358 elif flavor_iface
['dedicated'] == 'yes:sriov':
2359 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2360 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2362 netDict
["use"]=iface
['type']
2363 if netDict
["use"]=="data" and not netDict
.get("type"):
2364 #print "netDict", netDict
2365 #print "iface", iface
2366 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'])
2367 if flavor_dict
.get('extended')==None:
2368 raise NfvoException(e_text
+ "After database migration some information is not available. \
2369 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
2371 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
2372 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2373 netDict
["type"]="virtual"
2374 if "vpci" in iface
and iface
["vpci"] is not None:
2375 netDict
['vpci'] = iface
['vpci']
2376 if "mac" in iface
and iface
["mac"] is not None:
2377 netDict
['mac_address'] = iface
['mac']
2378 if "port-security" in iface
and iface
["port-security"] is not None:
2379 netDict
['port_security'] = iface
['port-security']
2380 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2381 netDict
['floating_ip'] = iface
['floating-ip']
2382 netDict
['name'] = iface
['internal_name']
2383 if iface
['net_id'] is None:
2384 for vnf_iface
in sce_vnf
["interfaces"]:
2387 if vnf_iface
['interface_id']==iface
['uuid']:
2388 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
2391 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2392 #skip bridge ifaces not connected to any net
2393 #if 'net_id' not in netDict or netDict['net_id']==None:
2395 myVMDict
['networks'].append(netDict
)
2396 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2397 #print myVMDict['name']
2398 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2399 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2400 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2402 if 'availability_zone' in myVMDict
:
2403 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
2407 vm_id
= myvim
.new_vminstance(myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2408 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2409 availability_zone_index
=av_index
,
2410 availability_zone_list
=vnf_availability_zones
)
2411 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
2412 vm
['vim_id'] = vm_id
2413 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2414 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2415 for net
in myVMDict
['networks']:
2417 for iface
in vm
['interfaces']:
2418 if net
["name"]==iface
["internal_name"]:
2419 iface
["vim_id"]=net
["vim_id"]
2422 logger
.debug("start scenario Deployment done")
2423 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2424 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
2425 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
2426 return mydb
.get_instance_scenario(instance_id
)
2428 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
2429 _
, message
= rollback(mydb
, vims
, rollbackList
)
2430 if isinstance(e
, db_base_Exception
):
2431 error_text
= "Exception at database"
2433 error_text
= "Exception at VIM"
2434 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2435 #logger.error("start_scenario %s", error_text)
2436 raise NfvoException(error_text
, e
.http_code
)
2438 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
2439 """ join the cloud config information into cloud_config_preserve.
2440 In case of conflict cloud_config_preserve preserves
2443 if not cloud_config_preserve
and not cloud_config
:
2446 new_cloud_config
= {"key-pairs":[], "users":[]}
2448 if cloud_config_preserve
:
2449 for key
in cloud_config_preserve
.get("key-pairs", () ):
2450 if key
not in new_cloud_config
["key-pairs"]:
2451 new_cloud_config
["key-pairs"].append(key
)
2453 for key
in cloud_config
.get("key-pairs", () ):
2454 if key
not in new_cloud_config
["key-pairs"]:
2455 new_cloud_config
["key-pairs"].append(key
)
2456 if not new_cloud_config
["key-pairs"]:
2457 del new_cloud_config
["key-pairs"]
2461 new_cloud_config
["users"] += cloud_config
.get("users", () )
2462 if cloud_config_preserve
:
2463 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
2464 index_to_delete
= []
2465 users
= new_cloud_config
.get("users", [])
2466 for index0
in range(0,len(users
)):
2467 if index0
in index_to_delete
:
2469 for index1
in range(index0
+1,len(users
)):
2470 if index1
in index_to_delete
:
2472 if users
[index0
]["name"] == users
[index1
]["name"]:
2473 index_to_delete
.append(index1
)
2474 for key
in users
[index1
].get("key-pairs",()):
2475 if "key-pairs" not in users
[index0
]:
2476 users
[index0
]["key-pairs"] = [key
]
2477 elif key
not in users
[index0
]["key-pairs"]:
2478 users
[index0
]["key-pairs"].append(key
)
2479 index_to_delete
.sort(reverse
=True)
2480 for index
in index_to_delete
:
2482 if not new_cloud_config
["users"]:
2483 del new_cloud_config
["users"]
2486 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
2487 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
2488 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
2489 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
2492 new_cloud_config
["user-data"] = []
2493 if cloud_config
and cloud_config
.get("user-data"):
2494 if isinstance(cloud_config
["user-data"], list):
2495 new_cloud_config
["user-data"] += cloud_config
["user-data"]
2497 new_cloud_config
["user-data"].append(cloud_config
["user-data"])
2498 if cloud_config_preserve
and cloud_config_preserve
.get("user-data"):
2499 if isinstance(cloud_config_preserve
["user-data"], list):
2500 new_cloud_config
["user-data"] += cloud_config_preserve
["user-data"]
2502 new_cloud_config
["user-data"].append(cloud_config_preserve
["user-data"])
2503 if not new_cloud_config
["user-data"]:
2504 del new_cloud_config
["user-data"]
2507 new_cloud_config
["config-files"] = []
2508 if cloud_config
and cloud_config
.get("config-files") != None:
2509 new_cloud_config
["config-files"] += cloud_config
["config-files"]
2510 if cloud_config_preserve
:
2511 for file in cloud_config_preserve
.get("config-files", ()):
2512 for index
in range(0, len(new_cloud_config
["config-files"])):
2513 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
2514 new_cloud_config
["config-files"][index
] = file
2517 new_cloud_config
["config-files"].append(file)
2518 if not new_cloud_config
["config-files"]:
2519 del new_cloud_config
["config-files"]
2520 return new_cloud_config
2523 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
2524 datacenter_id
= None
2525 datacenter_name
= None
2528 if datacenter_tenant_id
:
2529 thread_id
= datacenter_tenant_id
2530 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
2532 where_
={"td.nfvo_tenant_id": tenant_id
}
2533 if datacenter_id_name
:
2534 if utils
.check_valid_uuid(datacenter_id_name
):
2535 datacenter_id
= datacenter_id_name
2536 where_
["dt.datacenter_id"] = datacenter_id
2538 datacenter_name
= datacenter_id_name
2539 where_
["d.name"] = datacenter_name
2540 if datacenter_tenant_id
:
2541 where_
["dt.uuid"] = datacenter_tenant_id
2542 datacenters
= mydb
.get_rows(
2543 SELECT
=("dt.uuid as datacenter_tenant_id",),
2544 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
2545 "join datacenters as d on d.uuid=dt.datacenter_id",
2547 if len(datacenters
) > 1:
2548 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2550 thread_id
= datacenters
[0]["datacenter_tenant_id"]
2551 thread
= vim_threads
["running"].get(thread_id
)
2553 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
2554 return thread_id
, thread
2555 except db_base_Exception
as e
:
2556 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
2559 def get_datacenter_uuid(mydb
, tenant_id
, datacenter_id_name
):
2561 if utils
.check_valid_uuid(datacenter_id_name
):
2562 WHERE_dict
['d.uuid'] = datacenter_id_name
2564 WHERE_dict
['d.name'] = datacenter_id_name
2567 WHERE_dict
['nfvo_tenant_id'] = tenant_id
2568 from_
= "tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join datacenter_tenants as" \
2569 " dt on td.datacenter_tenant_id=dt.uuid"
2571 from_
= 'datacenters as d'
2572 vimaccounts
= mydb
.get_rows(FROM
=from_
, SELECT
=("d.uuid as uuid",), WHERE
=WHERE_dict
)
2573 if len(vimaccounts
) == 0:
2574 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
2575 elif len(vimaccounts
)>1:
2576 #print "nfvo.datacenter_action() error. Several datacenters found"
2577 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2578 return vimaccounts
[0]["uuid"]
2581 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
2582 datacenter_id
= None
2583 datacenter_name
= None
2584 if datacenter_id_name
:
2585 if utils
.check_valid_uuid(datacenter_id_name
):
2586 datacenter_id
= datacenter_id_name
2588 datacenter_name
= datacenter_id_name
2589 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
2591 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
2593 #print "nfvo.datacenter_action() error. Several datacenters found"
2594 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2595 return list(vims
.keys())[0], list(vims
.values())[0]
2599 '''Takes dict d and updates it with the values in dict u.'''
2600 '''It merges all depth levels'''
2601 for k
, v
in u
.items():
2602 if isinstance(v
, collections
.Mapping
):
2603 r
= update(d
.get(k
, {}), v
)
2609 def create_instance(mydb
, tenant_id
, instance_dict
):
2610 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2611 # logger.debug("Creating instance...")
2612 scenario
= instance_dict
["scenario"]
2614 # find main datacenter
2616 myvim_threads_id
= {}
2617 datacenter
= instance_dict
.get("datacenter")
2618 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2619 myvims
[default_datacenter_id
] = vim
2620 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
2621 tenant
= mydb
.get_rows_by_id('nfvo_tenants', tenant_id
)
2622 # myvim_tenant = myvim['tenant_id']
2626 # print "Checking that the scenario exists and getting the scenario dictionary"
2627 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, datacenter_vim_id
=myvim_threads_id
[default_datacenter_id
],
2628 datacenter_id
=default_datacenter_id
)
2630 # logger.debug(">>>>>> Dictionaries before merging")
2631 # logger.debug(">>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
2632 # logger.debug(">>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
2634 db_instance_vnfs
= []
2635 db_instance_vms
= []
2636 db_instance_interfaces
= []
2641 instance_name
= instance_dict
["name"]
2642 instance_uuid
= str(uuid4())
2643 uuid_list
.append(instance_uuid
)
2644 db_instance_scenario
= {
2645 "uuid": instance_uuid
,
2646 "name": instance_name
,
2647 "tenant_id": tenant_id
,
2648 "scenario_id": scenarioDict
['uuid'],
2649 "datacenter_id": default_datacenter_id
,
2650 # filled bellow 'datacenter_tenant_id'
2651 "description": instance_dict
.get("description"),
2653 if scenarioDict
.get("cloud-config"):
2654 db_instance_scenario
["cloud_config"] = yaml
.safe_dump(scenarioDict
["cloud-config"],
2655 default_flow_style
=True, width
=256)
2656 instance_action_id
= get_task_id()
2657 db_instance_action
= {
2658 "uuid": instance_action_id
, # same uuid for the instance and the action on create
2659 "tenant_id": tenant_id
,
2660 "instance_id": instance_uuid
,
2661 "description": "CREATE",
2664 # Auxiliary dictionaries from x to y
2665 vnf_net2instance
= {}
2666 sce_net2instance
= {}
2667 net2task_id
= {'scenario': {}}
2669 # logger.debug("Creating instance from scenario-dict:\n%s",
2670 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
2672 # 0 check correct parameters
2673 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).items():
2675 for scenario_net
in scenarioDict
['nets']:
2676 if net_name
== scenario_net
["name"]:
2680 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
),
2682 if "sites" not in net_instance_desc
:
2683 net_instance_desc
["sites"] = [ {} ]
2684 site_without_datacenter_field
= False
2685 for site
in net_instance_desc
["sites"]:
2686 if site
.get("datacenter"):
2687 site
["datacenter"] = get_datacenter_uuid(mydb
, tenant_id
, site
["datacenter"])
2688 if site
["datacenter"] not in myvims
:
2689 # Add this datacenter to myvims
2690 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
2692 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
2693 site
["datacenter"] = d
# change name to id
2695 if site_without_datacenter_field
:
2696 raise NfvoException("Found more than one entries without datacenter field at "
2697 "instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
2698 site_without_datacenter_field
= True
2699 site
["datacenter"] = default_datacenter_id
# change name to id
2701 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).items():
2703 for scenario_vnf
in scenarioDict
['vnfs']:
2704 if vnf_name
== scenario_vnf
['name']:
2708 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
2709 if "datacenter" in vnf_instance_desc
:
2710 # Add this datacenter to myvims
2711 vnf_instance_desc
["datacenter"] = get_datacenter_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2712 if vnf_instance_desc
["datacenter"] not in myvims
:
2713 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2715 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2716 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
2718 # 0.1 parse cloud-config parameters
2719 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
2720 # We add the RO key to cloud_config
2721 if tenant
[0].get('RO_pub_key'):
2722 RO_key
= {"key-pairs": [tenant
[0]['RO_pub_key']]}
2723 cloud_config
= unify_cloud_config(cloud_config
, RO_key
)
2725 # 0.2 merge instance information into scenario
2726 # Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
2727 # However, this is not possible yet.
2728 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).items():
2729 for scenario_net
in scenarioDict
['nets']:
2730 if net_name
== scenario_net
["name"]:
2731 if 'ip-profile' in net_instance_desc
:
2732 # translate from input format to database format
2733 ipprofile_in
= net_instance_desc
['ip-profile']
2735 ipprofile_db
['subnet_address'] = ipprofile_in
.get('subnet-address')
2736 ipprofile_db
['ip_version'] = ipprofile_in
.get('ip-version', 'IPv4')
2737 ipprofile_db
['gateway_address'] = ipprofile_in
.get('gateway-address')
2738 ipprofile_db
['dns_address'] = ipprofile_in
.get('dns-address')
2739 if isinstance(ipprofile_db
['dns_address'], (list, tuple)):
2740 ipprofile_db
['dns_address'] = ";".join(ipprofile_db
['dns_address'])
2741 if 'dhcp' in ipprofile_in
:
2742 ipprofile_db
['dhcp_start_address'] = ipprofile_in
['dhcp'].get('start-address')
2743 ipprofile_db
['dhcp_enabled'] = ipprofile_in
['dhcp'].get('enabled', True)
2744 ipprofile_db
['dhcp_count'] = ipprofile_in
['dhcp'].get('count' )
2745 if 'ip_profile' not in scenario_net
:
2746 scenario_net
['ip_profile'] = ipprofile_db
2748 update(scenario_net
['ip_profile'], ipprofile_db
)
2749 for interface
in net_instance_desc
.get('interfaces', () ):
2750 if 'ip_address' in interface
:
2751 for vnf
in scenarioDict
['vnfs']:
2752 if interface
['vnf'] == vnf
['name']:
2753 for vnf_interface
in vnf
['interfaces']:
2754 if interface
['vnf_interface'] == vnf_interface
['external_name']:
2755 vnf_interface
['ip_address']=interface
['ip_address']
2757 # logger.debug(">>>>>>>> Merged dictionary")
2758 # logger.debug("Creating instance scenario-dict MERGED:\n%s",
2759 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
2761 # 1. Creating new nets (sce_nets) in the VIM"
2762 db_instance_nets
= []
2763 for sce_net
in scenarioDict
['nets']:
2764 descriptor_net
= instance_dict
.get("networks", {}).get(sce_net
["name"], {})
2765 net_name
= descriptor_net
.get("vim-network-name")
2766 sce_net2instance
[sce_net
['uuid']] = {}
2767 net2task_id
['scenario'][sce_net
['uuid']] = {}
2769 sites
= descriptor_net
.get("sites", [ {} ])
2771 if site
.get("datacenter"):
2772 vim
= myvims
[ site
["datacenter"] ]
2773 datacenter_id
= site
["datacenter"]
2774 myvim_thread_id
= myvim_threads_id
[ site
["datacenter"] ]
2776 vim
= myvims
[ default_datacenter_id
]
2777 datacenter_id
= default_datacenter_id
2778 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2779 net_type
= sce_net
['type']
2780 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} # 'shared': True
2783 if sce_net
["external"]:
2784 net_name
= sce_net
["name"]
2786 net_name
= "{}.{}".format(instance_name
, sce_net
["name"])
2787 net_name
= net_name
[:255] # limit length
2789 if "netmap-use" in site
or "netmap-create" in site
:
2790 create_network
= False
2791 lookfor_network
= False
2792 if "netmap-use" in site
:
2793 lookfor_network
= True
2794 if utils
.check_valid_uuid(site
["netmap-use"]):
2795 filter_text
= "scenario id '%s'" % site
["netmap-use"]
2796 lookfor_filter
["id"] = site
["netmap-use"]
2798 filter_text
= "scenario name '%s'" % site
["netmap-use"]
2799 lookfor_filter
["name"] = site
["netmap-use"]
2800 if "netmap-create" in site
:
2801 create_network
= True
2802 net_vim_name
= net_name
2803 if site
["netmap-create"]:
2804 net_vim_name
= site
["netmap-create"]
2805 elif sce_net
["external"]:
2806 if sce_net
['vim_id'] != None:
2807 # there is a netmap at datacenter_nets database # TODO REVISE!!!!
2808 create_network
= False
2809 lookfor_network
= True
2810 lookfor_filter
["id"] = sce_net
['vim_id']
2811 filter_text
= "vim_id '{}' datacenter_netmap name '{}'. Try to reload vims with "\
2812 "datacenter-net-update".format(sce_net
['vim_id'], sce_net
["name"])
2813 # look for network at datacenter and return error
2815 # There is not a netmap, look at datacenter for a net with this name and create if not found
2816 create_network
= True
2817 lookfor_network
= True
2818 lookfor_filter
["name"] = sce_net
["name"]
2819 net_vim_name
= sce_net
["name"]
2820 filter_text
= "scenario name '%s'" % sce_net
["name"]
2822 net_vim_name
= net_name
2823 create_network
= True
2824 lookfor_network
= False
2828 task_action
= "CREATE"
2829 task_extra
["params"] = (net_vim_name
, net_type
, sce_net
.get('ip_profile', None))
2831 task_extra
["find"] = (lookfor_filter
,)
2832 elif lookfor_network
:
2833 task_action
= "FIND"
2834 task_extra
["params"] = (lookfor_filter
,)
2836 # fill database content
2837 net_uuid
= str(uuid4())
2838 uuid_list
.append(net_uuid
)
2839 sce_net2instance
[sce_net
['uuid']][datacenter_id
] = net_uuid
2843 "instance_scenario_id": instance_uuid
,
2844 "sce_net_id": sce_net
["uuid"],
2845 "created": create_network
,
2846 'datacenter_id': datacenter_id
,
2847 'datacenter_tenant_id': myvim_thread_id
,
2848 'status': 'BUILD' if create_network
else "ACTIVE"
2850 db_instance_nets
.append(db_net
)
2852 "instance_action_id": instance_action_id
,
2853 "status": "SCHEDULED",
2854 "task_index": task_index
,
2855 "datacenter_vim_id": myvim_thread_id
,
2856 "action": task_action
,
2857 "item": "instance_nets",
2858 "item_id": net_uuid
,
2859 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
2861 net2task_id
['scenario'][sce_net
['uuid']][datacenter_id
] = task_index
2863 db_vim_actions
.append(db_vim_action
)
2865 if 'ip_profile' in sce_net
:
2867 'instance_net_id': net_uuid
,
2868 'ip_version': sce_net
['ip_profile']['ip_version'],
2869 'subnet_address': sce_net
['ip_profile']['subnet_address'],
2870 'gateway_address': sce_net
['ip_profile']['gateway_address'],
2871 'dns_address': sce_net
['ip_profile']['dns_address'],
2872 'dhcp_enabled': sce_net
['ip_profile']['dhcp_enabled'],
2873 'dhcp_start_address': sce_net
['ip_profile']['dhcp_start_address'],
2874 'dhcp_count': sce_net
['ip_profile']['dhcp_count'],
2876 db_ip_profiles
.append(db_ip_profile
)
2878 # 2. Creating new nets (vnf internal nets) in the VIM"
2879 # For each vnf net, we create it and we add it to instanceNetlist.
2880 for sce_vnf
in scenarioDict
['vnfs']:
2881 for net
in sce_vnf
['nets']:
2882 if sce_vnf
.get("datacenter"):
2883 datacenter_id
= sce_vnf
["datacenter"]
2884 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
2886 datacenter_id
= default_datacenter_id
2887 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2888 descriptor_net
= instance_dict
.get("vnfs", {}).get(sce_vnf
["name"], {})
2889 net_name
= descriptor_net
.get("name")
2891 net_name
= "{}.{}".format(instance_name
, net
["name"])
2892 net_name
= net_name
[:255] # limit length
2893 net_type
= net
['type']
2895 if sce_vnf
['uuid'] not in vnf_net2instance
:
2896 vnf_net2instance
[sce_vnf
['uuid']] = {}
2897 if sce_vnf
['uuid'] not in net2task_id
:
2898 net2task_id
[sce_vnf
['uuid']] = {}
2899 net2task_id
[sce_vnf
['uuid']][net
['uuid']] = task_index
2901 # fill database content
2902 net_uuid
= str(uuid4())
2903 uuid_list
.append(net_uuid
)
2904 vnf_net2instance
[sce_vnf
['uuid']][net
['uuid']] = net_uuid
2908 "instance_scenario_id": instance_uuid
,
2909 "net_id": net
["uuid"],
2911 'datacenter_id': datacenter_id
,
2912 'datacenter_tenant_id': myvim_thread_id
,
2914 db_instance_nets
.append(db_net
)
2917 "instance_action_id": instance_action_id
,
2918 "task_index": task_index
,
2919 "datacenter_vim_id": myvim_thread_id
,
2920 "status": "SCHEDULED",
2922 "item": "instance_nets",
2923 "item_id": net_uuid
,
2924 "extra": yaml
.safe_dump({"params": (net_name
, net_type
, net
.get('ip_profile',None))},
2925 default_flow_style
=True, width
=256)
2928 db_vim_actions
.append(db_vim_action
)
2930 if 'ip_profile' in net
:
2932 'instance_net_id': net_uuid
,
2933 'ip_version': net
['ip_profile']['ip_version'],
2934 'subnet_address': net
['ip_profile']['subnet_address'],
2935 'gateway_address': net
['ip_profile']['gateway_address'],
2936 'dns_address': net
['ip_profile']['dns_address'],
2937 'dhcp_enabled': net
['ip_profile']['dhcp_enabled'],
2938 'dhcp_start_address': net
['ip_profile']['dhcp_start_address'],
2939 'dhcp_count': net
['ip_profile']['dhcp_count'],
2941 db_ip_profiles
.append(db_ip_profile
)
2943 # print "vnf_net2instance:"
2944 # print yaml.safe_dump(vnf_net2instance, indent=4, default_flow_style=False)
2946 # 3. Creating new vm instances in the VIM
2947 # myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2948 sce_vnf_list
= sorted(scenarioDict
['vnfs'], key
=lambda k
: k
['name'])
2949 for sce_vnf
in sce_vnf_list
:
2950 vnf_availability_zones
= []
2951 for vm
in sce_vnf
['vms']:
2952 vm_av
= vm
.get('availability_zone')
2953 if vm_av
and vm_av
not in vnf_availability_zones
:
2954 vnf_availability_zones
.append(vm_av
)
2956 # check if there is enough availability zones available at vim level.
2957 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
2958 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
2959 raise NfvoException('No enough availability zones at VIM for this deployment', HTTP_Bad_Request
)
2961 if sce_vnf
.get("datacenter"):
2962 vim
= myvims
[ sce_vnf
["datacenter"] ]
2963 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"] ]
2964 datacenter_id
= sce_vnf
["datacenter"]
2966 vim
= myvims
[ default_datacenter_id
]
2967 myvim_thread_id
= myvim_threads_id
[ default_datacenter_id
]
2968 datacenter_id
= default_datacenter_id
2969 sce_vnf
["datacenter_id"] = datacenter_id
2972 vnf_uuid
= str(uuid4())
2973 uuid_list
.append(vnf_uuid
)
2976 'instance_scenario_id': instance_uuid
,
2977 'vnf_id': sce_vnf
['vnf_id'],
2978 'sce_vnf_id': sce_vnf
['uuid'],
2979 'datacenter_id': datacenter_id
,
2980 'datacenter_tenant_id': myvim_thread_id
,
2982 db_instance_vnfs
.append(db_instance_vnf
)
2984 for vm
in sce_vnf
['vms']:
2986 myVMDict
['name'] = "{}.{}.{}".format(instance_name
[:64], sce_vnf
['name'][:64], vm
["name"][:64])
2987 myVMDict
['description'] = myVMDict
['name'][0:99]
2989 # myVMDict['start'] = "no"
2990 myVMDict
['name'] = myVMDict
['name'][0:255] # limit name length
2991 #create image at vim in case it not exist
2992 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2993 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
2994 vm
['vim_image_id'] = image_id
2996 # create flavor at vim in case it not exist
2997 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2998 if flavor_dict
['extended']!=None:
2999 flavor_dict
['extended'] = yaml
.load(flavor_dict
['extended'])
3000 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
3002 # Obtain information for additional disks
3003 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',), WHERE
={'vim_id': flavor_id
})
3004 if not extended_flavor_dict
:
3005 raise NfvoException("flavor '{}' not found".format(flavor_id
), HTTP_Not_Found
)
3008 # extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
3009 myVMDict
['disks'] = None
3010 extended_info
= extended_flavor_dict
[0]['extended']
3011 if extended_info
!= None:
3012 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
3013 if 'disks' in extended_flavor_dict_yaml
:
3014 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
3016 vm
['vim_flavor_id'] = flavor_id
3017 myVMDict
['imageRef'] = vm
['vim_image_id']
3018 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
3019 myVMDict
['availability_zone'] = vm
.get('availability_zone')
3020 myVMDict
['networks'] = []
3021 task_depends_on
= []
3022 # TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
3024 for iface
in vm
['interfaces']:
3026 if iface
['type']=="data":
3027 netDict
['type'] = iface
['model']
3028 elif "model" in iface
and iface
["model"]!=None:
3029 netDict
['model']=iface
['model']
3030 # TODO in future, remove this because mac_address will not be set, and the type of PV,VF
3031 # is obtained from iterface table model
3032 # discover type of interface looking at flavor
3033 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
3034 for flavor_iface
in numa
.get('interfaces',[]):
3035 if flavor_iface
.get('name') == iface
['internal_name']:
3036 if flavor_iface
['dedicated'] == 'yes':
3037 netDict
['type']="PF" #passthrough
3038 elif flavor_iface
['dedicated'] == 'no':
3039 netDict
['type']="VF" #siov
3040 elif flavor_iface
['dedicated'] == 'yes:sriov':
3041 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
3042 netDict
["mac_address"] = flavor_iface
.get("mac_address")
3044 netDict
["use"]=iface
['type']
3045 if netDict
["use"]=="data" and not netDict
.get("type"):
3046 #print "netDict", netDict
3047 #print "iface", iface
3048 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'])
3049 if flavor_dict
.get('extended')==None:
3050 raise NfvoException(e_text
+ "After database migration some information is not available. \
3051 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
3053 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
3054 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
3055 netDict
["type"]="virtual"
3056 if "vpci" in iface
and iface
["vpci"] is not None:
3057 netDict
['vpci'] = iface
['vpci']
3058 if "mac" in iface
and iface
["mac"] is not None:
3059 netDict
['mac_address'] = iface
['mac']
3060 if "port-security" in iface
and iface
["port-security"] is not None:
3061 netDict
['port_security'] = iface
['port-security']
3062 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
3063 netDict
['floating_ip'] = iface
['floating-ip']
3064 netDict
['name'] = iface
['internal_name']
3065 if iface
['net_id'] is None:
3066 for vnf_iface
in sce_vnf
["interfaces"]:
3069 if vnf_iface
['interface_id']==iface
['uuid']:
3070 netDict
['net_id'] = "TASK-{}".format(net2task_id
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
])
3071 instance_net_id
= sce_net2instance
[ vnf_iface
['sce_net_id'] ][datacenter_id
]
3072 task_depends_on
.append(net2task_id
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
])
3075 netDict
['net_id'] = "TASK-{}".format(net2task_id
[ sce_vnf
['uuid'] ][ iface
['net_id'] ])
3076 instance_net_id
= vnf_net2instance
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
3077 task_depends_on
.append(net2task_id
[sce_vnf
['uuid'] ][ iface
['net_id']])
3078 # skip bridge ifaces not connected to any net
3079 if 'net_id' not in netDict
or netDict
['net_id']==None:
3081 myVMDict
['networks'].append(netDict
)
3084 # 'instance_vm_id': instance_vm_uuid,
3085 "instance_net_id": instance_net_id
,
3086 'interface_id': iface
['uuid'],
3087 # 'vim_interface_id': ,
3088 'type': 'external' if iface
['external_name'] is not None else 'internal',
3089 'ip_address': iface
.get('ip_address'),
3090 'floating_ip': int(iface
.get('floating-ip', False)),
3091 'port_security': int(iface
.get('port-security', True))
3093 db_vm_ifaces
.append(db_vm_iface
)
3094 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3095 # print myVMDict['name']
3096 # print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
3097 # print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
3098 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3099 if vm
.get("boot_data"):
3100 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config
)
3102 cloud_config_vm
= cloud_config
3103 if myVMDict
.get('availability_zone'):
3104 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
3107 for vm_index
in range(0, vm
.get('count', 1)):
3109 if vm
.get('count', 1) > 1:
3110 vm_index_name
+= "." + chr(97 + vm_index
)
3111 task_params
= (myVMDict
['name']+vm_index_name
, myVMDict
['description'], myVMDict
.get('start', None),
3112 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'], cloud_config_vm
,
3113 myVMDict
['disks'], av_index
, vnf_availability_zones
)
3114 # put interface uuid back to scenario[vnfs][vms[[interfaces]
3115 for net
in myVMDict
['networks']:
3117 for iface
in vm
['interfaces']:
3118 if net
["name"]==iface
["internal_name"]:
3119 iface
["vim_id"]=net
["vim_id"]
3121 vm_uuid
= str(uuid4())
3122 uuid_list
.append(vm_uuid
)
3125 'instance_vnf_id': vnf_uuid
,
3126 #TODO delete "vim_vm_id": vm_id,
3127 "vm_id": vm
["uuid"],
3130 db_instance_vms
.append(db_vm
)
3133 for db_vm_iface
in db_vm_ifaces
:
3134 iface_uuid
= str(uuid4())
3135 uuid_list
.append(iface_uuid
)
3136 db_vm_iface_instance
= {
3138 "instance_vm_id": vm_uuid
3140 db_vm_iface_instance
.update(db_vm_iface
)
3141 if db_vm_iface_instance
.get("ip_address"): # increment ip_address
3142 ip
= db_vm_iface_instance
.get("ip_address")
3147 ip
= ip
[i
:] + str(int(ip
[:i
]) +1)
3148 db_vm_iface_instance
["ip_address"] = ip
3150 db_vm_iface_instance
["ip_address"] = None
3151 db_instance_interfaces
.append(db_vm_iface_instance
)
3152 myVMDict
['networks'][iface_index
]["uuid"] = iface_uuid
3156 "instance_action_id": instance_action_id
,
3157 "task_index": task_index
,
3158 "datacenter_vim_id": myvim_thread_id
,
3160 "status": "SCHEDULED",
3161 "item": "instance_vms",
3163 "extra": yaml
.safe_dump({"params": task_params
, "depends_on": task_depends_on
},
3164 default_flow_style
=True, width
=256)
3167 db_vim_actions
.append(db_vim_action
)
3169 scenarioDict
["datacenter2tenant"] = myvim_threads_id
3171 db_instance_action
["number_tasks"] = task_index
3172 db_instance_scenario
['datacenter_tenant_id'] = myvim_threads_id
[default_datacenter_id
]
3173 db_instance_scenario
['datacenter_id'] = default_datacenter_id
3175 {"instance_scenarios": db_instance_scenario
},
3176 {"instance_vnfs": db_instance_vnfs
},
3177 {"instance_nets": db_instance_nets
},
3178 {"ip_profiles": db_ip_profiles
},
3179 {"instance_vms": db_instance_vms
},
3180 {"instance_interfaces": db_instance_interfaces
},
3181 {"instance_actions": db_instance_action
},
3182 {"vim_actions": db_vim_actions
}
3185 logger
.debug("create_instance done DB tables: %s",
3186 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
3187 mydb
.new_rows(db_tables
, uuid_list
)
3188 for myvim_thread_id
in list(myvim_threads_id
.values()):
3189 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
3191 returned_instance
= mydb
.get_instance_scenario(instance_uuid
)
3192 returned_instance
["action_id"] = instance_action_id
3193 return returned_instance
3194 except (NfvoException
, vimconn
.vimconnException
, db_base_Exception
) as e
:
3195 message
= rollback(mydb
, myvims
, rollbackList
)
3196 if isinstance(e
, db_base_Exception
):
3197 error_text
= "database Exception"
3198 elif isinstance(e
, vimconn
.vimconnException
):
3199 error_text
= "VIM Exception"
3201 error_text
= "Exception"
3202 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
3203 # logger.error("create_instance: %s", error_text)
3204 raise NfvoException(error_text
, e
.http_code
)
3207 def delete_instance(mydb
, tenant_id
, instance_id
):
3208 # print "Checking that the instance_id exists and getting the instance dictionary"
3209 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
3210 # print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
3211 tenant_id
= instanceDict
["tenant_id"]
3212 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
3214 # 1. Delete from Database
3215 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
3217 # 2. delete from VIM
3221 vimthread_affected
= {}
3224 instance_action_id
= get_task_id()
3226 db_instance_action
= {
3227 "uuid": instance_action_id
, # same uuid for the instance and the action on create
3228 "tenant_id": tenant_id
,
3229 "instance_id": instance_id
,
3230 "description": "DELETE",
3231 # "number_tasks": 0 # filled bellow
3236 for sce_vnf
in instanceDict
['vnfs']:
3237 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
3238 vimthread_affected
[sce_vnf
["datacenter_tenant_id"]] = None
3239 if datacenter_key
not in myvims
:
3241 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
3242 except NfvoException
as e
:
3243 logger
.error(str(e
))
3245 myvim_threads
[datacenter_key
] = myvim_thread
3246 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
3247 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
3249 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
3250 sce_vnf
["datacenter_tenant_id"]))
3251 myvims
[datacenter_key
] = None
3253 myvims
[datacenter_key
] = list(vims
.values())[0]
3254 myvim
= myvims
[datacenter_key
]
3255 myvim_thread
= myvim_threads
[datacenter_key
]
3256 for vm
in sce_vnf
['vms']:
3258 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
3262 "instance_action_id": instance_action_id
,
3263 "task_index": task_index
,
3264 "datacenter_vim_id": sce_vnf
["datacenter_tenant_id"],
3266 "status": "SCHEDULED",
3267 "item": "instance_vms",
3268 "item_id": vm
["uuid"],
3269 "extra": yaml
.safe_dump({"params": vm
["interfaces"]},
3270 default_flow_style
=True, width
=256)
3273 db_vim_actions
.append(db_vim_action
)
3275 except vimconn
.vimconnNotFoundException
as e
:
3276 error_msg
+="\n VM VIM_id={} not found at datacenter={}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
3277 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
3278 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
3279 except vimconn
.vimconnException
as e
:
3280 error_msg
+="\n VM VIM_id={} at datacenter={} Error: {} {}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"], e
.http_code
, str(e
))
3281 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s",
3282 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
3286 for net
in instanceDict
['nets']:
3287 # TODO if not net['created']:
3288 # TODO continue #skip not created nets
3290 vimthread_affected
[net
["datacenter_tenant_id"]] = None
3291 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
3292 if datacenter_key
not in myvims
:
3294 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
3295 except NfvoException
as e
:
3296 logger
.error(str(e
))
3298 myvim_threads
[datacenter_key
] = myvim_thread
3299 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
3300 datacenter_tenant_id
=net
["datacenter_tenant_id"])
3302 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
3303 myvims
[datacenter_key
] = None
3305 myvims
[datacenter_key
] = list(vims
.values())[0]
3306 myvim
= myvims
[datacenter_key
]
3307 myvim_thread
= myvim_threads
[datacenter_key
]
3310 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
3314 "instance_action_id": instance_action_id
,
3315 "task_index": task_index
,
3316 "datacenter_vim_id": net
["datacenter_tenant_id"],
3318 "status": "SCHEDULED",
3319 "item": "instance_nets",
3320 "item_id": net
["uuid"],
3321 "extra": yaml
.safe_dump({"params": (net
['vim_net_id'], net
['sdn_net_id'])},
3322 default_flow_style
=True, width
=256)
3325 db_vim_actions
.append(db_vim_action
)
3327 except vimconn
.vimconnNotFoundException
as e
:
3328 error_msg
+= "\n NET VIM_id={} not found at datacenter={}".format(net
['vim_net_id'], net
["datacenter_id"])
3329 logger
.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found",
3330 net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']))
3331 except vimconn
.vimconnException
as e
:
3332 error_msg
+= "\n NET VIM_id={} at datacenter={} Error: {} {}".format(net
['vim_net_id'],
3333 net
["datacenter_id"],
3334 e
.http_code
, str(e
))
3335 logger
.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s",
3336 e
.http_code
, net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']), str(e
))
3338 db_instance_action
["number_tasks"] = task_index
3340 {"instance_actions": db_instance_action
},
3341 {"vim_actions": db_vim_actions
}
3344 logger
.debug("delete_instance done DB tables: %s",
3345 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
3346 mydb
.new_rows(db_tables
, ())
3347 for myvim_thread_id
in list(vimthread_affected
.keys()):
3348 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
3350 if len(error_msg
) > 0:
3351 return 'action_id={} instance {} deleted but some elements could not be deleted, or already deleted '\
3352 '(error: 404) from VIM: {}'.format(instance_action_id
, message
, error_msg
)
3354 return "action_id={} instance {} deleted".format(instance_action_id
, message
)
3357 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
3358 '''Refreshes a scenario instance. It modifies instanceDict'''
3360 - 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
3363 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
3364 # #print "nfvo.refresh_instance begins"
3365 # #print json.dumps(instanceDict, indent=4)
3367 # #print "Getting the VIM URL and the VIM tenant_id"
3370 # # 1. Getting VIM vm and net list
3371 # vms_updated = [] #List of VM instance uuids in openmano that were updated
3374 # for sce_vnf in instanceDict['vnfs']:
3375 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
3376 # if datacenter_key not in vm_list:
3377 # vm_list[datacenter_key] = []
3378 # if datacenter_key not in myvims:
3379 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
3380 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
3381 # if len(vims) == 0:
3382 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
3383 # myvims[datacenter_key] = None
3385 # myvims[datacenter_key] = vims.values()[0]
3386 # for vm in sce_vnf['vms']:
3387 # vm_list[datacenter_key].append(vm['vim_vm_id'])
3388 # vms_notupdated.append(vm["uuid"])
3390 # nets_updated = [] #List of VM instance uuids in openmano that were updated
3391 # nets_notupdated=[]
3393 # for net in instanceDict['nets']:
3394 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
3395 # if datacenter_key not in net_list:
3396 # net_list[datacenter_key] = []
3397 # if datacenter_key not in myvims:
3398 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
3399 # datacenter_tenant_id=net["datacenter_tenant_id"])
3400 # if len(vims) == 0:
3401 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
3402 # myvims[datacenter_key] = None
3404 # myvims[datacenter_key] = vims.values()[0]
3406 # net_list[datacenter_key].append(net['vim_net_id'])
3407 # nets_notupdated.append(net["uuid"])
3409 # # 1. Getting the status of all VMs
3411 # for datacenter_key in myvims:
3412 # if not vm_list.get(datacenter_key):
3416 # if not myvims[datacenter_key]:
3417 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
3420 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
3422 # except vimconn.vimconnException as e:
3423 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
3424 # failed_message = str(e)
3426 # for vm in vm_list[datacenter_key]:
3427 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
3429 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
3430 # for sce_vnf in instanceDict['vnfs']:
3431 # for vm in sce_vnf['vms']:
3432 # vm_id = vm['vim_vm_id']
3433 # interfaces = vm_dict[vm_id].pop('interfaces', [])
3434 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
3435 # has_mgmt_iface = False
3436 # for iface in vm["interfaces"]:
3437 # if iface["type"]=="mgmt":
3438 # has_mgmt_iface = True
3439 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
3440 # vm_dict[vm_id]['status'] = "ACTIVE"
3441 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
3442 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
3443 # 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'):
3444 # vm['status'] = vm_dict[vm_id]['status']
3445 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
3446 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
3447 # # 2.1. Update in openmano DB the VMs whose status changed
3449 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
3450 # vms_notupdated.remove(vm["uuid"])
3452 # vms_updated.append(vm["uuid"])
3453 # except db_base_Exception as e:
3454 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
3455 # # 2.2. Update in openmano DB the interface VMs
3456 # for interface in interfaces:
3457 # #translate from vim_net_id to instance_net_id
3458 # network_id_list=[]
3459 # for net in instanceDict['nets']:
3460 # if net["vim_net_id"] == interface["vim_net_id"]:
3461 # network_id_list.append(net["uuid"])
3462 # if not network_id_list:
3464 # del interface["vim_net_id"]
3466 # for network_id in network_id_list:
3467 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
3468 # except db_base_Exception as e:
3469 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
3471 # # 3. Getting the status of all nets
3473 # for datacenter_key in myvims:
3474 # if not net_list.get(datacenter_key):
3477 # failed_message = ""
3478 # if not myvims[datacenter_key]:
3479 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
3482 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
3484 # except vimconn.vimconnException as e:
3485 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
3486 # failed_message = str(e)
3488 # for net in net_list[datacenter_key]:
3489 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
3491 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
3492 # # TODO: update nets inside a vnf
3493 # for net in instanceDict['nets']:
3494 # net_id = net['vim_net_id']
3495 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
3496 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
3497 # 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'):
3498 # net['status'] = net_dict[net_id]['status']
3499 # net['error_msg'] = net_dict[net_id].get('error_msg')
3500 # net['vim_info'] = net_dict[net_id].get('vim_info')
3501 # # 5.1. Update in openmano DB the nets whose status changed
3503 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
3504 # nets_notupdated.remove(net["uuid"])
3506 # nets_updated.append(net["uuid"])
3507 # except db_base_Exception as e:
3508 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
3510 # # Returns appropriate output
3511 # #print "nfvo.refresh_instance finishes"
3512 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
3513 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
3514 instance_id
= instanceDict
['uuid']
3515 # if len(vms_notupdated)+len(nets_notupdated)>0:
3516 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
3517 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
3519 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
3521 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
3522 #print "Checking that the instance_id exists and getting the instance dictionary"
3523 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
3524 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
3526 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
3527 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
3529 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
3530 myvim
= list(vims
.values())[0]
3532 if action_dict
.get("create-vdu"):
3533 for vdu
in action_dict
["create-vdu"]:
3534 vdu_id
= vdu
.get("vdu-id")
3535 vdu_count
= vdu
.get("count", 1)
3536 # get from database TODO
3540 input_vnfs
= action_dict
.pop("vnfs", [])
3541 input_vms
= action_dict
.pop("vms", [])
3542 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
3546 for sce_vnf
in instanceDict
['vnfs']:
3547 for vm
in sce_vnf
['vms']:
3548 if not action_over_all
:
3549 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
3550 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
3553 if "add_public_key" in action_dict
:
3555 if sce_vnf
.get('mgmt_access'):
3556 mgmt_access
= yaml
.load(sce_vnf
['mgmt_access'])
3557 ssh_access
= mgmt_access
['config-access']['ssh-access']
3558 tenant
= mydb
.get_rows_by_id('nfvo_tenants', nfvo_tenant
)
3560 if ssh_access
['required'] and ssh_access
['default-user']:
3561 if 'ip_address' in vm
:
3562 mgmt_ip
= vm
['ip_address'].split(';')
3563 password
= mgmt_access
['config-access'].get('password')
3564 priv_RO_key
= decrypt_key(tenant
[0]['encrypted_RO_priv_key'], tenant
[0]['uuid'])
3565 myvim
.inject_user_key(mgmt_ip
[0], ssh_access
['default-user'],
3566 action_dict
['add_public_key'],
3567 password
=password
, ro_key
=priv_RO_key
)
3569 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
3570 HTTP_Internal_Server_Error
)
3572 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
3573 HTTP_Internal_Server_Error
)
3575 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
3576 HTTP_Internal_Server_Error
)
3578 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
3579 if "console" in action_dict
:
3580 if not global_config
["http_console_proxy"]:
3581 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
3582 "description": "{protocol}//{ip}:{port}/{suffix}".format(
3583 protocol
=data
["protocol"],
3584 ip
= data
["server"],
3585 port
= data
["port"],
3586 suffix
= data
["suffix"]),
3590 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
3591 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
3592 "description": "this console is only reachable by local interface",
3597 #print "console data", data
3599 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
3600 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
3601 "description": "{protocol}//{ip}:{port}/{suffix}".format(
3602 protocol
=data
["protocol"],
3603 ip
= global_config
["http_console_host"],
3604 port
= console_thread
.port
,
3605 suffix
= data
["suffix"]),
3609 except NfvoException
as e
:
3610 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
3614 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
3616 except vimconn
.vimconnException
as e
:
3617 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
3620 if vm_ok
==0: #all goes wrong
3625 def instance_action_get(mydb
, nfvo_tenant
, instance_id
, action_id
):
3627 if nfvo_tenant
and nfvo_tenant
!= "any":
3628 filter["tenant_id"] = nfvo_tenant
3629 if instance_id
and instance_id
!= "any":
3630 filter["instance_id"] = instance_id
3632 filter["uuid"] = action_id
3633 rows
= mydb
.get_rows(FROM
="instance_actions", WHERE
=filter)
3634 if not rows
and action_id
:
3635 raise NfvoException("Not found any action with this criteria", HTTP_Not_Found
)
3636 return {"ations": rows
}
3639 def create_or_use_console_proxy_thread(console_server
, console_port
):
3640 #look for a non-used port
3641 console_thread_key
= console_server
+ ":" + str(console_port
)
3642 if console_thread_key
in global_config
["console_thread"]:
3643 #global_config["console_thread"][console_thread_key].start_timeout()
3644 return global_config
["console_thread"][console_thread_key
]
3646 for port
in global_config
["console_port_iterator"]():
3647 #print "create_or_use_console_proxy_thread() port:", port
3648 if port
in global_config
["console_ports"]:
3651 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
3653 global_config
["console_thread"][console_thread_key
] = clithread
3654 global_config
["console_ports"][port
] = console_thread_key
3656 except cli
.ConsoleProxyExceptionPortUsed
as e
:
3657 #port used, try with onoher
3659 except cli
.ConsoleProxyException
as e
:
3660 raise NfvoException(str(e
), HTTP_Bad_Request
)
3661 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
3664 def check_tenant(mydb
, tenant_id
):
3665 '''check that tenant exists at database'''
3666 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
3668 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
3671 def new_tenant(mydb
, tenant_dict
):
3673 tenant_uuid
= str(uuid4())
3674 tenant_dict
['uuid'] = tenant_uuid
3676 pub_key
, priv_key
= create_RO_keypair(tenant_uuid
)
3677 tenant_dict
['RO_pub_key'] = pub_key
3678 tenant_dict
['encrypted_RO_priv_key'] = priv_key
3679 mydb
.new_row("nfvo_tenants", tenant_dict
, confidential_data
=True)
3680 except db_base_Exception
as e
:
3681 raise NfvoException("Error creating the new tenant: {} ".format(tenant_dict
['name']) + str(e
), HTTP_Internal_Server_Error
)
3684 def delete_tenant(mydb
, tenant
):
3685 #get nfvo_tenant info
3687 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
3688 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
3689 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
3692 def new_datacenter(mydb
, datacenter_descriptor
):
3693 if "config" in datacenter_descriptor
:
3694 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
3695 #Check that datacenter-type is correct
3696 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
3699 module
= "vimconn_" + datacenter_type
3700 pkg
= __import__("osm_ro." + module
)
3701 vim_conn
= getattr(pkg
, module
)
3702 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
3703 except (IOError, ImportError):
3704 # if module_info and module_info[0]:
3705 # file.close(module_info[0])
3706 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
3708 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True, confidential_data
=True)
3709 return datacenter_id
3712 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
3713 # obtain data, check that only one exist
3714 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
3717 datacenter_id
= datacenter
['uuid']
3718 where
={'uuid': datacenter
['uuid']}
3719 remove_port_mapping
= False
3720 if "config" in datacenter_descriptor
:
3721 if datacenter_descriptor
['config'] != None:
3723 new_config_dict
= datacenter_descriptor
["config"]
3726 for k
in new_config_dict
:
3727 if new_config_dict
[k
] == None:
3729 if k
== 'sdn-controller':
3730 remove_port_mapping
= True
3732 config_text
= datacenter
.get("config")
3735 config_dict
= yaml
.load(config_text
)
3736 config_dict
.update(new_config_dict
)
3740 except Exception as e
:
3741 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
3743 datacenter_descriptor
["config"] = yaml
.safe_dump(config_dict
, default_flow_style
=True, width
=256)
3745 datacenter_descriptor
["config"] = None
3746 if remove_port_mapping
:
3748 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_id
)
3749 except ovimException
as e
:
3750 logger
.error("Error deleting datacenter-port-mapping " + str(e
))
3752 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
3753 return datacenter_id
3756 def delete_datacenter(mydb
, datacenter
):
3757 #get nfvo_tenant info
3758 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
3759 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
3761 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_dict
['uuid'])
3762 except ovimException
as e
:
3763 logger
.error("Error deleting datacenter-port-mapping " + str(e
))
3764 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
3767 def associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter
, vim_tenant_id
=None, vim_tenant_name
=None, vim_username
=None, vim_password
=None, config
=None):
3768 # get datacenter info
3770 datacenter_id
= get_datacenter_uuid(mydb
, None, datacenter
)
3772 create_vim_tenant
= True if not vim_tenant_id
and not vim_tenant_name
else False
3774 # get nfvo_tenant info
3775 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
3776 if vim_tenant_name
==None:
3777 vim_tenant_name
=tenant_dict
['name']
3779 #check that this association does not exist before
3780 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
3781 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
3782 if len(tenants_datacenters
)>0:
3783 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
3785 vim_tenant_id_exist_atdb
=False
3786 if not create_vim_tenant
:
3787 where_
={"datacenter_id": datacenter_id
}
3788 if vim_tenant_id
!=None:
3789 where_
["vim_tenant_id"] = vim_tenant_id
3790 if vim_tenant_name
!=None:
3791 where_
["vim_tenant_name"] = vim_tenant_name
3792 #check if vim_tenant_id is already at database
3793 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
3794 if len(datacenter_tenants_dict
)>=1:
3795 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
3796 vim_tenant_id_exist_atdb
=True
3797 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
3799 datacenter_tenants_dict
= {}
3800 #insert at table datacenter_tenants
3801 else: #if vim_tenant_id==None:
3802 #create tenant at VIM if not provided
3804 _
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
, vim_user
=vim_username
,
3805 vim_passwd
=vim_password
)
3806 datacenter_name
= myvim
["name"]
3807 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
3808 except vimconn
.vimconnException
as e
:
3809 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
3810 datacenter_tenants_dict
= {}
3811 datacenter_tenants_dict
["created"]="true"
3813 #fill datacenter_tenants table
3814 if not vim_tenant_id_exist_atdb
:
3815 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
3816 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
3817 datacenter_tenants_dict
["user"] = vim_username
3818 datacenter_tenants_dict
["passwd"] = vim_password
3819 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
3821 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
3822 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True, confidential_data
=True)
3823 datacenter_tenants_dict
["uuid"] = id_
3825 #fill tenants_datacenters table
3826 datacenter_tenant_id
= datacenter_tenants_dict
["uuid"]
3827 tenants_datacenter_dict
["datacenter_tenant_id"] = datacenter_tenant_id
3828 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
3830 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_dict
['uuid'], datacenter_id
) # reload data
3831 datacenter_name
= myvim
["name"]
3832 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
3833 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, datacenter_name
, datacenter_tenant_id
,
3834 db
=db
, db_lock
=db_lock
, ovim
=ovim
)
3836 thread_id
= datacenter_tenants_dict
["uuid"]
3837 vim_threads
["running"][thread_id
] = new_thread
3838 return datacenter_id
3839 except vimconn
.vimconnException
as e
:
3840 raise NfvoException(str(e
), HTTP_Bad_Request
)
3843 def edit_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=None, vim_tenant_name
=None,
3844 vim_username
=None, vim_password
=None, config
=None):
3845 #Obtain the data of this datacenter_tenant_id
3846 vim_data
= mydb
.get_rows(
3847 SELECT
=("datacenter_tenants.vim_tenant_name", "datacenter_tenants.vim_tenant_id", "datacenter_tenants.user",
3848 "datacenter_tenants.passwd", "datacenter_tenants.config"),
3849 FROM
="datacenter_tenants JOIN tenants_datacenters ON datacenter_tenants.uuid=tenants_datacenters.datacenter_tenant_id",
3850 WHERE
={"tenants_datacenters.nfvo_tenant_id": nfvo_tenant
,
3851 "tenants_datacenters.datacenter_id": datacenter_id
})
3853 logger
.debug(str(vim_data
))
3854 if len(vim_data
) < 1:
3855 raise NfvoException("Datacenter {} is not attached for tenant {}".format(datacenter_id
, nfvo_tenant
), HTTP_Conflict
)
3859 v
['config'] = yaml
.load(v
['config'])
3862 v
['vim_tenant_id'] = vim_tenant_id
3864 v
['vim_tenant_name'] = vim_tenant_name
3866 v
['user'] = vim_username
3868 v
['passwd'] = vim_password
3872 v
['config'].update(config
)
3874 logger
.debug(str(v
))
3875 deassociate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'])
3876 associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'], vim_tenant_name
=v
['vim_tenant_name'],
3877 vim_username
=v
['user'], vim_password
=v
['passwd'], config
=v
['config'])
3879 return datacenter_id
3881 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
3882 #get nfvo_tenant info
3883 if not tenant_id
or tenant_id
=="any":
3886 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
3887 tenant_uuid
= tenant_dict
['uuid']
3889 datacenter_id
= get_datacenter_uuid(mydb
, tenant_uuid
, datacenter
)
3890 #check that this association exist before
3891 tenants_datacenter_dict
={"datacenter_id": datacenter_id
}
3893 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
3894 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
3895 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
3896 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
3898 #delete this association
3899 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
3901 #get vim_tenant info and deletes
3903 for tenant_datacenter_item
in tenant_datacenter_list
:
3904 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
3905 #try to delete vim:tenant
3907 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
3908 if vim_tenant_dict
['created']=='true':
3909 #delete tenant at VIM if created by NFVO
3911 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3912 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
3913 except vimconn
.vimconnException
as e
:
3914 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
3915 logger
.warn(warning
)
3916 except db_base_Exception
as e
:
3917 logger
.error("Cannot delete datacenter_tenants " + str(e
))
3918 pass # the error will be caused because dependencies, vim_tenant can not be deleted
3919 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
3920 thread
= vim_threads
["running"][thread_id
]
3921 thread
.insert_task("exit")
3922 vim_threads
["deleting"][thread_id
] = thread
3923 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
3926 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
3928 #get datacenter info
3929 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3931 if 'net-update' in action_dict
:
3933 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
3935 except vimconn
.vimconnException
as e
:
3936 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
3937 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
3938 #update nets Change from VIM format to NFVO format
3941 net_nfvo
={'datacenter_id': datacenter_id
}
3942 net_nfvo
['name'] = net
['name']
3943 #net_nfvo['description']= net['name']
3944 net_nfvo
['vim_net_id'] = net
['id']
3945 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
3946 net_nfvo
['shared'] = net
['shared']
3947 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
3948 net_list
.append(net_nfvo
)
3949 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
3950 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
3952 elif 'net-edit' in action_dict
:
3953 net
= action_dict
['net-edit'].pop('net')
3954 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
3955 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
3956 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
3958 elif 'net-delete' in action_dict
:
3959 net
= action_dict
['net-deelte'].get('net')
3960 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
3961 result
= mydb
.delete_row(FROM
='datacenter_nets',
3962 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
3966 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
3969 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
3970 #get datacenter info
3971 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3973 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
3974 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
3975 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
3979 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
3980 #get datacenter info
3981 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3984 action_dict
= action_dict
["netmap"]
3985 if 'vim_id' in action_dict
:
3986 filter_dict
["id"] = action_dict
['vim_id']
3987 if 'vim_name' in action_dict
:
3988 filter_dict
["name"] = action_dict
['vim_name']
3990 filter_dict
["shared"] = True
3993 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
3994 except vimconn
.vimconnException
as e
:
3995 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
3996 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
3997 if len(vim_nets
)>1 and action_dict
:
3998 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
3999 elif len(vim_nets
)==0: # and action_dict:
4000 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
4002 for net
in vim_nets
:
4003 net_nfvo
={'datacenter_id': datacenter_id
}
4004 if action_dict
and "name" in action_dict
:
4005 net_nfvo
['name'] = action_dict
['name']
4007 net_nfvo
['name'] = net
['name']
4008 #net_nfvo['description']= net['name']
4009 net_nfvo
['vim_net_id'] = net
['id']
4010 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
4011 net_nfvo
['shared'] = net
['shared']
4012 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
4014 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
4015 net_nfvo
["status"] = "OK"
4016 net_nfvo
["uuid"] = net_id
4017 except db_base_Exception
as e
:
4021 net_nfvo
["status"] = "FAIL: " + str(e
)
4022 net_list
.append(net_nfvo
)
4025 def get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
):
4026 # obtain all network data
4028 if utils
.check_valid_uuid(network_id
):
4029 filter_dict
= {"id": network_id
}
4031 filter_dict
= {"name": network_id
}
4033 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4034 network
= myvim
.get_network_list(filter_dict
=filter_dict
)
4035 except vimconn
.vimconnException
as e
:
4036 raise NfvoException("Not possible to get_sdn_net_id from VIM: {}".format(str(e
)), e
.http_code
)
4038 # ensure the network is defined
4039 if len(network
) == 0:
4040 raise NfvoException("Network {} is not present in the system".format(network_id
),
4043 # ensure there is only one network with the provided name
4044 if len(network
) > 1:
4045 raise NfvoException("Multiple networks present in vim identified by {}".format(network_id
), HTTP_Bad_Request
)
4047 # ensure it is a dataplane network
4048 if network
[0]['type'] != 'data':
4051 # ensure we use the id
4052 network_id
= network
[0]['id']
4054 # search in dabase mano_db in table instance nets for the sdn_net_id that corresponds to the vim_net_id==network_id
4055 # and with instance_scenario_id==NULL
4056 #search_dict = {'vim_net_id': network_id, 'instance_scenario_id': None}
4057 search_dict
= {'vim_net_id': network_id
}
4060 #sdn_network_id = mydb.get_rows(SELECT=('sdn_net_id',), FROM='instance_nets', WHERE=search_dict)[0]['sdn_net_id']
4061 result
= mydb
.get_rows(SELECT
=('sdn_net_id',), FROM
='instance_nets', WHERE
=search_dict
)
4062 except db_base_Exception
as e
:
4063 raise NfvoException("db_base_Exception obtaining SDN network to associated to vim network {}".format(
4064 network_id
) + str(e
), HTTP_Internal_Server_Error
)
4068 if net
['sdn_net_id'] != None:
4070 sdn_net_id
= net
['sdn_net_id']
4072 if sdn_net_counter
== 0:
4074 elif sdn_net_counter
== 1:
4077 raise NfvoException("More than one SDN network is associated to vim network {}".format(
4078 network_id
), HTTP_Internal_Server_Error
)
4080 def get_sdn_controller_id(mydb
, datacenter
):
4081 # Obtain sdn controller id
4082 config
= mydb
.get_rows(SELECT
=('config',), FROM
='datacenters', WHERE
={'uuid': datacenter
})[0].get('config', '{}')
4086 return yaml
.load(config
).get('sdn-controller')
4088 def vim_net_sdn_attach(mydb
, tenant_id
, datacenter
, network_id
, descriptor
):
4090 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
4091 if not sdn_network_id
:
4092 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
), HTTP_Internal_Server_Error
)
4094 #Obtain sdn controller id
4095 controller_id
= get_sdn_controller_id(mydb
, datacenter
)
4096 if not controller_id
:
4097 raise NfvoException("No SDN controller is set for datacenter {}".format(datacenter
), HTTP_Internal_Server_Error
)
4099 #Obtain sdn controller info
4100 sdn_controller
= ovim
.show_of_controller(controller_id
)
4103 'name': 'external_port',
4104 'net_id': sdn_network_id
,
4105 'ofc_id': controller_id
,
4106 'switch_dpid': sdn_controller
['dpid'],
4107 'switch_port': descriptor
['port']
4110 if 'vlan' in descriptor
:
4111 port_data
['vlan'] = descriptor
['vlan']
4112 if 'mac' in descriptor
:
4113 port_data
['mac'] = descriptor
['mac']
4115 result
= ovim
.new_port(port_data
)
4116 except ovimException
as e
:
4117 raise NfvoException("ovimException attaching SDN network {} to vim network {}".format(
4118 sdn_network_id
, network_id
) + str(e
), HTTP_Internal_Server_Error
)
4119 except db_base_Exception
as e
:
4120 raise NfvoException("db_base_Exception attaching SDN network to vim network {}".format(
4121 network_id
) + str(e
), HTTP_Internal_Server_Error
)
4123 return 'Port uuid: '+ result
4125 def vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, network_id
, port_id
=None):
4127 filter = {'uuid': port_id
}
4129 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
4130 if not sdn_network_id
:
4131 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
),
4132 HTTP_Internal_Server_Error
)
4133 #in case no port_id is specified only ports marked as 'external_port' will be detached
4134 filter = {'name': 'external_port', 'net_id': sdn_network_id
}
4137 port_list
= ovim
.get_ports(columns
={'uuid'}, filter=filter)
4138 except ovimException
as e
:
4139 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
4140 HTTP_Internal_Server_Error
)
4142 if len(port_list
) == 0:
4143 raise NfvoException("No ports attached to the network {} were found with the requested criteria".format(network_id
),
4147 for port
in port_list
:
4149 port_uuid_list
.append(port
['uuid'])
4150 ovim
.delete_port(port
['uuid'])
4151 except ovimException
as e
:
4152 raise NfvoException("ovimException deleting port {} for net {}. ".format(port
['uuid'], network_id
) + str(e
), HTTP_Internal_Server_Error
)
4154 return 'Detached ports uuid: {}'.format(','.join(port_uuid_list
))
4156 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
4157 #get datacenter info
4158 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4161 if utils
.check_valid_uuid(name
):
4162 filter_dict
["id"] = name
4164 filter_dict
["name"] = name
4166 if item
=="networks":
4167 #filter_dict['tenant_id'] = myvim['tenant_id']
4168 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
4170 if len(content
) == 0:
4171 raise NfvoException("Network {} is not present in the system. ".format(name
),
4174 #Update the networks with the attached ports
4176 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, net
['id'])
4177 if sdn_network_id
!= None:
4179 #port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan'}, filter={'name': 'external_port', 'net_id': sdn_network_id})
4180 port_list
= ovim
.get_ports(columns
={'uuid', 'switch_port', 'vlan','name'}, filter={'net_id': sdn_network_id
})
4181 except ovimException
as e
:
4182 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
), HTTP_Internal_Server_Error
)
4183 #Remove field name and if port name is external_port save it as 'type'
4184 for port
in port_list
:
4185 if port
['name'] == 'external_port':
4186 port
['type'] = "External"
4188 net
['sdn_network_id'] = sdn_network_id
4189 net
['sdn_attached_ports'] = port_list
4191 elif item
=="tenants":
4192 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
4193 elif item
== "images":
4195 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
4197 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
4198 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
4199 if name
and len(content
)==1:
4200 return {item
[:-1]: content
[0]}
4201 elif name
and len(content
)==0:
4202 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join([str(x
[0])+": "+str(x
[1]) for x
in iter(filter_dict
.items())]),
4205 return {item
: content
}
4206 except vimconn
.vimconnException
as e
:
4207 print("vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
)))
4208 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
4211 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
4212 #get datacenter info
4213 if tenant_id
== "any":
4216 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4218 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
4219 logger
.debug("vim_action_delete vim response: " + str(content
))
4220 items
= list(content
.values())[0]
4221 if type(items
)==list and len(items
)==0:
4222 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
4223 elif type(items
)==list and len(items
)>1:
4224 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
4225 else: # it is a dict
4226 item_id
= items
["id"]
4227 item_name
= str(items
.get("name"))
4230 if item
=="networks":
4231 # If there is a SDN network associated to the vim-network, proceed to clear the relationship and delete it
4232 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, item_id
)
4233 if sdn_network_id
!= None:
4234 #Delete any port attachment to this network
4236 port_list
= ovim
.get_ports(columns
={'uuid'}, filter={'net_id': sdn_network_id
})
4237 except ovimException
as e
:
4238 raise NfvoException(
4239 "ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
4240 HTTP_Internal_Server_Error
)
4242 # By calling one by one all ports to be detached we ensure that not only the external_ports get detached
4243 for port
in port_list
:
4244 vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, item_id
, port
['uuid'])
4246 #Delete from 'instance_nets' the correspondence between the vim-net-id and the sdn-net-id
4248 mydb
.delete_row(FROM
='instance_nets', WHERE
={'instance_scenario_id': None, 'sdn_net_id': sdn_network_id
, 'vim_net_id': item_id
})
4249 except db_base_Exception
as e
:
4250 raise NfvoException("Error deleting correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
4251 str(e
), HTTP_Internal_Server_Error
)
4253 #Delete the SDN network
4255 ovim
.delete_network(sdn_network_id
)
4256 except ovimException
as e
:
4257 logger
.error("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
), exc_info
=True)
4258 raise NfvoException("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
),
4259 HTTP_Internal_Server_Error
)
4261 content
= myvim
.delete_network(item_id
)
4262 elif item
=="tenants":
4263 content
= myvim
.delete_tenant(item_id
)
4264 elif item
== "images":
4265 content
= myvim
.delete_image(item_id
)
4267 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
4268 except vimconn
.vimconnException
as e
:
4269 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
4270 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
4272 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
4275 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
4276 #get datacenter info
4277 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
4278 if tenant_id
== "any":
4280 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4282 if item
=="networks":
4283 net
= descriptor
["network"]
4284 net_name
= net
.pop("name")
4285 net_type
= net
.pop("type", "bridge")
4286 net_public
= net
.pop("shared", False)
4287 net_ipprofile
= net
.pop("ip_profile", None)
4288 net_vlan
= net
.pop("vlan", None)
4289 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
4291 #If the datacenter has a SDN controller defined and the network is of dataplane type, then create the sdn network
4292 if get_sdn_controller_id(mydb
, datacenter
) != None and (net_type
== 'data' or net_type
== 'ptp'):
4295 sdn_network
['vlan'] = net_vlan
4296 sdn_network
['type'] = net_type
4297 sdn_network
['name'] = net_name
4298 ovim_content
= ovim
.new_network(sdn_network
)
4299 except ovimException
as e
:
4300 self
.logger
.error("ovimException creating SDN network={} ".format(
4301 sdn_network
) + str(e
), exc_info
=True)
4302 raise NfvoException("ovimException creating SDN network={} ".format(sdn_network
) + str(e
),
4303 HTTP_Internal_Server_Error
)
4305 # Save entry in in dabase mano_db in table instance_nets to stablish a dictionary vim_net_id <->sdn_net_id
4306 # use instance_scenario_id=None to distinguish from real instaces of nets
4307 correspondence
= {'instance_scenario_id': None, 'sdn_net_id': ovim_content
, 'vim_net_id': content
}
4308 #obtain datacenter_tenant_id
4309 correspondence
['datacenter_tenant_id'] = mydb
.get_rows(SELECT
=('uuid',), FROM
='datacenter_tenants', WHERE
={'datacenter_id': datacenter
})[0]['uuid']
4312 mydb
.new_row('instance_nets', correspondence
, add_uuid
=True)
4313 except db_base_Exception
as e
:
4314 raise NfvoException("Error saving correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
4315 str(e
), HTTP_Internal_Server_Error
)
4316 elif item
=="tenants":
4317 tenant
= descriptor
["tenant"]
4318 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
4320 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
4321 except vimconn
.vimconnException
as e
:
4322 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
4324 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
4326 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
4327 data
= ovim
.new_of_controller(sdn_controller
)
4328 logger
.debug('New SDN controller created with uuid {}'.format(data
))
4331 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
4332 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
4333 msg
= 'SDN controller {} updated'.format(data
)
4337 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
4338 if controller_id
== None:
4339 data
= ovim
.get_of_controllers()
4341 data
= ovim
.show_of_controller(controller_id
)
4343 msg
= 'SDN controller list:\n {}'.format(data
)
4347 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
4348 select_
= ('uuid', 'config')
4349 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
4350 for datacenter
in datacenters
:
4351 if datacenter
['config']:
4352 config
= yaml
.load(datacenter
['config'])
4353 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
4354 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), HTTP_Conflict
)
4356 data
= ovim
.delete_of_controller(controller_id
)
4357 msg
= 'SDN controller {} deleted'.format(data
)
4361 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
4362 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
4363 if len(controller
) < 1:
4364 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), HTTP_Not_Found
)
4367 sdn_controller_id
= yaml
.load(controller
[0]["config"])["sdn-controller"]
4369 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), HTTP_Bad_Request
)
4371 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
4372 switch_dpid
= sdn_controller
["dpid"]
4375 for compute_node
in sdn_port_mapping
:
4376 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
4378 element
["compute_node"] = compute_node
["compute_node"]
4379 for port
in compute_node
["ports"]:
4380 element
["pci"] = port
.get("pci")
4381 element
["switch_port"] = port
.get("switch_port")
4382 element
["switch_mac"] = port
.get("switch_mac")
4383 if not element
["pci"] or not (element
["switch_port"] or element
["switch_mac"]):
4384 raise NfvoException ("The mapping must contain the 'pci' and at least one of the elements 'switch_port'"
4385 " or 'switch_mac'", HTTP_Bad_Request
)
4386 maps
.append(dict(element
))
4388 return ovim
.set_of_port_mapping(maps
, ofc_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, region
=datacenter_id
)
4390 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
4391 maps
= ovim
.get_of_port_mappings(db_filter
={"region": datacenter_id
})
4394 "sdn-controller": None,
4395 "datacenter-id": datacenter_id
,
4397 "ports_mapping": list()
4400 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
4401 if datacenter
['config']:
4402 config
= yaml
.load(datacenter
['config'])
4403 if 'sdn-controller' in config
:
4404 controller_id
= config
['sdn-controller']
4405 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
4406 result
["sdn-controller"] = controller_id
4407 result
["dpid"] = sdn_controller
["dpid"]
4409 if result
["sdn-controller"] == None:
4410 raise NfvoException("SDN controller is not defined for datacenter {}".format(datacenter_id
), HTTP_Bad_Request
)
4411 if result
["dpid"] == None:
4412 raise NfvoException("It was not possible to determine DPID for SDN controller {}".format(result
["sdn-controller"]),
4413 HTTP_Internal_Server_Error
)
4418 ports_correspondence_dict
= dict()
4420 if result
["sdn-controller"] != link
["ofc_id"]:
4421 raise NfvoException("The sdn-controller specified for different port mappings differ", HTTP_Internal_Server_Error
)
4422 if result
["dpid"] != link
["switch_dpid"]:
4423 raise NfvoException("The dpid specified for different port mappings differ", HTTP_Internal_Server_Error
)
4425 element
["pci"] = link
["pci"]
4426 if link
["switch_port"]:
4427 element
["switch_port"] = link
["switch_port"]
4428 if link
["switch_mac"]:
4429 element
["switch_mac"] = link
["switch_mac"]
4431 if not link
["compute_node"] in ports_correspondence_dict
:
4433 content
["compute_node"] = link
["compute_node"]
4434 content
["ports"] = list()
4435 ports_correspondence_dict
[link
["compute_node"]] = content
4437 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
4439 for key
in sorted(ports_correspondence_dict
):
4440 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
4444 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
4445 return ovim
.clear_of_port_mapping(db_filter
={"region":datacenter_id
})
4447 def create_RO_keypair(tenant_id
):
4449 Creates a public / private keys for a RO tenant and returns their values
4451 tenant_id: ID of the tenant
4453 public_key: Public key for the RO tenant
4454 private_key: Encrypted private key for RO tenant
4458 key
= RSA
.generate(bits
)
4460 public_key
= key
.publickey().exportKey('OpenSSH')
4461 if isinstance(public_key
, ValueError):
4462 raise NfvoException("Unable to create public key: {}".format(public_key
), HTTP_Internal_Server_Error
)
4463 private_key
= key
.exportKey(passphrase
=tenant_id
, pkcs
=8)
4464 except (ValueError, NameError) as e
:
4465 raise NfvoException("Unable to create private key: {}".format(e
), HTTP_Internal_Server_Error
)
4466 return public_key
, private_key
4468 def decrypt_key (key
, tenant_id
):
4470 Decrypts an encrypted RSA key
4472 key: Private key to be decrypted
4473 tenant_id: ID of the tenant
4475 unencrypted_key: Unencrypted private key for RO tenant
4478 key
= RSA
.importKey(key
,tenant_id
)
4479 unencrypted_key
= key
.exportKey('PEM')
4480 if isinstance(unencrypted_key
, ValueError):
4481 raise NfvoException("Unable to decrypt the private key: {}".format(unencrypted_key
), HTTP_Internal_Server_Error
)
4482 except ValueError as e
:
4483 raise NfvoException("Unable to decrypt the private key: {}".format(e
), HTTP_Internal_Server_Error
)
4484 return unencrypted_key