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$"
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 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 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
.iteritems():
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 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
.itervalues():
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").itervalues():
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").itervalues():
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"].itervalues():
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'].itervalues():
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 cp_name2db_interface
= {}
1002 # for iface in chain(vdu.get("internal-interface").itervalues(), vdu.get("external-interface").itervalues()):
1003 for iface
in vdu
.get("interface").itervalues():
1004 iface_uuid
= str(uuid4())
1005 uuid_list
.append(iface_uuid
)
1008 "internal_name": get_str(iface
, "name", 255),
1011 if iface
.get("virtual-interface").get("vpci"):
1012 db_interface
["vpci"] = get_str(iface
.get("virtual-interface"), "vpci", 12)
1014 if iface
.get("virtual-interface").get("bandwidth"):
1015 bps
= int(iface
.get("virtual-interface").get("bandwidth"))
1016 db_interface
["bw"] = bps
/1000
1018 if iface
.get("virtual-interface").get("type") == "OM-MGMT":
1019 db_interface
["type"] = "mgmt"
1020 elif iface
.get("virtual-interface").get("type") in ("VIRTIO", "E1000"):
1021 db_interface
["type"] = "bridge"
1022 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1023 elif iface
.get("virtual-interface").get("type") in ("SR-IOV", "PCI-PASSTHROUGH"):
1024 db_interface
["type"] = "data"
1025 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1027 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vdu[{}]':'interface':'virtual"
1028 "-interface':'type':'{}'. Interface type is not supported".format(
1029 str(vnfd
["id"])[:255], str(vdu
["id"])[:255],
1030 iface
.get("virtual-interface").get("type")),
1033 if iface
.get("external-connection-point-ref"):
1035 cp
= vnfd
.get("connection-point")[iface
.get("external-connection-point-ref")]
1036 db_interface
["external_name"] = get_str(cp
, "name", 255)
1037 cp_name2iface_uuid
[db_interface
["external_name"]] = iface_uuid
1038 cp_name2vm_uuid
[db_interface
["external_name"]] = vm_uuid
1039 cp_name2db_interface
[db_interface
["external_name"]] = db_interface
1040 for cp_descriptor
in vnfd_descriptor
["connection-point"]:
1041 if cp_descriptor
["name"] == db_interface
["external_name"]:
1043 if str(cp_descriptor
.get("port-security-enabled")).lower() == "false":
1044 db_interface
["port_security"] = 0
1045 elif str(cp_descriptor
.get("port-security-enabled")).lower() == "true":
1046 db_interface
["port_security"] = 1
1048 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1049 "'interface[{iface}]':'vnfd-connection-point-ref':'{cp}' is not present"
1050 " at connection-point".format(
1051 vnf
=vnfd
["id"], vdu
=vdu
["id"], iface
=iface
["name"],
1052 cp
=iface
.get("vnfd-connection-point-ref")),
1054 elif iface
.get("internal-connection-point-ref"):
1056 for vld
in vnfd
.get("internal-vld").itervalues():
1057 for cp
in vld
.get("internal-connection-point").itervalues():
1058 if cp
.get("id-ref") == iface
.get("internal-connection-point-ref"):
1059 db_interface
["net_id"] = net_id2uuid
[vld
.get("id")]
1060 for cp_descriptor
in vnfd_descriptor
["connection-point"]:
1061 if cp_descriptor
["name"] == db_interface
["external_name"]:
1063 if str(cp_descriptor
.get("port-security-enabled")).lower() == "false":
1064 db_interface
["port_security"] = 0
1065 elif str(cp_descriptor
.get("port-security-enabled")).lower() == "true":
1066 db_interface
["port_security"] = 1
1069 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1070 "'interface[{iface}]':'vdu-internal-connection-point-ref':'{cp}' is not"
1071 " referenced by any internal-vld".format(
1072 vnf
=vnfd
["id"], vdu
=vdu
["id"], iface
=iface
["name"],
1073 cp
=iface
.get("vdu-internal-connection-point-ref")),
1075 if iface
.get("position") is not None:
1076 db_interface
["created_at"] = int(iface
.get("position")) - 1000
1077 db_interfaces
.append(db_interface
)
1079 # VNF affinity and antiaffinity
1080 for pg
in vnfd
.get("placement-groups").itervalues():
1081 pg_name
= get_str(pg
, "name", 255)
1082 for vdu
in pg
.get("member-vdus").itervalues():
1083 vdu_id
= get_str(vdu
, "member-vdu-ref", 255)
1084 if vdu_id
not in vdu_id2db_table_index
:
1085 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'placement-groups[{pg}]':"
1086 "'member-vdus':'{vdu}'. Reference to a non-existing vdu".format(
1087 vnf
=vnfd
["id"], pg
=pg_name
, vdu
=vdu_id
),
1089 db_vms
[vdu_id2db_table_index
[vdu_id
]]["availability_zone"] = pg_name
1090 # TODO consider the case of isolation and not colocation
1091 # if pg.get("strategy") == "ISOLATION":
1093 # VNF mgmt configuration
1095 if vnfd
["mgmt-interface"].get("vdu-id"):
1096 if vnfd
["mgmt-interface"]["vdu-id"] not in vdu_id2uuid
:
1097 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'vdu-id':"
1098 "'{vdu}'. Reference to a non-existing vdu".format(
1099 vnf
=vnfd
["id"], vdu
=vnfd
["mgmt-interface"]["vdu-id"]),
1101 mgmt_access
["vm_id"] = vdu_id2uuid
[vnfd
["mgmt-interface"]["vdu-id"]]
1102 if vnfd
["mgmt-interface"].get("ip-address"):
1103 mgmt_access
["ip-address"] = str(vnfd
["mgmt-interface"].get("ip-address"))
1104 if vnfd
["mgmt-interface"].get("cp"):
1105 if vnfd
["mgmt-interface"]["cp"] not in cp_name2iface_uuid
:
1106 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'cp':'{cp}'. "
1107 "Reference to a non-existing connection-point".format(
1108 vnf
=vnfd
["id"], cp
=vnfd
["mgmt-interface"]["cp"]),
1110 mgmt_access
["vm_id"] = cp_name2vm_uuid
[vnfd
["mgmt-interface"]["cp"]]
1111 mgmt_access
["interface_id"] = cp_name2iface_uuid
[vnfd
["mgmt-interface"]["cp"]]
1112 # mark this interface as of type mgmt
1113 cp_name2db_interface
[vnfd
["mgmt-interface"]["cp"]]["type"] = "mgmt"
1115 default_user
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1119 mgmt_access
["default_user"] = default_user
1120 required
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1123 mgmt_access
["required"] = required
1126 db_vnf
["mgmt_access"] = yaml
.safe_dump(mgmt_access
, default_flow_style
=True, width
=256)
1130 db_vnfs
.append(db_vnf
)
1134 {"images": db_images
},
1135 {"flavors": db_flavors
},
1137 {"interfaces": db_interfaces
},
1140 logger
.debug("create_vnf Deployment done vnfDict: %s",
1141 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
1142 mydb
.new_rows(db_tables
, uuid_list
)
1143 return vnfd_uuid_list
1144 except NfvoException
:
1146 except Exception as e
:
1147 logger
.error("Exception {}".format(e
))
1148 raise # NfvoException("Exception {}".format(e), HTTP_Bad_Request)
1151 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
1152 global global_config
1154 # Step 1. Check the VNF descriptor
1155 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
1156 # Step 2. Check tenant exist
1158 if tenant_id
!= "any":
1159 check_tenant(mydb
, tenant_id
)
1160 if "tenant_id" in vnf_descriptor
["vnf"]:
1161 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1162 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1165 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1166 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1167 if global_config
["auto_push_VNF_to_VIMs"]:
1168 vims
= get_vim(mydb
, tenant_id
)
1170 # Step 4. Review the descriptor and add missing fields
1171 #print vnf_descriptor
1172 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1173 vnf_name
= vnf_descriptor
['vnf']['name']
1174 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1175 if "physical" in vnf_descriptor
['vnf']:
1176 del vnf_descriptor
['vnf']['physical']
1177 #print vnf_descriptor
1179 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1180 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1181 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1183 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1184 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1185 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1187 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1188 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1190 VNFCitem
["name"] = vnfc
['name']
1191 VNFCitem
["availability_zone"] = vnfc
.get('availability_zone')
1192 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
1194 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1197 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1198 myflavorDict
["description"] = VNFCitem
["description"]
1199 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1200 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1201 myflavorDict
["disk"] = vnfc
.get("disk", 1)
1202 myflavorDict
["extended"] = {}
1204 devices
= vnfc
.get("devices")
1206 myflavorDict
["extended"]["devices"] = devices
1209 # 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
1210 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1212 # Previous code has been commented
1213 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1214 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1215 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1216 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1218 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1220 # print "Error creating flavor: unknown processor model. Rollback successful."
1221 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1223 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1224 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1226 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1227 myflavorDict
['extended']['numas'] = vnfc
['numas']
1231 # Step 6.2 New flavors are created in the VIM
1232 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1234 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1235 VNFCitem
["flavor_id"] = flavor_id
1236 VNFCDict
[vnfc
['name']] = VNFCitem
1238 logger
.debug("Creating new images in the VIM for each VNFC")
1239 # Step 6.3 New images are created in the VIM
1240 #For each VNFC, we must create the appropriate image.
1241 #This "for" loop might be integrated with the previous one
1242 #In case this integration is made, the VNFCDict might become a VNFClist.
1243 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1244 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1246 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1247 image_dict
['universal_name']=vnfc
.get('image name')
1248 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1249 image_dict
['location']=vnfc
.get('VNFC image')
1250 #image_dict['new_location']=vnfc.get('image location')
1251 image_dict
['checksum']=vnfc
.get('image checksum')
1252 image_metadata_dict
= vnfc
.get('image metadata', None)
1253 image_metadata_str
= None
1254 if image_metadata_dict
is not None:
1255 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1256 image_dict
['metadata']=image_metadata_str
1257 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1258 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1259 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1260 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1261 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1262 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1263 if vnfc
.get("boot-data"):
1264 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1267 # Step 7. Storing the VNF descriptor in the repository
1268 if "descriptor" not in vnf_descriptor
["vnf"]:
1269 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1271 # Step 8. Adding the VNF to the NFVO DB
1272 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1274 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1275 _
, message
= rollback(mydb
, vims
, rollback_list
)
1276 if isinstance(e
, db_base_Exception
):
1277 error_text
= "Exception at database"
1278 elif isinstance(e
, KeyError):
1279 error_text
= "KeyError exception "
1280 e
.http_code
= HTTP_Internal_Server_Error
1282 error_text
= "Exception at VIM"
1283 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1284 #logger.error("start_scenario %s", error_text)
1285 raise NfvoException(error_text
, e
.http_code
)
1288 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
1289 global global_config
1291 # Step 1. Check the VNF descriptor
1292 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
1293 # Step 2. Check tenant exist
1295 if tenant_id
!= "any":
1296 check_tenant(mydb
, tenant_id
)
1297 if "tenant_id" in vnf_descriptor
["vnf"]:
1298 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1299 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1302 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1303 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1304 if global_config
["auto_push_VNF_to_VIMs"]:
1305 vims
= get_vim(mydb
, tenant_id
)
1307 # Step 4. Review the descriptor and add missing fields
1308 #print vnf_descriptor
1309 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1310 vnf_name
= vnf_descriptor
['vnf']['name']
1311 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1312 if "physical" in vnf_descriptor
['vnf']:
1313 del vnf_descriptor
['vnf']['physical']
1314 #print vnf_descriptor
1316 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1317 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1318 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1320 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1321 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1322 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1324 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1325 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1327 VNFCitem
["name"] = vnfc
['name']
1328 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
1330 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1333 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1334 myflavorDict
["description"] = VNFCitem
["description"]
1335 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1336 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1337 myflavorDict
["disk"] = vnfc
.get("disk", 1)
1338 myflavorDict
["extended"] = {}
1340 devices
= vnfc
.get("devices")
1342 myflavorDict
["extended"]["devices"] = devices
1345 # 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
1346 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1348 # Previous code has been commented
1349 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1350 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1351 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1352 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1354 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1356 # print "Error creating flavor: unknown processor model. Rollback successful."
1357 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1359 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1360 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1362 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1363 myflavorDict
['extended']['numas'] = vnfc
['numas']
1367 # Step 6.2 New flavors are created in the VIM
1368 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1370 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1371 VNFCitem
["flavor_id"] = flavor_id
1372 VNFCDict
[vnfc
['name']] = VNFCitem
1374 logger
.debug("Creating new images in the VIM for each VNFC")
1375 # Step 6.3 New images are created in the VIM
1376 #For each VNFC, we must create the appropriate image.
1377 #This "for" loop might be integrated with the previous one
1378 #In case this integration is made, the VNFCDict might become a VNFClist.
1379 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1380 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1382 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1383 image_dict
['universal_name']=vnfc
.get('image name')
1384 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1385 image_dict
['location']=vnfc
.get('VNFC image')
1386 #image_dict['new_location']=vnfc.get('image location')
1387 image_dict
['checksum']=vnfc
.get('image checksum')
1388 image_metadata_dict
= vnfc
.get('image metadata', None)
1389 image_metadata_str
= None
1390 if image_metadata_dict
is not None:
1391 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1392 image_dict
['metadata']=image_metadata_str
1393 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1394 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1395 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1396 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1397 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1398 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1399 if vnfc
.get("boot-data"):
1400 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1402 # Step 7. Storing the VNF descriptor in the repository
1403 if "descriptor" not in vnf_descriptor
["vnf"]:
1404 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1406 # Step 8. Adding the VNF to the NFVO DB
1407 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1409 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1410 _
, message
= rollback(mydb
, vims
, rollback_list
)
1411 if isinstance(e
, db_base_Exception
):
1412 error_text
= "Exception at database"
1413 elif isinstance(e
, KeyError):
1414 error_text
= "KeyError exception "
1415 e
.http_code
= HTTP_Internal_Server_Error
1417 error_text
= "Exception at VIM"
1418 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1419 #logger.error("start_scenario %s", error_text)
1420 raise NfvoException(error_text
, e
.http_code
)
1423 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
1424 #check valid tenant_id
1425 check_tenant(mydb
, tenant_id
)
1428 if tenant_id
!= "any":
1429 where_or
["tenant_id"] = tenant_id
1430 where_or
["public"] = True
1431 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1433 vnf_id
= vnf
["uuid"]
1434 filter_keys
= ('uuid', 'name', 'description', 'public', "tenant_id", "osm_id", "created_at")
1435 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
1436 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
1437 data
={'vnf' : filtered_content
}
1439 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
1440 SELECT
=('vms.uuid as uuid', 'vms.osm_id as osm_id', 'vms.name as name', 'vms.description as description',
1442 WHERE
={'vnfs.uuid': vnf_id
} )
1444 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1445 # change boot_data into boot-data
1447 if vm
.get("boot_data"):
1448 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
1451 data
['vnf']['VNFC'] = content
1452 #TODO: GET all the information from a VNFC and include it in the output.
1455 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
1456 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
1457 WHERE
={'vnfs.uuid': vnf_id
} )
1458 data
['vnf']['nets'] = content
1460 #GET ip-profile for each net
1461 for net
in data
['vnf']['nets']:
1462 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1463 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1464 WHERE
={'net_id': net
["uuid"]} )
1465 if len(ipprofiles
)==1:
1466 net
["ip_profile"] = ipprofiles
[0]
1467 elif len(ipprofiles
)>1:
1468 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
1471 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1473 #GET External Interfaces
1474 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1475 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1476 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1477 WHERE
={'vnfs.uuid': vnf_id
},
1478 WHERE_NOT
={'interfaces.external_name': None} )
1480 data
['vnf']['external-connections'] = content
1485 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1486 # Check tenant exist
1487 if tenant_id
!= "any":
1488 check_tenant(mydb
, tenant_id
)
1489 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1490 vims
= get_vim(mydb
, tenant_id
)
1494 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1496 if tenant_id
!= "any":
1497 where_or
["tenant_id"] = tenant_id
1498 where_or
["public"] = True
1499 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1500 vnf_id
= vnf
["uuid"]
1502 # "Getting the list of flavors and tenants of the VNF"
1503 flavorList
= get_flavorlist(mydb
, vnf_id
)
1504 if len(flavorList
)==0:
1505 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1507 imageList
= get_imagelist(mydb
, vnf_id
)
1508 if len(imageList
)==0:
1509 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1511 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1513 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1516 for flavor
in flavorList
:
1517 #check if flavor is used by other vnf
1519 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1521 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1523 #flavor not used, must be deleted
1525 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
1526 for flavor_vim
in c
:
1527 if flavor_vim
["datacenter_vim_id"] not in vims
: # TODO change to datacenter_tenant_id
1529 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
1531 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
1533 myvim
.delete_flavor(flavor_vim
["vim_id"])
1534 except vimconn
.vimconnNotFoundException
as e
:
1535 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
1536 except vimconn
.vimconnException
as e
:
1537 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1538 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1539 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
1540 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1541 mydb
.delete_row_by_id('flavors', flavor
)
1542 except db_base_Exception
as e
:
1543 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1544 undeletedItems
.append("flavor %s" % flavor
)
1547 for image
in imageList
:
1549 #check if image is used by other vnf
1550 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
1552 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1554 #image not used, must be deleted
1556 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1558 if image_vim
["datacenter_vim_id"] not in vims
: # TODO change to datacenter_tenant_id
1560 if image_vim
['created']=='false': #skip this image because not created by openmano
1562 myvim
=vims
[ image_vim
["datacenter_id"] ]
1564 myvim
.delete_image(image_vim
["vim_id"])
1565 except vimconn
.vimconnNotFoundException
as e
:
1566 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1567 except vimconn
.vimconnException
as e
:
1568 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1569 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1570 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1571 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1572 mydb
.delete_row_by_id('images', image
)
1573 except db_base_Exception
as e
:
1574 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1575 undeletedItems
.append("image %s" % image
)
1577 return vnf_id
+ " " + vnf
["name"]
1579 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1582 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1583 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1587 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
1588 myvim
= vims
.values()[0]
1589 result
,servers
= myvim
.get_hosts_info()
1591 return result
, servers
1592 topology
= {'name':myvim
['name'] , 'servers': servers
}
1593 return result
, topology
1596 def get_hosts(mydb
, nfvo_tenant_id
):
1597 vims
= get_vim(mydb
, nfvo_tenant_id
)
1599 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
1601 #print "nfvo.datacenter_action() error. Several datacenters found"
1602 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1603 myvim
= vims
.values()[0]
1605 hosts
= myvim
.get_hosts()
1606 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1608 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1610 server
={'name':host
['name'], 'vms':[]}
1611 for vm
in host
['instances']:
1612 #get internal name and model
1614 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1615 WHERE
={'vim_vm_id':vm
['id']} )
1617 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1619 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1621 except db_base_Exception
as e
:
1622 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1623 datacenter
['Datacenters'][0]['servers'].append(server
)
1624 #return -400, "en construccion"
1626 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1628 except vimconn
.vimconnException
as e
:
1629 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1632 def new_scenario(mydb
, tenant_id
, topo
):
1634 # result, vims = get_vim(mydb, tenant_id)
1636 # return result, vims
1638 if tenant_id
!= "any":
1639 check_tenant(mydb
, tenant_id
)
1640 if "tenant_id" in topo
:
1641 if topo
["tenant_id"] != tenant_id
:
1642 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1647 #1.1: get VNFs and external_networks (other_nets).
1649 other_nets
={} #external_networks, bridge_networks and data_networkds
1650 nodes
= topo
['topology']['nodes']
1651 for k
in nodes
.keys():
1652 if nodes
[k
]['type'] == 'VNF':
1654 vnfs
[k
]['ifaces'] = {}
1655 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1656 other_nets
[k
] = nodes
[k
]
1657 other_nets
[k
]['external']=True
1658 elif nodes
[k
]['type'] == 'network':
1659 other_nets
[k
] = nodes
[k
]
1660 other_nets
[k
]['external']=False
1663 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1664 for name
,vnf
in vnfs
.items():
1666 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1668 error_pos
= "'topology':'nodes':'" + name
+ "'"
1670 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1671 where
['uuid'] = vnf
['vnf_id']
1672 if 'VNF model' in vnf
:
1673 error_text
+= " 'VNF model' " + vnf
['VNF model']
1674 where
['name'] = vnf
['VNF model']
1676 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
1678 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1684 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1686 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1687 vnf
['uuid']=vnf_db
[0]['uuid']
1688 vnf
['description']=vnf_db
[0]['description']
1689 #get external interfaces
1690 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1691 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1692 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1693 for ext_iface
in ext_ifaces
:
1694 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1696 #1.4 get list of connections
1697 conections
= topo
['topology']['connections']
1698 conections_list
= []
1699 conections_list_name
= []
1700 for k
in conections
.keys():
1701 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1702 ifaces_list
= conections
[k
]['nodes'].items()
1703 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1705 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1706 for k2
in conection_pair_list
:
1709 con_type
= conections
[k
].get("type", "link")
1710 if con_type
!= "link":
1712 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
1713 other_nets
[k
] = {'external': False}
1714 if conections
[k
].get("graph"):
1715 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1716 ifaces_list
.append( (k
, None) )
1719 if con_type
== "external_network":
1720 other_nets
[k
]['external'] = True
1721 if conections
[k
].get("model"):
1722 other_nets
[k
]["model"] = conections
[k
]["model"]
1724 other_nets
[k
]["model"] = k
1725 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1726 other_nets
[k
]["model"] = con_type
1728 conections_list_name
.append(k
)
1729 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)
1730 #print set(ifaces_list)
1731 #check valid VNF and iface names
1732 for iface
in ifaces_list
:
1733 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1734 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1735 str(k
), iface
[0]), HTTP_Not_Found
)
1736 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1737 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1738 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
1740 #1.5 unify connections from the pair list to a consolidated list
1742 while index
< len(conections_list
):
1744 while index2
< len(conections_list
):
1745 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1746 conections_list
[index
] |
= conections_list
[index2
]
1747 del conections_list
[index2
]
1748 del conections_list_name
[index2
]
1751 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1753 #for k in conections_list:
1758 #1.6 Delete non external nets
1759 # for k in other_nets.keys():
1760 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1761 # for con in conections_list:
1763 # for index in range(0,len(con)):
1764 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1765 # for index in delete_indexes:
1768 #1.7: Check external_ports are present at database table datacenter_nets
1769 for k
,net
in other_nets
.items():
1770 error_pos
= "'topology':'nodes':'" + k
+ "'"
1771 if net
['external']==False:
1772 if 'name' not in net
:
1774 if 'model' not in net
:
1775 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1776 if net
['model']=='bridge_net':
1777 net
['type']='bridge';
1778 elif net
['model']=='dataplane_net':
1781 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1783 #IF we do not want to check that external network exist at datacenter
1788 # if 'net_id' in net:
1789 # error_text += " 'net_id' " + net['net_id']
1790 # WHERE_['uuid'] = net['net_id']
1791 # if 'model' in net:
1792 # error_text += " 'model' " + net['model']
1793 # WHERE_['name'] = net['model']
1794 # if len(WHERE_) == 0:
1795 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1796 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1797 # FROM='datacenter_nets', WHERE=WHERE_ )
1799 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1801 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1802 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1804 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1805 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1806 # other_nets[k].update(net_db[0])
1809 net_nb
=0 #Number of nets
1810 for con
in conections_list
:
1811 #check if this is connected to a external net
1815 for index
in range(0,len(con
)):
1816 #check if this is connected to a external net
1817 for net_key
in other_nets
.keys():
1818 if con
[index
][0]==net_key
:
1819 if other_net_index
>=0:
1820 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1821 #print "nfvo.new_scenario " + error_text
1822 raise NfvoException(error_text
, HTTP_Bad_Request
)
1824 other_net_index
= index
1825 net_target
= net_key
1827 #print "other_net_index", other_net_index
1829 if other_net_index
>=0:
1830 del con
[other_net_index
]
1831 #IF we do not want to check that external network exist at datacenter
1832 if other_nets
[net_target
]['external'] :
1833 if "name" not in other_nets
[net_target
]:
1834 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1835 if other_nets
[net_target
]["type"] == "external_network":
1836 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1837 other_nets
[net_target
]["type"] = "data"
1839 other_nets
[net_target
]["type"] = "bridge"
1841 # if other_nets[net_target]['external'] :
1842 # 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
1843 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1844 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1845 # print "nfvo.new_scenario " + error_text
1846 # return -HTTP_Bad_Request, error_text
1849 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1852 net_type_bridge
=False
1854 net_target
= "__-__net"+str(net_nb
)
1855 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
1856 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1859 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1860 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1861 if iface_type
=='mgmt' or iface_type
=='bridge':
1862 net_type_bridge
= True
1864 net_type_data
= True
1865 if net_type_bridge
and net_type_data
:
1866 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1867 #print "nfvo.new_scenario " + error_text
1868 raise NfvoException(error_text
, HTTP_Bad_Request
)
1869 elif net_type_bridge
:
1872 type_
='data' if len(con
)>2 else 'ptp'
1873 net_list
[net_target
]['type'] = type_
1876 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1877 #print "nfvo.new_scenario " + error_text
1879 raise NfvoException(error_text
, HTTP_Bad_Request
)
1881 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1882 #1.8.1 obtain management net
1883 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1884 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1885 #1.8.2 check all interfaces from all vnfs
1887 add_mgmt_net
= False
1888 for vnf
in vnfs
.values():
1889 for iface
in vnf
['ifaces'].values():
1890 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1891 #iface not connected
1892 iface
['net_key'] = 'mgmt'
1894 if add_mgmt_net
and 'mgmt' not in net_list
:
1895 net_list
['mgmt']=mgmt_net
[0]
1896 net_list
['mgmt']['external']=True
1897 net_list
['mgmt']['graph']={'visible':False}
1899 net_list
.update(other_nets
)
1901 #print 'net_list', net_list
1906 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1907 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1908 'tenant_id':tenant_id
, 'name':topo
['name'],
1909 'description':topo
.get('description',topo
['name']),
1910 'public': topo
.get('public', False)
1916 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
1917 """ This creates a new scenario for version 0.2 and 0.3"""
1918 scenario
= scenario_dict
["scenario"]
1919 if tenant_id
!= "any":
1920 check_tenant(mydb
, tenant_id
)
1921 if "tenant_id" in scenario
:
1922 if scenario
["tenant_id"] != tenant_id
:
1923 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1924 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1925 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1929 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
1930 for name
,vnf
in scenario
["vnfs"].iteritems():
1932 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1934 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1936 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1937 where
['uuid'] = vnf
['vnf_id']
1938 if 'vnf_name' in vnf
:
1939 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1940 where
['name'] = vnf
['vnf_name']
1942 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1943 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
1948 if len(vnf_db
) == 0:
1949 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1950 elif len(vnf_db
) > 1:
1951 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1952 vnf
['uuid'] = vnf_db
[0]['uuid']
1953 vnf
['description'] = vnf_db
[0]['description']
1955 # get external interfaces
1956 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
1957 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1958 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name': None} )
1959 for ext_iface
in ext_ifaces
:
1960 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
1961 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1963 # 2: Insert net_key and ip_address at every vnf interface
1964 for net_name
, net
in scenario
["networks"].items():
1965 net_type_bridge
= False
1966 net_type_data
= False
1967 for iface_dict
in net
["interfaces"]:
1968 if version
== "0.2":
1969 temp_dict
= iface_dict
1971 elif version
== "0.3":
1972 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
1973 ip_address
= iface_dict
.get('ip_address', None)
1974 for vnf
, iface
in temp_dict
.items():
1975 if vnf
not in scenario
["vnfs"]:
1976 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
1978 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1979 raise NfvoException(error_text
, HTTP_Not_Found
)
1980 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1981 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
1982 .format(net_name
, iface
)
1983 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1984 raise NfvoException(error_text
, HTTP_Bad_Request
)
1985 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1986 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
1987 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1988 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1989 raise NfvoException(error_text
, HTTP_Bad_Request
)
1990 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1991 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
1992 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1993 if iface_type
== 'mgmt' or iface_type
== 'bridge':
1994 net_type_bridge
= True
1996 net_type_data
= True
1998 if net_type_bridge
and net_type_data
:
1999 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
2001 # logger.debug("nfvo.new_scenario " + error_text)
2002 raise NfvoException(error_text
, HTTP_Bad_Request
)
2003 elif net_type_bridge
:
2006 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
2008 if net
.get("implementation"): # for v0.3
2009 if type_
== "bridge" and net
["implementation"] == "underlay":
2010 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
2011 "'network':'{}'".format(net_name
)
2012 # logger.debug(error_text)
2013 raise NfvoException(error_text
, HTTP_Bad_Request
)
2014 elif type_
!= "bridge" and net
["implementation"] == "overlay":
2015 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
2016 "'network':'{}'".format(net_name
)
2017 # logger.debug(error_text)
2018 raise NfvoException(error_text
, HTTP_Bad_Request
)
2019 net
.pop("implementation")
2020 if "type" in net
and version
== "0.3": # for v0.3
2021 if type_
== "data" and net
["type"] == "e-line":
2022 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
2023 "'e-line' at 'network':'{}'".format(net_name
)
2024 # logger.debug(error_text)
2025 raise NfvoException(error_text
, HTTP_Bad_Request
)
2026 elif type_
== "ptp" and net
["type"] == "e-lan":
2030 net
['name'] = net_name
2031 net
['external'] = net
.get('external', False)
2033 # 3: insert at database
2034 scenario
["nets"] = scenario
["networks"]
2035 scenario
['tenant_id'] = tenant_id
2036 scenario_id
= mydb
.new_scenario(scenario
)
2040 def new_nsd_v3(mydb
, tenant_id
, nsd_descriptor
):
2042 Parses an OSM IM nsd_catalog and insert at DB
2045 :param nsd_descriptor:
2046 :return: The list of cretated NSD ids
2049 mynsd
= nsd_catalog
.nsd()
2051 pybindJSONDecoder
.load_ietf_json(nsd_descriptor
, None, None, obj
=mynsd
)
2052 except Exception as e
:
2053 raise NfvoException("Error. Invalid NS descriptor format: " + str(e
), HTTP_Bad_Request
)
2057 db_sce_interfaces
= []
2059 db_ip_profiles_index
= 0
2062 for nsd_yang
in mynsd
.nsd_catalog
.nsd
.itervalues():
2063 nsd
= nsd_yang
.get()
2066 scenario_uuid
= str(uuid4())
2067 uuid_list
.append(scenario_uuid
)
2068 nsd_uuid_list
.append(scenario_uuid
)
2070 "uuid": scenario_uuid
,
2071 "osm_id": get_str(nsd
, "id", 255),
2072 "name": get_str(nsd
, "name", 255),
2073 "description": get_str(nsd
, "description", 255),
2074 "tenant_id": tenant_id
,
2075 "vendor": get_str(nsd
, "vendor", 255),
2076 "short_name": get_str(nsd
, "short-name", 255),
2077 "descriptor": str(nsd_descriptor
)[:60000],
2079 db_scenarios
.append(db_scenario
)
2081 # table sce_vnfs (constituent-vnfd)
2082 vnf_index2scevnf_uuid
= {}
2083 vnf_index2vnf_uuid
= {}
2084 for vnf
in nsd
.get("constituent-vnfd").itervalues():
2085 existing_vnf
= mydb
.get_rows(FROM
="vnfs", WHERE
={'osm_id': str(vnf
["vnfd-id-ref"])[:255],
2086 'tenant_id': tenant_id
})
2087 if not existing_vnf
:
2088 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'constituent-vnfd':'vnfd-id-ref':"
2089 "'{}'. Reference to a non-existing VNFD in the catalog".format(
2090 str(nsd
["id"]), str(vnf
["vnfd-id-ref"])[:255]),
2092 sce_vnf_uuid
= str(uuid4())
2093 uuid_list
.append(sce_vnf_uuid
)
2095 "uuid": sce_vnf_uuid
,
2096 "scenario_id": scenario_uuid
,
2097 "name": existing_vnf
[0]["name"][:200] + "." + get_str(vnf
, "member-vnf-index", 5),
2098 "vnf_id": existing_vnf
[0]["uuid"],
2099 "member_vnf_index": int(vnf
["member-vnf-index"]),
2100 # TODO 'start-by-default': True
2102 vnf_index2scevnf_uuid
[int(vnf
['member-vnf-index'])] = sce_vnf_uuid
2103 vnf_index2vnf_uuid
[int(vnf
['member-vnf-index'])] = existing_vnf
[0]["uuid"]
2104 db_sce_vnfs
.append(db_sce_vnf
)
2106 # table ip_profiles (ip-profiles)
2107 ip_profile_name2db_table_index
= {}
2108 for ip_profile
in nsd
.get("ip-profiles").itervalues():
2110 "ip_version": str(ip_profile
["ip-profile-params"].get("ip-version", "ipv4")),
2111 "subnet_address": str(ip_profile
["ip-profile-params"].get("subnet-address")),
2112 "gateway_address": str(ip_profile
["ip-profile-params"].get("gateway-address")),
2113 "dhcp_enabled": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("enabled", True)),
2114 "dhcp_start_address": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("start-address")),
2115 "dhcp_count": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("count")),
2118 for dns
in ip_profile
["ip-profile-params"]["dns-server"].itervalues():
2119 dns_list
.append(str(dns
.get("address")))
2120 db_ip_profile
["dns_address"] = ";".join(dns_list
)
2121 if ip_profile
["ip-profile-params"].get('security-group'):
2122 db_ip_profile
["security_group"] = ip_profile
["ip-profile-params"]['security-group']
2123 ip_profile_name2db_table_index
[str(ip_profile
["name"])] = db_ip_profiles_index
2124 db_ip_profiles_index
+= 1
2125 db_ip_profiles
.append(db_ip_profile
)
2127 # table sce_nets (internal-vld)
2128 for vld
in nsd
.get("vld").itervalues():
2129 sce_net_uuid
= str(uuid4())
2130 uuid_list
.append(sce_net_uuid
)
2132 "uuid": sce_net_uuid
,
2133 "name": get_str(vld
, "name", 255),
2134 "scenario_id": scenario_uuid
,
2136 "multipoint": not vld
.get("type") == "ELINE",
2138 "description": get_str(vld
, "description", 255),
2140 # guess type of network
2141 if vld
.get("mgmt-network"):
2142 db_sce_net
["type"] = "bridge"
2143 db_sce_net
["external"] = True
2144 elif vld
.get("provider-network").get("overlay-type") == "VLAN":
2145 db_sce_net
["type"] = "data"
2147 db_sce_net
["type"] = "bridge"
2148 db_sce_nets
.append(db_sce_net
)
2150 # ip-profile, link db_ip_profile with db_sce_net
2151 if vld
.get("ip-profile-ref"):
2152 ip_profile_name
= vld
.get("ip-profile-ref")
2153 if ip_profile_name
not in ip_profile_name2db_table_index
:
2154 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'ip-profile-ref':'{}'."
2155 " Reference to a non-existing 'ip_profiles'".format(
2156 str(nsd
["id"]), str(vld
["id"]), str(vld
["ip-profile-ref"])),
2158 db_ip_profiles
[ip_profile_name2db_table_index
[ip_profile_name
]]["sce_net_id"] = sce_net_uuid
2160 # table sce_interfaces (vld:vnfd-connection-point-ref)
2161 for iface
in vld
.get("vnfd-connection-point-ref").itervalues():
2162 vnf_index
= int(iface
['member-vnf-index-ref'])
2163 # check correct parameters
2164 if vnf_index
not in vnf_index2vnf_uuid
:
2165 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2166 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2167 "'nsd':'constituent-vnfd'".format(
2168 str(nsd
["id"]), str(vld
["id"]), str(iface
["member-vnf-index-ref"])),
2171 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2172 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2173 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2174 'external_name': get_str(iface
, "vnfd-connection-point-ref",
2176 if not existing_ifaces
:
2177 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2178 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2179 "connection-point name at VNFD '{}'".format(
2180 str(nsd
["id"]), str(vld
["id"]), str(iface
["vnfd-connection-point-ref"]),
2181 str(iface
.get("vnfd-id-ref"))[:255]),
2183 interface_uuid
= existing_ifaces
[0]["uuid"]
2184 sce_interface_uuid
= str(uuid4())
2185 uuid_list
.append(sce_net_uuid
)
2186 db_sce_interface
= {
2187 "uuid": sce_interface_uuid
,
2188 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2189 "sce_net_id": sce_net_uuid
,
2190 "interface_id": interface_uuid
,
2191 # "ip_address": #TODO
2193 db_sce_interfaces
.append(db_sce_interface
)
2196 {"scenarios": db_scenarios
},
2197 {"sce_nets": db_sce_nets
},
2198 {"ip_profiles": db_ip_profiles
},
2199 {"sce_vnfs": db_sce_vnfs
},
2200 {"sce_interfaces": db_sce_interfaces
},
2203 logger
.debug("create_vnf Deployment done vnfDict: %s",
2204 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
2205 mydb
.new_rows(db_tables
, uuid_list
)
2206 return nsd_uuid_list
2207 except NfvoException
:
2209 except Exception as e
:
2210 logger
.error("Exception {}".format(e
))
2211 raise # NfvoException("Exception {}".format(e), HTTP_Bad_Request)
2214 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
2215 data
["uuid"] = scenario_id
2216 data
["tenant_id"] = tenant_id
2217 c
= mydb
.edit_scenario( data
)
2221 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
2222 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2223 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
2224 vims
= {datacenter_id
: myvim
}
2225 myvim_tenant
= myvim
['tenant_id']
2226 datacenter_name
= myvim
['name']
2230 #print "Checking that the scenario_id exists and getting the scenario dictionary"
2231 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
=datacenter_id
)
2232 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
2233 scenarioDict
['datacenter_id'] = datacenter_id
2234 #print '================scenarioDict======================='
2235 #print json.dumps(scenarioDict, indent=4)
2236 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
2238 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
2239 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2241 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
2242 auxNetDict
['scenario'] = {}
2244 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
2245 for sce_net
in scenarioDict
['nets']:
2246 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
2248 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
2249 myNetName
= myNetName
[0:255] #limit length
2250 myNetType
= sce_net
['type']
2252 myNetDict
["name"] = myNetName
2253 myNetDict
["type"] = myNetType
2254 myNetDict
["tenant_id"] = myvim_tenant
2255 myNetIPProfile
= sce_net
.get('ip_profile', None)
2257 #We should use the dictionary as input parameter for new_network
2259 if not sce_net
["external"]:
2260 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2261 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
2262 sce_net
['vim_id'] = network_id
2263 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
2264 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2265 sce_net
["created"] = True
2267 if sce_net
['vim_id'] == None:
2268 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
2269 _
, message
= rollback(mydb
, vims
, rollbackList
)
2270 logger
.error("nfvo.start_scenario: %s", error_text
)
2271 raise NfvoException(error_text
, HTTP_Bad_Request
)
2272 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
2273 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
2275 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
2276 #For each vnf net, we create it and we add it to instanceNetlist.
2278 for sce_vnf
in scenarioDict
['vnfs']:
2279 for net
in sce_vnf
['nets']:
2280 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
2282 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
2283 myNetName
= myNetName
[0:255] #limit length
2284 myNetType
= net
['type']
2286 myNetDict
["name"] = myNetName
2287 myNetDict
["type"] = myNetType
2288 myNetDict
["tenant_id"] = myvim_tenant
2289 myNetIPProfile
= net
.get('ip_profile', None)
2292 #We should use the dictionary as input parameter for new_network
2293 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2294 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
2295 net
['vim_id'] = network_id
2296 if sce_vnf
['uuid'] not in auxNetDict
:
2297 auxNetDict
[sce_vnf
['uuid']] = {}
2298 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
2299 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2300 net
["created"] = True
2302 #print "auxNetDict:"
2303 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2305 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
2306 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2308 for sce_vnf
in scenarioDict
['vnfs']:
2309 vnf_availability_zones
= []
2310 for vm
in sce_vnf
['vms']:
2311 vm_av
= vm
.get('availability_zone')
2312 if vm_av
and vm_av
not in vnf_availability_zones
:
2313 vnf_availability_zones
.append(vm_av
)
2315 # check if there is enough availability zones available at vim level.
2316 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
2317 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
2318 raise NfvoException('No enough availability zones at VIM for this deployment', HTTP_Bad_Request
)
2320 for vm
in sce_vnf
['vms']:
2323 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
2324 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
2325 #myVMDict['description'] = vm['description']
2326 myVMDict
['description'] = myVMDict
['name'][0:99]
2328 myVMDict
['start'] = "no"
2329 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2330 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
2332 #create image at vim in case it not exist
2333 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2334 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
2335 vm
['vim_image_id'] = image_id
2337 #create flavor at vim in case it not exist
2338 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2339 if flavor_dict
['extended']!=None:
2340 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2341 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
2342 vm
['vim_flavor_id'] = flavor_id
2345 myVMDict
['imageRef'] = vm
['vim_image_id']
2346 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2347 myVMDict
['networks'] = []
2348 for iface
in vm
['interfaces']:
2350 if iface
['type']=="data":
2351 netDict
['type'] = iface
['model']
2352 elif "model" in iface
and iface
["model"]!=None:
2353 netDict
['model']=iface
['model']
2354 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2355 #discover type of interface looking at flavor
2356 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2357 for flavor_iface
in numa
.get('interfaces',[]):
2358 if flavor_iface
.get('name') == iface
['internal_name']:
2359 if flavor_iface
['dedicated'] == 'yes':
2360 netDict
['type']="PF" #passthrough
2361 elif flavor_iface
['dedicated'] == 'no':
2362 netDict
['type']="VF" #siov
2363 elif flavor_iface
['dedicated'] == 'yes:sriov':
2364 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2365 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2367 netDict
["use"]=iface
['type']
2368 if netDict
["use"]=="data" and not netDict
.get("type"):
2369 #print "netDict", netDict
2370 #print "iface", iface
2371 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'])
2372 if flavor_dict
.get('extended')==None:
2373 raise NfvoException(e_text
+ "After database migration some information is not available. \
2374 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
2376 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
2377 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2378 netDict
["type"]="virtual"
2379 if "vpci" in iface
and iface
["vpci"] is not None:
2380 netDict
['vpci'] = iface
['vpci']
2381 if "mac" in iface
and iface
["mac"] is not None:
2382 netDict
['mac_address'] = iface
['mac']
2383 if "port-security" in iface
and iface
["port-security"] is not None:
2384 netDict
['port_security'] = iface
['port-security']
2385 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2386 netDict
['floating_ip'] = iface
['floating-ip']
2387 netDict
['name'] = iface
['internal_name']
2388 if iface
['net_id'] is None:
2389 for vnf_iface
in sce_vnf
["interfaces"]:
2392 if vnf_iface
['interface_id']==iface
['uuid']:
2393 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
2396 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2397 #skip bridge ifaces not connected to any net
2398 #if 'net_id' not in netDict or netDict['net_id']==None:
2400 myVMDict
['networks'].append(netDict
)
2401 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2402 #print myVMDict['name']
2403 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2404 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2405 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2407 if 'availability_zone' in myVMDict
:
2408 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
2412 vm_id
= myvim
.new_vminstance(myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2413 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2414 availability_zone_index
=av_index
,
2415 availability_zone_list
=vnf_availability_zones
)
2416 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
2417 vm
['vim_id'] = vm_id
2418 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2419 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2420 for net
in myVMDict
['networks']:
2422 for iface
in vm
['interfaces']:
2423 if net
["name"]==iface
["internal_name"]:
2424 iface
["vim_id"]=net
["vim_id"]
2427 logger
.debug("start scenario Deployment done")
2428 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2429 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
2430 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
2431 return mydb
.get_instance_scenario(instance_id
)
2433 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
2434 _
, message
= rollback(mydb
, vims
, rollbackList
)
2435 if isinstance(e
, db_base_Exception
):
2436 error_text
= "Exception at database"
2438 error_text
= "Exception at VIM"
2439 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2440 #logger.error("start_scenario %s", error_text)
2441 raise NfvoException(error_text
, e
.http_code
)
2443 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
2444 """ join the cloud config information into cloud_config_preserve.
2445 In case of conflict cloud_config_preserve preserves
2448 if not cloud_config_preserve
and not cloud_config
:
2451 new_cloud_config
= {"key-pairs":[], "users":[]}
2453 if cloud_config_preserve
:
2454 for key
in cloud_config_preserve
.get("key-pairs", () ):
2455 if key
not in new_cloud_config
["key-pairs"]:
2456 new_cloud_config
["key-pairs"].append(key
)
2458 for key
in cloud_config
.get("key-pairs", () ):
2459 if key
not in new_cloud_config
["key-pairs"]:
2460 new_cloud_config
["key-pairs"].append(key
)
2461 if not new_cloud_config
["key-pairs"]:
2462 del new_cloud_config
["key-pairs"]
2466 new_cloud_config
["users"] += cloud_config
.get("users", () )
2467 if cloud_config_preserve
:
2468 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
2469 index_to_delete
= []
2470 users
= new_cloud_config
.get("users", [])
2471 for index0
in range(0,len(users
)):
2472 if index0
in index_to_delete
:
2474 for index1
in range(index0
+1,len(users
)):
2475 if index1
in index_to_delete
:
2477 if users
[index0
]["name"] == users
[index1
]["name"]:
2478 index_to_delete
.append(index1
)
2479 for key
in users
[index1
].get("key-pairs",()):
2480 if "key-pairs" not in users
[index0
]:
2481 users
[index0
]["key-pairs"] = [key
]
2482 elif key
not in users
[index0
]["key-pairs"]:
2483 users
[index0
]["key-pairs"].append(key
)
2484 index_to_delete
.sort(reverse
=True)
2485 for index
in index_to_delete
:
2487 if not new_cloud_config
["users"]:
2488 del new_cloud_config
["users"]
2491 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
2492 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
2493 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
2494 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
2497 new_cloud_config
["user-data"] = []
2498 if cloud_config
and cloud_config
.get("user-data"):
2499 if isinstance(cloud_config
["user-data"], list):
2500 new_cloud_config
["user-data"] += cloud_config
["user-data"]
2502 new_cloud_config
["user-data"].append(cloud_config
["user-data"])
2503 if cloud_config_preserve
and cloud_config_preserve
.get("user-data"):
2504 if isinstance(cloud_config_preserve
["user-data"], list):
2505 new_cloud_config
["user-data"] += cloud_config_preserve
["user-data"]
2507 new_cloud_config
["user-data"].append(cloud_config_preserve
["user-data"])
2508 if not new_cloud_config
["user-data"]:
2509 del new_cloud_config
["user-data"]
2512 new_cloud_config
["config-files"] = []
2513 if cloud_config
and cloud_config
.get("config-files") != None:
2514 new_cloud_config
["config-files"] += cloud_config
["config-files"]
2515 if cloud_config_preserve
:
2516 for file in cloud_config_preserve
.get("config-files", ()):
2517 for index
in range(0, len(new_cloud_config
["config-files"])):
2518 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
2519 new_cloud_config
["config-files"][index
] = file
2522 new_cloud_config
["config-files"].append(file)
2523 if not new_cloud_config
["config-files"]:
2524 del new_cloud_config
["config-files"]
2525 return new_cloud_config
2528 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
2529 datacenter_id
= None
2530 datacenter_name
= None
2533 if datacenter_tenant_id
:
2534 thread_id
= datacenter_tenant_id
2535 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
2537 where_
={"td.nfvo_tenant_id": tenant_id
}
2538 if datacenter_id_name
:
2539 if utils
.check_valid_uuid(datacenter_id_name
):
2540 datacenter_id
= datacenter_id_name
2541 where_
["dt.datacenter_id"] = datacenter_id
2543 datacenter_name
= datacenter_id_name
2544 where_
["d.name"] = datacenter_name
2545 if datacenter_tenant_id
:
2546 where_
["dt.uuid"] = datacenter_tenant_id
2547 datacenters
= mydb
.get_rows(
2548 SELECT
=("dt.uuid as datacenter_tenant_id",),
2549 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
2550 "join datacenters as d on d.uuid=dt.datacenter_id",
2552 if len(datacenters
) > 1:
2553 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2555 thread_id
= datacenters
[0]["datacenter_tenant_id"]
2556 thread
= vim_threads
["running"].get(thread_id
)
2558 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
2559 return thread_id
, thread
2560 except db_base_Exception
as e
:
2561 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
2564 def get_datacenter_uuid(mydb
, tenant_id
, datacenter_id_name
):
2566 if utils
.check_valid_uuid(datacenter_id_name
):
2567 WHERE_dict
['d.uuid'] = datacenter_id_name
2569 WHERE_dict
['d.name'] = datacenter_id_name
2572 WHERE_dict
['nfvo_tenant_id'] = tenant_id
2573 from_
= "tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join datacenter_tenants as" \
2574 " dt on td.datacenter_tenant_id=dt.uuid"
2576 from_
= 'datacenters as d'
2577 vimaccounts
= mydb
.get_rows(FROM
=from_
, SELECT
=("d.uuid as uuid",), WHERE
=WHERE_dict
)
2578 if len(vimaccounts
) == 0:
2579 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
2580 elif len(vimaccounts
)>1:
2581 #print "nfvo.datacenter_action() error. Several datacenters found"
2582 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2583 return vimaccounts
[0]["uuid"]
2586 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
2587 datacenter_id
= None
2588 datacenter_name
= None
2589 if datacenter_id_name
:
2590 if utils
.check_valid_uuid(datacenter_id_name
):
2591 datacenter_id
= datacenter_id_name
2593 datacenter_name
= datacenter_id_name
2594 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
2596 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
2598 #print "nfvo.datacenter_action() error. Several datacenters found"
2599 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2600 return vims
.keys()[0], vims
.values()[0]
2604 '''Takes dict d and updates it with the values in dict u.'''
2605 '''It merges all depth levels'''
2606 for k
, v
in u
.iteritems():
2607 if isinstance(v
, collections
.Mapping
):
2608 r
= update(d
.get(k
, {}), v
)
2614 def create_instance(mydb
, tenant_id
, instance_dict
):
2615 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2616 # logger.debug("Creating instance...")
2617 scenario
= instance_dict
["scenario"]
2619 # find main datacenter
2621 myvim_threads_id
= {}
2622 datacenter
= instance_dict
.get("datacenter")
2623 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2624 myvims
[default_datacenter_id
] = vim
2625 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
2626 tenant
= mydb
.get_rows_by_id('nfvo_tenants', tenant_id
)
2627 # myvim_tenant = myvim['tenant_id']
2631 # print "Checking that the scenario exists and getting the scenario dictionary"
2632 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, datacenter_vim_id
=myvim_threads_id
[default_datacenter_id
],
2633 datacenter_id
=default_datacenter_id
)
2635 # logger.debug(">>>>>> Dictionaries before merging")
2636 # logger.debug(">>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
2637 # logger.debug(">>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
2639 db_instance_vnfs
= []
2640 db_instance_vms
= []
2641 db_instance_interfaces
= []
2646 instance_name
= instance_dict
["name"]
2647 instance_uuid
= str(uuid4())
2648 uuid_list
.append(instance_uuid
)
2649 db_instance_scenario
= {
2650 "uuid": instance_uuid
,
2651 "name": instance_name
,
2652 "tenant_id": tenant_id
,
2653 "scenario_id": scenarioDict
['uuid'],
2654 "datacenter_id": default_datacenter_id
,
2655 # filled bellow 'datacenter_tenant_id'
2656 "description": instance_dict
.get("description"),
2658 if scenarioDict
.get("cloud-config"):
2659 db_instance_scenario
["cloud_config"] = yaml
.safe_dump(scenarioDict
["cloud-config"],
2660 default_flow_style
=True, width
=256)
2661 instance_action_id
= get_task_id()
2662 db_instance_action
= {
2663 "uuid": instance_action_id
, # same uuid for the instance and the action on create
2664 "tenant_id": tenant_id
,
2665 "instance_id": instance_uuid
,
2666 "description": "CREATE",
2669 # Auxiliary dictionaries from x to y
2670 vnf_net2instance
= {}
2671 sce_net2instance
= {}
2672 net2task_id
= {'scenario': {}}
2674 # logger.debug("Creating instance from scenario-dict:\n%s",
2675 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
2677 # 0 check correct parameters
2678 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).iteritems():
2680 for scenario_net
in scenarioDict
['nets']:
2681 if net_name
== scenario_net
["name"]:
2685 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
),
2687 if "sites" not in net_instance_desc
:
2688 net_instance_desc
["sites"] = [ {} ]
2689 site_without_datacenter_field
= False
2690 for site
in net_instance_desc
["sites"]:
2691 if site
.get("datacenter"):
2692 site
["datacenter"] = get_datacenter_uuid(mydb
, tenant_id
, site
["datacenter"])
2693 if site
["datacenter"] not in myvims
:
2694 # Add this datacenter to myvims
2695 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
2697 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
2698 site
["datacenter"] = d
# change name to id
2700 if site_without_datacenter_field
:
2701 raise NfvoException("Found more than one entries without datacenter field at "
2702 "instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
2703 site_without_datacenter_field
= True
2704 site
["datacenter"] = default_datacenter_id
# change name to id
2706 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
2708 for scenario_vnf
in scenarioDict
['vnfs']:
2709 if vnf_name
== scenario_vnf
['name']:
2713 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
2714 if "datacenter" in vnf_instance_desc
:
2715 # Add this datacenter to myvims
2716 vnf_instance_desc
["datacenter"] = get_datacenter_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2717 if vnf_instance_desc
["datacenter"] not in myvims
:
2718 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2720 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2721 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
2723 # 0.1 parse cloud-config parameters
2724 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
2725 # We add the RO key to cloud_config
2726 if tenant
[0].get('RO_pub_key'):
2727 RO_key
= {"key-pairs": [tenant
[0]['RO_pub_key']]}
2728 cloud_config
= unify_cloud_config(cloud_config
, RO_key
)
2730 # 0.2 merge instance information into scenario
2731 # Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
2732 # However, this is not possible yet.
2733 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
2734 for scenario_net
in scenarioDict
['nets']:
2735 if net_name
== scenario_net
["name"]:
2736 if 'ip-profile' in net_instance_desc
:
2737 # translate from input format to database format
2738 ipprofile_in
= net_instance_desc
['ip-profile']
2740 ipprofile_db
['subnet_address'] = ipprofile_in
.get('subnet-address')
2741 ipprofile_db
['ip_version'] = ipprofile_in
.get('ip-version', 'IPv4')
2742 ipprofile_db
['gateway_address'] = ipprofile_in
.get('gateway-address')
2743 ipprofile_db
['dns_address'] = ipprofile_in
.get('dns-address')
2744 if isinstance(ipprofile_db
['dns_address'], (list, tuple)):
2745 ipprofile_db
['dns_address'] = ";".join(ipprofile_db
['dns_address'])
2746 if 'dhcp' in ipprofile_in
:
2747 ipprofile_db
['dhcp_start_address'] = ipprofile_in
['dhcp'].get('start-address')
2748 ipprofile_db
['dhcp_enabled'] = ipprofile_in
['dhcp'].get('enabled', True)
2749 ipprofile_db
['dhcp_count'] = ipprofile_in
['dhcp'].get('count' )
2750 if 'ip_profile' not in scenario_net
:
2751 scenario_net
['ip_profile'] = ipprofile_db
2753 update(scenario_net
['ip_profile'], ipprofile_db
)
2754 for interface
in net_instance_desc
.get('interfaces', () ):
2755 if 'ip_address' in interface
:
2756 for vnf
in scenarioDict
['vnfs']:
2757 if interface
['vnf'] == vnf
['name']:
2758 for vnf_interface
in vnf
['interfaces']:
2759 if interface
['vnf_interface'] == vnf_interface
['external_name']:
2760 vnf_interface
['ip_address']=interface
['ip_address']
2762 # logger.debug(">>>>>>>> Merged dictionary")
2763 # logger.debug("Creating instance scenario-dict MERGED:\n%s",
2764 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
2766 # 1. Creating new nets (sce_nets) in the VIM"
2767 db_instance_nets
= []
2768 for sce_net
in scenarioDict
['nets']:
2769 descriptor_net
= instance_dict
.get("networks", {}).get(sce_net
["name"], {})
2770 net_name
= descriptor_net
.get("vim-network-name")
2771 sce_net2instance
[sce_net
['uuid']] = {}
2772 net2task_id
['scenario'][sce_net
['uuid']] = {}
2774 sites
= descriptor_net
.get("sites", [ {} ])
2776 if site
.get("datacenter"):
2777 vim
= myvims
[ site
["datacenter"] ]
2778 datacenter_id
= site
["datacenter"]
2779 myvim_thread_id
= myvim_threads_id
[ site
["datacenter"] ]
2781 vim
= myvims
[ default_datacenter_id
]
2782 datacenter_id
= default_datacenter_id
2783 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2784 net_type
= sce_net
['type']
2785 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} # 'shared': True
2788 if sce_net
["external"]:
2789 net_name
= sce_net
["name"]
2791 net_name
= "{}.{}".format(instance_name
, sce_net
["name"])
2792 net_name
= net_name
[:255] # limit length
2794 if "netmap-use" in site
or "netmap-create" in site
:
2795 create_network
= False
2796 lookfor_network
= False
2797 if "netmap-use" in site
:
2798 lookfor_network
= True
2799 if utils
.check_valid_uuid(site
["netmap-use"]):
2800 filter_text
= "scenario id '%s'" % site
["netmap-use"]
2801 lookfor_filter
["id"] = site
["netmap-use"]
2803 filter_text
= "scenario name '%s'" % site
["netmap-use"]
2804 lookfor_filter
["name"] = site
["netmap-use"]
2805 if "netmap-create" in site
:
2806 create_network
= True
2807 net_vim_name
= net_name
2808 if site
["netmap-create"]:
2809 net_vim_name
= site
["netmap-create"]
2810 elif sce_net
["external"]:
2811 if sce_net
['vim_id'] != None:
2812 # there is a netmap at datacenter_nets database # TODO REVISE!!!!
2813 create_network
= False
2814 lookfor_network
= True
2815 lookfor_filter
["id"] = sce_net
['vim_id']
2816 filter_text
= "vim_id '{}' datacenter_netmap name '{}'. Try to reload vims with "\
2817 "datacenter-net-update".format(sce_net
['vim_id'], sce_net
["name"])
2818 # look for network at datacenter and return error
2820 # There is not a netmap, look at datacenter for a net with this name and create if not found
2821 create_network
= True
2822 lookfor_network
= True
2823 lookfor_filter
["name"] = sce_net
["name"]
2824 net_vim_name
= sce_net
["name"]
2825 filter_text
= "scenario name '%s'" % sce_net
["name"]
2827 net_vim_name
= net_name
2828 create_network
= True
2829 lookfor_network
= False
2833 task_action
= "CREATE"
2834 task_extra
["params"] = (net_vim_name
, net_type
, sce_net
.get('ip_profile', None))
2836 task_extra
["find"] = (lookfor_filter
,)
2837 elif lookfor_network
:
2838 task_action
= "FIND"
2839 task_extra
["params"] = (lookfor_filter
,)
2841 # fill database content
2842 net_uuid
= str(uuid4())
2843 uuid_list
.append(net_uuid
)
2844 sce_net2instance
[sce_net
['uuid']][datacenter_id
] = net_uuid
2848 "instance_scenario_id": instance_uuid
,
2849 "sce_net_id": sce_net
["uuid"],
2850 "created": create_network
,
2851 'datacenter_id': datacenter_id
,
2852 'datacenter_tenant_id': myvim_thread_id
,
2853 'status': 'BUILD' if create_network
else "ACTIVE"
2855 db_instance_nets
.append(db_net
)
2857 "instance_action_id": instance_action_id
,
2858 "status": "SCHEDULED",
2859 "task_index": task_index
,
2860 "datacenter_vim_id": myvim_thread_id
,
2861 "action": task_action
,
2862 "item": "instance_nets",
2863 "item_id": net_uuid
,
2864 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
2866 net2task_id
['scenario'][sce_net
['uuid']][datacenter_id
] = task_index
2868 db_vim_actions
.append(db_vim_action
)
2870 if 'ip_profile' in sce_net
:
2872 'instance_net_id': net_uuid
,
2873 'ip_version': sce_net
['ip_profile']['ip_version'],
2874 'subnet_address': sce_net
['ip_profile']['subnet_address'],
2875 'gateway_address': sce_net
['ip_profile']['gateway_address'],
2876 'dns_address': sce_net
['ip_profile']['dns_address'],
2877 'dhcp_enabled': sce_net
['ip_profile']['dhcp_enabled'],
2878 'dhcp_start_address': sce_net
['ip_profile']['dhcp_start_address'],
2879 'dhcp_count': sce_net
['ip_profile']['dhcp_count'],
2881 db_ip_profiles
.append(db_ip_profile
)
2883 # 2. Creating new nets (vnf internal nets) in the VIM"
2884 # For each vnf net, we create it and we add it to instanceNetlist.
2885 for sce_vnf
in scenarioDict
['vnfs']:
2886 for net
in sce_vnf
['nets']:
2887 if sce_vnf
.get("datacenter"):
2888 datacenter_id
= sce_vnf
["datacenter"]
2889 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
2891 datacenter_id
= default_datacenter_id
2892 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2893 descriptor_net
= instance_dict
.get("vnfs", {}).get(sce_vnf
["name"], {})
2894 net_name
= descriptor_net
.get("name")
2896 net_name
= "{}.{}".format(instance_name
, net
["name"])
2897 net_name
= net_name
[:255] # limit length
2898 net_type
= net
['type']
2900 if sce_vnf
['uuid'] not in vnf_net2instance
:
2901 vnf_net2instance
[sce_vnf
['uuid']] = {}
2902 if sce_vnf
['uuid'] not in net2task_id
:
2903 net2task_id
[sce_vnf
['uuid']] = {}
2904 net2task_id
[sce_vnf
['uuid']][net
['uuid']] = task_index
2906 # fill database content
2907 net_uuid
= str(uuid4())
2908 uuid_list
.append(net_uuid
)
2909 vnf_net2instance
[sce_vnf
['uuid']][net
['uuid']] = net_uuid
2913 "instance_scenario_id": instance_uuid
,
2914 "net_id": net
["uuid"],
2916 'datacenter_id': datacenter_id
,
2917 'datacenter_tenant_id': myvim_thread_id
,
2919 db_instance_nets
.append(db_net
)
2922 "instance_action_id": instance_action_id
,
2923 "task_index": task_index
,
2924 "datacenter_vim_id": myvim_thread_id
,
2925 "status": "SCHEDULED",
2927 "item": "instance_nets",
2928 "item_id": net_uuid
,
2929 "extra": yaml
.safe_dump({"params": (net_name
, net_type
, net
.get('ip_profile',None))},
2930 default_flow_style
=True, width
=256)
2933 db_vim_actions
.append(db_vim_action
)
2935 if 'ip_profile' in net
:
2937 'instance_net_id': net_uuid
,
2938 'ip_version': net
['ip_profile']['ip_version'],
2939 'subnet_address': net
['ip_profile']['subnet_address'],
2940 'gateway_address': net
['ip_profile']['gateway_address'],
2941 'dns_address': net
['ip_profile']['dns_address'],
2942 'dhcp_enabled': net
['ip_profile']['dhcp_enabled'],
2943 'dhcp_start_address': net
['ip_profile']['dhcp_start_address'],
2944 'dhcp_count': net
['ip_profile']['dhcp_count'],
2946 db_ip_profiles
.append(db_ip_profile
)
2948 # print "vnf_net2instance:"
2949 # print yaml.safe_dump(vnf_net2instance, indent=4, default_flow_style=False)
2951 # 3. Creating new vm instances in the VIM
2952 # myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2953 sce_vnf_list
= sorted(scenarioDict
['vnfs'], key
=lambda k
: k
['name'])
2954 for sce_vnf
in sce_vnf_list
:
2955 vnf_availability_zones
= []
2956 for vm
in sce_vnf
['vms']:
2957 vm_av
= vm
.get('availability_zone')
2958 if vm_av
and vm_av
not in vnf_availability_zones
:
2959 vnf_availability_zones
.append(vm_av
)
2961 # check if there is enough availability zones available at vim level.
2962 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
2963 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
2964 raise NfvoException('No enough availability zones at VIM for this deployment', HTTP_Bad_Request
)
2966 if sce_vnf
.get("datacenter"):
2967 vim
= myvims
[ sce_vnf
["datacenter"] ]
2968 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"] ]
2969 datacenter_id
= sce_vnf
["datacenter"]
2971 vim
= myvims
[ default_datacenter_id
]
2972 myvim_thread_id
= myvim_threads_id
[ default_datacenter_id
]
2973 datacenter_id
= default_datacenter_id
2974 sce_vnf
["datacenter_id"] = datacenter_id
2977 vnf_uuid
= str(uuid4())
2978 uuid_list
.append(vnf_uuid
)
2981 'instance_scenario_id': instance_uuid
,
2982 'vnf_id': sce_vnf
['vnf_id'],
2983 'sce_vnf_id': sce_vnf
['uuid'],
2984 'datacenter_id': datacenter_id
,
2985 'datacenter_tenant_id': myvim_thread_id
,
2987 db_instance_vnfs
.append(db_instance_vnf
)
2989 for vm
in sce_vnf
['vms']:
2991 myVMDict
['name'] = "{}.{}.{}".format(instance_name
[:64], sce_vnf
['name'][:64], vm
["name"][:64])
2992 myVMDict
['description'] = myVMDict
['name'][0:99]
2994 # myVMDict['start'] = "no"
2995 myVMDict
['name'] = myVMDict
['name'][0:255] # limit name length
2996 #create image at vim in case it not exist
2997 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2998 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
2999 vm
['vim_image_id'] = image_id
3001 # create flavor at vim in case it not exist
3002 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
3003 if flavor_dict
['extended']!=None:
3004 flavor_dict
['extended'] = yaml
.load(flavor_dict
['extended'])
3005 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
3007 # Obtain information for additional disks
3008 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',), WHERE
={'vim_id': flavor_id
})
3009 if not extended_flavor_dict
:
3010 raise NfvoException("flavor '{}' not found".format(flavor_id
), HTTP_Not_Found
)
3013 # extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
3014 myVMDict
['disks'] = None
3015 extended_info
= extended_flavor_dict
[0]['extended']
3016 if extended_info
!= None:
3017 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
3018 if 'disks' in extended_flavor_dict_yaml
:
3019 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
3021 vm
['vim_flavor_id'] = flavor_id
3022 myVMDict
['imageRef'] = vm
['vim_image_id']
3023 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
3024 myVMDict
['availability_zone'] = vm
.get('availability_zone')
3025 myVMDict
['networks'] = []
3026 task_depends_on
= []
3027 # TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
3029 for iface
in vm
['interfaces']:
3031 if iface
['type']=="data":
3032 netDict
['type'] = iface
['model']
3033 elif "model" in iface
and iface
["model"]!=None:
3034 netDict
['model']=iface
['model']
3035 # TODO in future, remove this because mac_address will not be set, and the type of PV,VF
3036 # is obtained from iterface table model
3037 # discover type of interface looking at flavor
3038 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
3039 for flavor_iface
in numa
.get('interfaces',[]):
3040 if flavor_iface
.get('name') == iface
['internal_name']:
3041 if flavor_iface
['dedicated'] == 'yes':
3042 netDict
['type']="PF" #passthrough
3043 elif flavor_iface
['dedicated'] == 'no':
3044 netDict
['type']="VF" #siov
3045 elif flavor_iface
['dedicated'] == 'yes:sriov':
3046 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
3047 netDict
["mac_address"] = flavor_iface
.get("mac_address")
3049 netDict
["use"]=iface
['type']
3050 if netDict
["use"]=="data" and not netDict
.get("type"):
3051 #print "netDict", netDict
3052 #print "iface", iface
3053 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'])
3054 if flavor_dict
.get('extended')==None:
3055 raise NfvoException(e_text
+ "After database migration some information is not available. \
3056 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
3058 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
3059 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
3060 netDict
["type"]="virtual"
3061 if "vpci" in iface
and iface
["vpci"] is not None:
3062 netDict
['vpci'] = iface
['vpci']
3063 if "mac" in iface
and iface
["mac"] is not None:
3064 netDict
['mac_address'] = iface
['mac']
3065 if "port-security" in iface
and iface
["port-security"] is not None:
3066 netDict
['port_security'] = iface
['port-security']
3067 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
3068 netDict
['floating_ip'] = iface
['floating-ip']
3069 netDict
['name'] = iface
['internal_name']
3070 if iface
['net_id'] is None:
3071 for vnf_iface
in sce_vnf
["interfaces"]:
3074 if vnf_iface
['interface_id']==iface
['uuid']:
3075 netDict
['net_id'] = "TASK-{}".format(net2task_id
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
])
3076 instance_net_id
= sce_net2instance
[ vnf_iface
['sce_net_id'] ][datacenter_id
]
3077 task_depends_on
.append(net2task_id
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
])
3080 netDict
['net_id'] = "TASK-{}".format(net2task_id
[ sce_vnf
['uuid'] ][ iface
['net_id'] ])
3081 instance_net_id
= vnf_net2instance
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
3082 task_depends_on
.append(net2task_id
[sce_vnf
['uuid'] ][ iface
['net_id']])
3083 # skip bridge ifaces not connected to any net
3084 if 'net_id' not in netDict
or netDict
['net_id']==None:
3086 myVMDict
['networks'].append(netDict
)
3089 # 'instance_vm_id': instance_vm_uuid,
3090 "instance_net_id": instance_net_id
,
3091 'interface_id': iface
['uuid'],
3092 # 'vim_interface_id': ,
3093 'type': 'external' if iface
['external_name'] is not None else 'internal',
3094 'ip_address': iface
.get('ip_address'),
3095 'floating_ip': int(iface
.get('floating-ip', False)),
3096 'port_security': int(iface
.get('port-security', True))
3098 db_vm_ifaces
.append(db_vm_iface
)
3099 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3100 # print myVMDict['name']
3101 # print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
3102 # print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
3103 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3104 if vm
.get("boot_data"):
3105 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config
)
3107 cloud_config_vm
= cloud_config
3108 if myVMDict
.get('availability_zone'):
3109 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
3112 for vm_index
in range(0, vm
.get('count', 1)):
3114 if vm
.get('count', 1) > 1:
3115 vm_index_name
+= "." + chr(97 + vm_index
)
3116 task_params
= (myVMDict
['name']+vm_index_name
, myVMDict
['description'], myVMDict
.get('start', None),
3117 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'], cloud_config_vm
,
3118 myVMDict
['disks'], av_index
, vnf_availability_zones
)
3119 # put interface uuid back to scenario[vnfs][vms[[interfaces]
3120 for net
in myVMDict
['networks']:
3122 for iface
in vm
['interfaces']:
3123 if net
["name"]==iface
["internal_name"]:
3124 iface
["vim_id"]=net
["vim_id"]
3126 vm_uuid
= str(uuid4())
3127 uuid_list
.append(vm_uuid
)
3130 'instance_vnf_id': vnf_uuid
,
3131 #TODO delete "vim_vm_id": vm_id,
3132 "vm_id": vm
["uuid"],
3135 db_instance_vms
.append(db_vm
)
3138 for db_vm_iface
in db_vm_ifaces
:
3139 iface_uuid
= str(uuid4())
3140 uuid_list
.append(iface_uuid
)
3141 db_vm_iface_instance
= {
3143 "instance_vm_id": vm_uuid
3145 db_vm_iface_instance
.update(db_vm_iface
)
3146 if db_vm_iface_instance
.get("ip_address"): # increment ip_address
3147 ip
= db_vm_iface_instance
.get("ip_address")
3152 ip
= ip
[i
:] + str(int(ip
[:i
]) +1)
3153 db_vm_iface_instance
["ip_address"] = ip
3155 db_vm_iface_instance
["ip_address"] = None
3156 db_instance_interfaces
.append(db_vm_iface_instance
)
3157 myVMDict
['networks'][iface_index
]["uuid"] = iface_uuid
3161 "instance_action_id": instance_action_id
,
3162 "task_index": task_index
,
3163 "datacenter_vim_id": myvim_thread_id
,
3165 "status": "SCHEDULED",
3166 "item": "instance_vms",
3168 "extra": yaml
.safe_dump({"params": task_params
, "depends_on": task_depends_on
},
3169 default_flow_style
=True, width
=256)
3172 db_vim_actions
.append(db_vim_action
)
3174 scenarioDict
["datacenter2tenant"] = myvim_threads_id
3176 db_instance_action
["number_tasks"] = task_index
3177 db_instance_scenario
['datacenter_tenant_id'] = myvim_threads_id
[default_datacenter_id
]
3178 db_instance_scenario
['datacenter_id'] = default_datacenter_id
3180 {"instance_scenarios": db_instance_scenario
},
3181 {"instance_vnfs": db_instance_vnfs
},
3182 {"instance_nets": db_instance_nets
},
3183 {"ip_profiles": db_ip_profiles
},
3184 {"instance_vms": db_instance_vms
},
3185 {"instance_interfaces": db_instance_interfaces
},
3186 {"instance_actions": db_instance_action
},
3187 {"vim_actions": db_vim_actions
}
3190 logger
.debug("create_instance done DB tables: %s",
3191 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
3192 mydb
.new_rows(db_tables
, uuid_list
)
3193 for myvim_thread_id
in myvim_threads_id
.values():
3194 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
3196 returned_instance
= mydb
.get_instance_scenario(instance_uuid
)
3197 returned_instance
["action_id"] = instance_action_id
3198 return returned_instance
3199 except (NfvoException
, vimconn
.vimconnException
, db_base_Exception
) as e
:
3200 message
= rollback(mydb
, myvims
, rollbackList
)
3201 if isinstance(e
, db_base_Exception
):
3202 error_text
= "database Exception"
3203 elif isinstance(e
, vimconn
.vimconnException
):
3204 error_text
= "VIM Exception"
3206 error_text
= "Exception"
3207 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
3208 # logger.error("create_instance: %s", error_text)
3209 raise NfvoException(error_text
, e
.http_code
)
3212 def delete_instance(mydb
, tenant_id
, instance_id
):
3213 # print "Checking that the instance_id exists and getting the instance dictionary"
3214 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
3215 # print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
3216 tenant_id
= instanceDict
["tenant_id"]
3217 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
3219 # 1. Delete from Database
3220 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
3222 # 2. delete from VIM
3226 vimthread_affected
= {}
3229 instance_action_id
= get_task_id()
3231 db_instance_action
= {
3232 "uuid": instance_action_id
, # same uuid for the instance and the action on create
3233 "tenant_id": tenant_id
,
3234 "instance_id": instance_id
,
3235 "description": "DELETE",
3236 # "number_tasks": 0 # filled bellow
3241 for sce_vnf
in instanceDict
['vnfs']:
3242 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
3243 vimthread_affected
[sce_vnf
["datacenter_tenant_id"]] = None
3244 if datacenter_key
not in myvims
:
3246 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
3247 except NfvoException
as e
:
3248 logger
.error(str(e
))
3250 myvim_threads
[datacenter_key
] = myvim_thread
3251 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
3252 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
3254 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
3255 sce_vnf
["datacenter_tenant_id"]))
3256 myvims
[datacenter_key
] = None
3258 myvims
[datacenter_key
] = vims
.values()[0]
3259 myvim
= myvims
[datacenter_key
]
3260 myvim_thread
= myvim_threads
[datacenter_key
]
3261 for vm
in sce_vnf
['vms']:
3263 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
3267 "instance_action_id": instance_action_id
,
3268 "task_index": task_index
,
3269 "datacenter_vim_id": sce_vnf
["datacenter_tenant_id"],
3271 "status": "SCHEDULED",
3272 "item": "instance_vms",
3273 "item_id": vm
["uuid"],
3274 "extra": yaml
.safe_dump({"params": vm
["interfaces"]},
3275 default_flow_style
=True, width
=256)
3278 db_vim_actions
.append(db_vim_action
)
3280 except vimconn
.vimconnNotFoundException
as e
:
3281 error_msg
+="\n VM VIM_id={} not found at datacenter={}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
3282 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
3283 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
3284 except vimconn
.vimconnException
as e
:
3285 error_msg
+="\n VM VIM_id={} at datacenter={} Error: {} {}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"], e
.http_code
, str(e
))
3286 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s",
3287 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
3291 for net
in instanceDict
['nets']:
3292 # TODO if not net['created']:
3293 # TODO continue #skip not created nets
3295 vimthread_affected
[net
["datacenter_tenant_id"]] = None
3296 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
3297 if datacenter_key
not in myvims
:
3299 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
3300 except NfvoException
as e
:
3301 logger
.error(str(e
))
3303 myvim_threads
[datacenter_key
] = myvim_thread
3304 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
3305 datacenter_tenant_id
=net
["datacenter_tenant_id"])
3307 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
3308 myvims
[datacenter_key
] = None
3310 myvims
[datacenter_key
] = vims
.values()[0]
3311 myvim
= myvims
[datacenter_key
]
3312 myvim_thread
= myvim_threads
[datacenter_key
]
3315 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
3319 "instance_action_id": instance_action_id
,
3320 "task_index": task_index
,
3321 "datacenter_vim_id": net
["datacenter_tenant_id"],
3323 "status": "SCHEDULED",
3324 "item": "instance_nets",
3325 "item_id": net
["uuid"],
3326 "extra": yaml
.safe_dump({"params": (net
['vim_net_id'], net
['sdn_net_id'])},
3327 default_flow_style
=True, width
=256)
3330 db_vim_actions
.append(db_vim_action
)
3332 except vimconn
.vimconnNotFoundException
as e
:
3333 error_msg
+= "\n NET VIM_id={} not found at datacenter={}".format(net
['vim_net_id'], net
["datacenter_id"])
3334 logger
.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found",
3335 net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']))
3336 except vimconn
.vimconnException
as e
:
3337 error_msg
+= "\n NET VIM_id={} at datacenter={} Error: {} {}".format(net
['vim_net_id'],
3338 net
["datacenter_id"],
3339 e
.http_code
, str(e
))
3340 logger
.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s",
3341 e
.http_code
, net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']), str(e
))
3343 db_instance_action
["number_tasks"] = task_index
3345 {"instance_actions": db_instance_action
},
3346 {"vim_actions": db_vim_actions
}
3349 logger
.debug("delete_instance done DB tables: %s",
3350 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
3351 mydb
.new_rows(db_tables
, ())
3352 for myvim_thread_id
in vimthread_affected
.keys():
3353 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
3355 if len(error_msg
) > 0:
3356 return 'action_id={} instance {} deleted but some elements could not be deleted, or already deleted '\
3357 '(error: 404) from VIM: {}'.format(instance_action_id
, message
, error_msg
)
3359 return "action_id={} instance {} deleted".format(instance_action_id
, message
)
3362 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
3363 '''Refreshes a scenario instance. It modifies instanceDict'''
3365 - 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
3368 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
3369 # #print "nfvo.refresh_instance begins"
3370 # #print json.dumps(instanceDict, indent=4)
3372 # #print "Getting the VIM URL and the VIM tenant_id"
3375 # # 1. Getting VIM vm and net list
3376 # vms_updated = [] #List of VM instance uuids in openmano that were updated
3379 # for sce_vnf in instanceDict['vnfs']:
3380 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
3381 # if datacenter_key not in vm_list:
3382 # vm_list[datacenter_key] = []
3383 # if datacenter_key not in myvims:
3384 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
3385 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
3386 # if len(vims) == 0:
3387 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
3388 # myvims[datacenter_key] = None
3390 # myvims[datacenter_key] = vims.values()[0]
3391 # for vm in sce_vnf['vms']:
3392 # vm_list[datacenter_key].append(vm['vim_vm_id'])
3393 # vms_notupdated.append(vm["uuid"])
3395 # nets_updated = [] #List of VM instance uuids in openmano that were updated
3396 # nets_notupdated=[]
3398 # for net in instanceDict['nets']:
3399 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
3400 # if datacenter_key not in net_list:
3401 # net_list[datacenter_key] = []
3402 # if datacenter_key not in myvims:
3403 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
3404 # datacenter_tenant_id=net["datacenter_tenant_id"])
3405 # if len(vims) == 0:
3406 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
3407 # myvims[datacenter_key] = None
3409 # myvims[datacenter_key] = vims.values()[0]
3411 # net_list[datacenter_key].append(net['vim_net_id'])
3412 # nets_notupdated.append(net["uuid"])
3414 # # 1. Getting the status of all VMs
3416 # for datacenter_key in myvims:
3417 # if not vm_list.get(datacenter_key):
3421 # if not myvims[datacenter_key]:
3422 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
3425 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
3427 # except vimconn.vimconnException as e:
3428 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
3429 # failed_message = str(e)
3431 # for vm in vm_list[datacenter_key]:
3432 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
3434 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
3435 # for sce_vnf in instanceDict['vnfs']:
3436 # for vm in sce_vnf['vms']:
3437 # vm_id = vm['vim_vm_id']
3438 # interfaces = vm_dict[vm_id].pop('interfaces', [])
3439 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
3440 # has_mgmt_iface = False
3441 # for iface in vm["interfaces"]:
3442 # if iface["type"]=="mgmt":
3443 # has_mgmt_iface = True
3444 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
3445 # vm_dict[vm_id]['status'] = "ACTIVE"
3446 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
3447 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
3448 # 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'):
3449 # vm['status'] = vm_dict[vm_id]['status']
3450 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
3451 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
3452 # # 2.1. Update in openmano DB the VMs whose status changed
3454 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
3455 # vms_notupdated.remove(vm["uuid"])
3457 # vms_updated.append(vm["uuid"])
3458 # except db_base_Exception as e:
3459 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
3460 # # 2.2. Update in openmano DB the interface VMs
3461 # for interface in interfaces:
3462 # #translate from vim_net_id to instance_net_id
3463 # network_id_list=[]
3464 # for net in instanceDict['nets']:
3465 # if net["vim_net_id"] == interface["vim_net_id"]:
3466 # network_id_list.append(net["uuid"])
3467 # if not network_id_list:
3469 # del interface["vim_net_id"]
3471 # for network_id in network_id_list:
3472 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
3473 # except db_base_Exception as e:
3474 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
3476 # # 3. Getting the status of all nets
3478 # for datacenter_key in myvims:
3479 # if not net_list.get(datacenter_key):
3482 # failed_message = ""
3483 # if not myvims[datacenter_key]:
3484 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
3487 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
3489 # except vimconn.vimconnException as e:
3490 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
3491 # failed_message = str(e)
3493 # for net in net_list[datacenter_key]:
3494 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
3496 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
3497 # # TODO: update nets inside a vnf
3498 # for net in instanceDict['nets']:
3499 # net_id = net['vim_net_id']
3500 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
3501 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
3502 # 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'):
3503 # net['status'] = net_dict[net_id]['status']
3504 # net['error_msg'] = net_dict[net_id].get('error_msg')
3505 # net['vim_info'] = net_dict[net_id].get('vim_info')
3506 # # 5.1. Update in openmano DB the nets whose status changed
3508 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
3509 # nets_notupdated.remove(net["uuid"])
3511 # nets_updated.append(net["uuid"])
3512 # except db_base_Exception as e:
3513 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
3515 # # Returns appropriate output
3516 # #print "nfvo.refresh_instance finishes"
3517 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
3518 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
3519 instance_id
= instanceDict
['uuid']
3520 # if len(vms_notupdated)+len(nets_notupdated)>0:
3521 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
3522 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
3524 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
3526 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
3527 #print "Checking that the instance_id exists and getting the instance dictionary"
3528 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
3529 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
3531 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
3532 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
3534 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
3535 myvim
= vims
.values()[0]
3537 if action_dict
.get("create-vdu"):
3538 for vdu
in action_dict
["create-vdu"]:
3539 vdu_id
= vdu
.get("vdu-id")
3540 vdu_count
= vdu
.get("count", 1)
3541 # get from database TODO
3545 input_vnfs
= action_dict
.pop("vnfs", [])
3546 input_vms
= action_dict
.pop("vms", [])
3547 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
3551 for sce_vnf
in instanceDict
['vnfs']:
3552 for vm
in sce_vnf
['vms']:
3553 if not action_over_all
:
3554 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
3555 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
3558 if "add_public_key" in action_dict
:
3560 if sce_vnf
.get('mgmt_access'):
3561 mgmt_access
= yaml
.load(sce_vnf
['mgmt_access'])
3562 ssh_access
= mgmt_access
['config-access']['ssh-access']
3563 tenant
= mydb
.get_rows_by_id('nfvo_tenants', nfvo_tenant
)
3565 if ssh_access
['required'] and ssh_access
['default-user']:
3566 if 'ip_address' in vm
:
3567 mgmt_ip
= vm
['ip_address'].split(';')
3568 password
= mgmt_access
['config-access'].get('password')
3569 priv_RO_key
= decrypt_key(tenant
[0]['encrypted_RO_priv_key'], tenant
[0]['uuid'])
3570 myvim
.inject_user_key(mgmt_ip
[0], ssh_access
['default-user'],
3571 action_dict
['add_public_key'],
3572 password
=password
, ro_key
=priv_RO_key
)
3574 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
3575 HTTP_Internal_Server_Error
)
3577 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
3578 HTTP_Internal_Server_Error
)
3580 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
3581 HTTP_Internal_Server_Error
)
3583 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
3584 if "console" in action_dict
:
3585 if not global_config
["http_console_proxy"]:
3586 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
3587 "description": "{protocol}//{ip}:{port}/{suffix}".format(
3588 protocol
=data
["protocol"],
3589 ip
= data
["server"],
3590 port
= data
["port"],
3591 suffix
= data
["suffix"]),
3595 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
3596 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
3597 "description": "this console is only reachable by local interface",
3602 #print "console data", data
3604 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
3605 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
3606 "description": "{protocol}//{ip}:{port}/{suffix}".format(
3607 protocol
=data
["protocol"],
3608 ip
= global_config
["http_console_host"],
3609 port
= console_thread
.port
,
3610 suffix
= data
["suffix"]),
3614 except NfvoException
as e
:
3615 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
3619 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
3621 except vimconn
.vimconnException
as e
:
3622 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
3625 if vm_ok
==0: #all goes wrong
3630 def instance_action_get(mydb
, nfvo_tenant
, instance_id
, action_id
):
3632 if nfvo_tenant
and nfvo_tenant
!= "any":
3633 filter["tenant_id"] = nfvo_tenant
3634 if instance_id
and instance_id
!= "any":
3635 filter["instance_id"] = instance_id
3637 filter["uuid"] = action_id
3638 rows
= mydb
.get_rows(FROM
="instance_actions", WHERE
=filter)
3639 if not rows
and action_id
:
3640 raise NfvoException("Not found any action with this criteria", HTTP_Not_Found
)
3641 return {"ations": rows
}
3644 def create_or_use_console_proxy_thread(console_server
, console_port
):
3645 #look for a non-used port
3646 console_thread_key
= console_server
+ ":" + str(console_port
)
3647 if console_thread_key
in global_config
["console_thread"]:
3648 #global_config["console_thread"][console_thread_key].start_timeout()
3649 return global_config
["console_thread"][console_thread_key
]
3651 for port
in global_config
["console_port_iterator"]():
3652 #print "create_or_use_console_proxy_thread() port:", port
3653 if port
in global_config
["console_ports"]:
3656 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
3658 global_config
["console_thread"][console_thread_key
] = clithread
3659 global_config
["console_ports"][port
] = console_thread_key
3661 except cli
.ConsoleProxyExceptionPortUsed
as e
:
3662 #port used, try with onoher
3664 except cli
.ConsoleProxyException
as e
:
3665 raise NfvoException(str(e
), HTTP_Bad_Request
)
3666 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
3669 def check_tenant(mydb
, tenant_id
):
3670 '''check that tenant exists at database'''
3671 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
3673 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
3676 def new_tenant(mydb
, tenant_dict
):
3678 tenant_uuid
= str(uuid4())
3679 tenant_dict
['uuid'] = tenant_uuid
3681 pub_key
, priv_key
= create_RO_keypair(tenant_uuid
)
3682 tenant_dict
['RO_pub_key'] = pub_key
3683 tenant_dict
['encrypted_RO_priv_key'] = priv_key
3684 mydb
.new_row("nfvo_tenants", tenant_dict
, confidential_data
=True)
3685 except db_base_Exception
as e
:
3686 raise NfvoException("Error creating the new tenant: {} ".format(tenant_dict
['name']) + str(e
), HTTP_Internal_Server_Error
)
3689 def delete_tenant(mydb
, tenant
):
3690 #get nfvo_tenant info
3692 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
3693 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
3694 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
3697 def new_datacenter(mydb
, datacenter_descriptor
):
3698 if "config" in datacenter_descriptor
:
3699 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
3700 #Check that datacenter-type is correct
3701 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
3704 module
= "vimconn_" + datacenter_type
3705 pkg
= __import__("osm_ro." + module
)
3706 vim_conn
= getattr(pkg
, module
)
3707 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
3708 except (IOError, ImportError):
3709 # if module_info and module_info[0]:
3710 # file.close(module_info[0])
3711 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
3713 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True, confidential_data
=True)
3714 return datacenter_id
3717 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
3718 # obtain data, check that only one exist
3719 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
3722 datacenter_id
= datacenter
['uuid']
3723 where
={'uuid': datacenter
['uuid']}
3724 remove_port_mapping
= False
3725 if "config" in datacenter_descriptor
:
3726 if datacenter_descriptor
['config'] != None:
3728 new_config_dict
= datacenter_descriptor
["config"]
3731 for k
in new_config_dict
:
3732 if new_config_dict
[k
] == None:
3734 if k
== 'sdn-controller':
3735 remove_port_mapping
= True
3737 config_text
= datacenter
.get("config")
3740 config_dict
= yaml
.load(config_text
)
3741 config_dict
.update(new_config_dict
)
3745 except Exception as e
:
3746 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
3748 datacenter_descriptor
["config"] = yaml
.safe_dump(config_dict
, default_flow_style
=True, width
=256)
3750 datacenter_descriptor
["config"] = None
3751 if remove_port_mapping
:
3753 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_id
)
3754 except ovimException
as e
:
3755 logger
.error("Error deleting datacenter-port-mapping " + str(e
))
3757 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
3758 return datacenter_id
3761 def delete_datacenter(mydb
, datacenter
):
3762 #get nfvo_tenant info
3763 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
3764 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
3766 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_dict
['uuid'])
3767 except ovimException
as e
:
3768 logger
.error("Error deleting datacenter-port-mapping " + str(e
))
3769 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
3772 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):
3773 # get datacenter info
3775 datacenter_id
= get_datacenter_uuid(mydb
, None, datacenter
)
3777 create_vim_tenant
= True if not vim_tenant_id
and not vim_tenant_name
else False
3779 # get nfvo_tenant info
3780 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
3781 if vim_tenant_name
==None:
3782 vim_tenant_name
=tenant_dict
['name']
3784 #check that this association does not exist before
3785 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
3786 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
3787 if len(tenants_datacenters
)>0:
3788 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
3790 vim_tenant_id_exist_atdb
=False
3791 if not create_vim_tenant
:
3792 where_
={"datacenter_id": datacenter_id
}
3793 if vim_tenant_id
!=None:
3794 where_
["vim_tenant_id"] = vim_tenant_id
3795 if vim_tenant_name
!=None:
3796 where_
["vim_tenant_name"] = vim_tenant_name
3797 #check if vim_tenant_id is already at database
3798 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
3799 if len(datacenter_tenants_dict
)>=1:
3800 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
3801 vim_tenant_id_exist_atdb
=True
3802 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
3804 datacenter_tenants_dict
= {}
3805 #insert at table datacenter_tenants
3806 else: #if vim_tenant_id==None:
3807 #create tenant at VIM if not provided
3809 _
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
, vim_user
=vim_username
,
3810 vim_passwd
=vim_password
)
3811 datacenter_name
= myvim
["name"]
3812 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
3813 except vimconn
.vimconnException
as e
:
3814 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
3815 datacenter_tenants_dict
= {}
3816 datacenter_tenants_dict
["created"]="true"
3818 #fill datacenter_tenants table
3819 if not vim_tenant_id_exist_atdb
:
3820 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
3821 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
3822 datacenter_tenants_dict
["user"] = vim_username
3823 datacenter_tenants_dict
["passwd"] = vim_password
3824 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
3826 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
3827 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True, confidential_data
=True)
3828 datacenter_tenants_dict
["uuid"] = id_
3830 #fill tenants_datacenters table
3831 datacenter_tenant_id
= datacenter_tenants_dict
["uuid"]
3832 tenants_datacenter_dict
["datacenter_tenant_id"] = datacenter_tenant_id
3833 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
3835 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_dict
['uuid'], datacenter_id
) # reload data
3836 datacenter_name
= myvim
["name"]
3837 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
3838 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, datacenter_name
, datacenter_tenant_id
,
3839 db
=db
, db_lock
=db_lock
, ovim
=ovim
)
3841 thread_id
= datacenter_tenants_dict
["uuid"]
3842 vim_threads
["running"][thread_id
] = new_thread
3843 return datacenter_id
3844 except vimconn
.vimconnException
as e
:
3845 raise NfvoException(str(e
), HTTP_Bad_Request
)
3848 def edit_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=None, vim_tenant_name
=None,
3849 vim_username
=None, vim_password
=None, config
=None):
3850 #Obtain the data of this datacenter_tenant_id
3851 vim_data
= mydb
.get_rows(
3852 SELECT
=("datacenter_tenants.vim_tenant_name", "datacenter_tenants.vim_tenant_id", "datacenter_tenants.user",
3853 "datacenter_tenants.passwd", "datacenter_tenants.config"),
3854 FROM
="datacenter_tenants JOIN tenants_datacenters ON datacenter_tenants.uuid=tenants_datacenters.datacenter_tenant_id",
3855 WHERE
={"tenants_datacenters.nfvo_tenant_id": nfvo_tenant
,
3856 "tenants_datacenters.datacenter_id": datacenter_id
})
3858 logger
.debug(str(vim_data
))
3859 if len(vim_data
) < 1:
3860 raise NfvoException("Datacenter {} is not attached for tenant {}".format(datacenter_id
, nfvo_tenant
), HTTP_Conflict
)
3864 v
['config'] = yaml
.load(v
['config'])
3867 v
['vim_tenant_id'] = vim_tenant_id
3869 v
['vim_tenant_name'] = vim_tenant_name
3871 v
['user'] = vim_username
3873 v
['passwd'] = vim_password
3877 v
['config'].update(config
)
3879 logger
.debug(str(v
))
3880 deassociate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'])
3881 associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'], vim_tenant_name
=v
['vim_tenant_name'],
3882 vim_username
=v
['user'], vim_password
=v
['passwd'], config
=v
['config'])
3884 return datacenter_id
3886 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
3887 #get nfvo_tenant info
3888 if not tenant_id
or tenant_id
=="any":
3891 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
3892 tenant_uuid
= tenant_dict
['uuid']
3894 datacenter_id
= get_datacenter_uuid(mydb
, tenant_uuid
, datacenter
)
3895 #check that this association exist before
3896 tenants_datacenter_dict
={"datacenter_id": datacenter_id
}
3898 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
3899 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
3900 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
3901 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
3903 #delete this association
3904 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
3906 #get vim_tenant info and deletes
3908 for tenant_datacenter_item
in tenant_datacenter_list
:
3909 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
3910 #try to delete vim:tenant
3912 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
3913 if vim_tenant_dict
['created']=='true':
3914 #delete tenant at VIM if created by NFVO
3916 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3917 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
3918 except vimconn
.vimconnException
as e
:
3919 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
3920 logger
.warn(warning
)
3921 except db_base_Exception
as e
:
3922 logger
.error("Cannot delete datacenter_tenants " + str(e
))
3923 pass # the error will be caused because dependencies, vim_tenant can not be deleted
3924 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
3925 thread
= vim_threads
["running"][thread_id
]
3926 thread
.insert_task("exit")
3927 vim_threads
["deleting"][thread_id
] = thread
3928 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
3931 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
3933 #get datacenter info
3934 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3936 if 'net-update' in action_dict
:
3938 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
3940 except vimconn
.vimconnException
as e
:
3941 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
3942 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
3943 #update nets Change from VIM format to NFVO format
3946 net_nfvo
={'datacenter_id': datacenter_id
}
3947 net_nfvo
['name'] = net
['name']
3948 #net_nfvo['description']= net['name']
3949 net_nfvo
['vim_net_id'] = net
['id']
3950 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
3951 net_nfvo
['shared'] = net
['shared']
3952 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
3953 net_list
.append(net_nfvo
)
3954 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
3955 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
3957 elif 'net-edit' in action_dict
:
3958 net
= action_dict
['net-edit'].pop('net')
3959 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
3960 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
3961 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
3963 elif 'net-delete' in action_dict
:
3964 net
= action_dict
['net-deelte'].get('net')
3965 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
3966 result
= mydb
.delete_row(FROM
='datacenter_nets',
3967 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
3971 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
3974 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
3975 #get datacenter info
3976 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3978 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
3979 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
3980 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
3984 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
3985 #get datacenter info
3986 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3989 action_dict
= action_dict
["netmap"]
3990 if 'vim_id' in action_dict
:
3991 filter_dict
["id"] = action_dict
['vim_id']
3992 if 'vim_name' in action_dict
:
3993 filter_dict
["name"] = action_dict
['vim_name']
3995 filter_dict
["shared"] = True
3998 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
3999 except vimconn
.vimconnException
as e
:
4000 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
4001 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
4002 if len(vim_nets
)>1 and action_dict
:
4003 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
4004 elif len(vim_nets
)==0: # and action_dict:
4005 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
4007 for net
in vim_nets
:
4008 net_nfvo
={'datacenter_id': datacenter_id
}
4009 if action_dict
and "name" in action_dict
:
4010 net_nfvo
['name'] = action_dict
['name']
4012 net_nfvo
['name'] = net
['name']
4013 #net_nfvo['description']= net['name']
4014 net_nfvo
['vim_net_id'] = net
['id']
4015 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
4016 net_nfvo
['shared'] = net
['shared']
4017 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
4019 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
4020 net_nfvo
["status"] = "OK"
4021 net_nfvo
["uuid"] = net_id
4022 except db_base_Exception
as e
:
4026 net_nfvo
["status"] = "FAIL: " + str(e
)
4027 net_list
.append(net_nfvo
)
4030 def get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
):
4031 # obtain all network data
4033 if utils
.check_valid_uuid(network_id
):
4034 filter_dict
= {"id": network_id
}
4036 filter_dict
= {"name": network_id
}
4038 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4039 network
= myvim
.get_network_list(filter_dict
=filter_dict
)
4040 except vimconn
.vimconnException
as e
:
4041 raise NfvoException("Not possible to get_sdn_net_id from VIM: {}".format(str(e
)), e
.http_code
)
4043 # ensure the network is defined
4044 if len(network
) == 0:
4045 raise NfvoException("Network {} is not present in the system".format(network_id
),
4048 # ensure there is only one network with the provided name
4049 if len(network
) > 1:
4050 raise NfvoException("Multiple networks present in vim identified by {}".format(network_id
), HTTP_Bad_Request
)
4052 # ensure it is a dataplane network
4053 if network
[0]['type'] != 'data':
4056 # ensure we use the id
4057 network_id
= network
[0]['id']
4059 # search in dabase mano_db in table instance nets for the sdn_net_id that corresponds to the vim_net_id==network_id
4060 # and with instance_scenario_id==NULL
4061 #search_dict = {'vim_net_id': network_id, 'instance_scenario_id': None}
4062 search_dict
= {'vim_net_id': network_id
}
4065 #sdn_network_id = mydb.get_rows(SELECT=('sdn_net_id',), FROM='instance_nets', WHERE=search_dict)[0]['sdn_net_id']
4066 result
= mydb
.get_rows(SELECT
=('sdn_net_id',), FROM
='instance_nets', WHERE
=search_dict
)
4067 except db_base_Exception
as e
:
4068 raise NfvoException("db_base_Exception obtaining SDN network to associated to vim network {}".format(
4069 network_id
) + str(e
), HTTP_Internal_Server_Error
)
4073 if net
['sdn_net_id'] != None:
4075 sdn_net_id
= net
['sdn_net_id']
4077 if sdn_net_counter
== 0:
4079 elif sdn_net_counter
== 1:
4082 raise NfvoException("More than one SDN network is associated to vim network {}".format(
4083 network_id
), HTTP_Internal_Server_Error
)
4085 def get_sdn_controller_id(mydb
, datacenter
):
4086 # Obtain sdn controller id
4087 config
= mydb
.get_rows(SELECT
=('config',), FROM
='datacenters', WHERE
={'uuid': datacenter
})[0].get('config', '{}')
4091 return yaml
.load(config
).get('sdn-controller')
4093 def vim_net_sdn_attach(mydb
, tenant_id
, datacenter
, network_id
, descriptor
):
4095 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
4096 if not sdn_network_id
:
4097 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
), HTTP_Internal_Server_Error
)
4099 #Obtain sdn controller id
4100 controller_id
= get_sdn_controller_id(mydb
, datacenter
)
4101 if not controller_id
:
4102 raise NfvoException("No SDN controller is set for datacenter {}".format(datacenter
), HTTP_Internal_Server_Error
)
4104 #Obtain sdn controller info
4105 sdn_controller
= ovim
.show_of_controller(controller_id
)
4108 'name': 'external_port',
4109 'net_id': sdn_network_id
,
4110 'ofc_id': controller_id
,
4111 'switch_dpid': sdn_controller
['dpid'],
4112 'switch_port': descriptor
['port']
4115 if 'vlan' in descriptor
:
4116 port_data
['vlan'] = descriptor
['vlan']
4117 if 'mac' in descriptor
:
4118 port_data
['mac'] = descriptor
['mac']
4120 result
= ovim
.new_port(port_data
)
4121 except ovimException
as e
:
4122 raise NfvoException("ovimException attaching SDN network {} to vim network {}".format(
4123 sdn_network_id
, network_id
) + str(e
), HTTP_Internal_Server_Error
)
4124 except db_base_Exception
as e
:
4125 raise NfvoException("db_base_Exception attaching SDN network to vim network {}".format(
4126 network_id
) + str(e
), HTTP_Internal_Server_Error
)
4128 return 'Port uuid: '+ result
4130 def vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, network_id
, port_id
=None):
4132 filter = {'uuid': port_id
}
4134 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
4135 if not sdn_network_id
:
4136 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
),
4137 HTTP_Internal_Server_Error
)
4138 #in case no port_id is specified only ports marked as 'external_port' will be detached
4139 filter = {'name': 'external_port', 'net_id': sdn_network_id
}
4142 port_list
= ovim
.get_ports(columns
={'uuid'}, filter=filter)
4143 except ovimException
as e
:
4144 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
4145 HTTP_Internal_Server_Error
)
4147 if len(port_list
) == 0:
4148 raise NfvoException("No ports attached to the network {} were found with the requested criteria".format(network_id
),
4152 for port
in port_list
:
4154 port_uuid_list
.append(port
['uuid'])
4155 ovim
.delete_port(port
['uuid'])
4156 except ovimException
as e
:
4157 raise NfvoException("ovimException deleting port {} for net {}. ".format(port
['uuid'], network_id
) + str(e
), HTTP_Internal_Server_Error
)
4159 return 'Detached ports uuid: {}'.format(','.join(port_uuid_list
))
4161 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
4162 #get datacenter info
4163 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4166 if utils
.check_valid_uuid(name
):
4167 filter_dict
["id"] = name
4169 filter_dict
["name"] = name
4171 if item
=="networks":
4172 #filter_dict['tenant_id'] = myvim['tenant_id']
4173 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
4175 if len(content
) == 0:
4176 raise NfvoException("Network {} is not present in the system. ".format(name
),
4179 #Update the networks with the attached ports
4181 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, net
['id'])
4182 if sdn_network_id
!= None:
4184 #port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan'}, filter={'name': 'external_port', 'net_id': sdn_network_id})
4185 port_list
= ovim
.get_ports(columns
={'uuid', 'switch_port', 'vlan','name'}, filter={'net_id': sdn_network_id
})
4186 except ovimException
as e
:
4187 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
), HTTP_Internal_Server_Error
)
4188 #Remove field name and if port name is external_port save it as 'type'
4189 for port
in port_list
:
4190 if port
['name'] == 'external_port':
4191 port
['type'] = "External"
4193 net
['sdn_network_id'] = sdn_network_id
4194 net
['sdn_attached_ports'] = port_list
4196 elif item
=="tenants":
4197 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
4198 elif item
== "images":
4200 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
4202 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
4203 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
4204 if name
and len(content
)==1:
4205 return {item
[:-1]: content
[0]}
4206 elif name
and len(content
)==0:
4207 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
4210 return {item
: content
}
4211 except vimconn
.vimconnException
as e
:
4212 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
4213 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
4216 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
4217 #get datacenter info
4218 if tenant_id
== "any":
4221 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4223 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
4224 logger
.debug("vim_action_delete vim response: " + str(content
))
4225 items
= content
.values()[0]
4226 if type(items
)==list and len(items
)==0:
4227 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
4228 elif type(items
)==list and len(items
)>1:
4229 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
4230 else: # it is a dict
4231 item_id
= items
["id"]
4232 item_name
= str(items
.get("name"))
4235 if item
=="networks":
4236 # If there is a SDN network associated to the vim-network, proceed to clear the relationship and delete it
4237 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, item_id
)
4238 if sdn_network_id
!= None:
4239 #Delete any port attachment to this network
4241 port_list
= ovim
.get_ports(columns
={'uuid'}, filter={'net_id': sdn_network_id
})
4242 except ovimException
as e
:
4243 raise NfvoException(
4244 "ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
4245 HTTP_Internal_Server_Error
)
4247 # By calling one by one all ports to be detached we ensure that not only the external_ports get detached
4248 for port
in port_list
:
4249 vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, item_id
, port
['uuid'])
4251 #Delete from 'instance_nets' the correspondence between the vim-net-id and the sdn-net-id
4253 mydb
.delete_row(FROM
='instance_nets', WHERE
={'instance_scenario_id': None, 'sdn_net_id': sdn_network_id
, 'vim_net_id': item_id
})
4254 except db_base_Exception
as e
:
4255 raise NfvoException("Error deleting correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
4256 str(e
), HTTP_Internal_Server_Error
)
4258 #Delete the SDN network
4260 ovim
.delete_network(sdn_network_id
)
4261 except ovimException
as e
:
4262 logger
.error("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
), exc_info
=True)
4263 raise NfvoException("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
),
4264 HTTP_Internal_Server_Error
)
4266 content
= myvim
.delete_network(item_id
)
4267 elif item
=="tenants":
4268 content
= myvim
.delete_tenant(item_id
)
4269 elif item
== "images":
4270 content
= myvim
.delete_image(item_id
)
4272 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
4273 except vimconn
.vimconnException
as e
:
4274 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
4275 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
4277 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
4280 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
4281 #get datacenter info
4282 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
4283 if tenant_id
== "any":
4285 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4287 if item
=="networks":
4288 net
= descriptor
["network"]
4289 net_name
= net
.pop("name")
4290 net_type
= net
.pop("type", "bridge")
4291 net_public
= net
.pop("shared", False)
4292 net_ipprofile
= net
.pop("ip_profile", None)
4293 net_vlan
= net
.pop("vlan", None)
4294 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
4296 #If the datacenter has a SDN controller defined and the network is of dataplane type, then create the sdn network
4297 if get_sdn_controller_id(mydb
, datacenter
) != None and (net_type
== 'data' or net_type
== 'ptp'):
4300 sdn_network
['vlan'] = net_vlan
4301 sdn_network
['type'] = net_type
4302 sdn_network
['name'] = net_name
4303 ovim_content
= ovim
.new_network(sdn_network
)
4304 except ovimException
as e
:
4305 self
.logger
.error("ovimException creating SDN network={} ".format(
4306 sdn_network
) + str(e
), exc_info
=True)
4307 raise NfvoException("ovimException creating SDN network={} ".format(sdn_network
) + str(e
),
4308 HTTP_Internal_Server_Error
)
4310 # Save entry in in dabase mano_db in table instance_nets to stablish a dictionary vim_net_id <->sdn_net_id
4311 # use instance_scenario_id=None to distinguish from real instaces of nets
4312 correspondence
= {'instance_scenario_id': None, 'sdn_net_id': ovim_content
, 'vim_net_id': content
}
4313 #obtain datacenter_tenant_id
4314 correspondence
['datacenter_tenant_id'] = mydb
.get_rows(SELECT
=('uuid',), FROM
='datacenter_tenants', WHERE
={'datacenter_id': datacenter
})[0]['uuid']
4317 mydb
.new_row('instance_nets', correspondence
, add_uuid
=True)
4318 except db_base_Exception
as e
:
4319 raise NfvoException("Error saving correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
4320 str(e
), HTTP_Internal_Server_Error
)
4321 elif item
=="tenants":
4322 tenant
= descriptor
["tenant"]
4323 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
4325 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
4326 except vimconn
.vimconnException
as e
:
4327 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
4329 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
4331 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
4332 data
= ovim
.new_of_controller(sdn_controller
)
4333 logger
.debug('New SDN controller created with uuid {}'.format(data
))
4336 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
4337 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
4338 msg
= 'SDN controller {} updated'.format(data
)
4342 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
4343 if controller_id
== None:
4344 data
= ovim
.get_of_controllers()
4346 data
= ovim
.show_of_controller(controller_id
)
4348 msg
= 'SDN controller list:\n {}'.format(data
)
4352 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
4353 select_
= ('uuid', 'config')
4354 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
4355 for datacenter
in datacenters
:
4356 if datacenter
['config']:
4357 config
= yaml
.load(datacenter
['config'])
4358 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
4359 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), HTTP_Conflict
)
4361 data
= ovim
.delete_of_controller(controller_id
)
4362 msg
= 'SDN controller {} deleted'.format(data
)
4366 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
4367 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
4368 if len(controller
) < 1:
4369 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), HTTP_Not_Found
)
4372 sdn_controller_id
= yaml
.load(controller
[0]["config"])["sdn-controller"]
4374 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), HTTP_Bad_Request
)
4376 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
4377 switch_dpid
= sdn_controller
["dpid"]
4380 for compute_node
in sdn_port_mapping
:
4381 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
4383 element
["compute_node"] = compute_node
["compute_node"]
4384 for port
in compute_node
["ports"]:
4385 element
["pci"] = port
.get("pci")
4386 element
["switch_port"] = port
.get("switch_port")
4387 element
["switch_mac"] = port
.get("switch_mac")
4388 if not element
["pci"] or not (element
["switch_port"] or element
["switch_mac"]):
4389 raise NfvoException ("The mapping must contain the 'pci' and at least one of the elements 'switch_port'"
4390 " or 'switch_mac'", HTTP_Bad_Request
)
4391 maps
.append(dict(element
))
4393 return ovim
.set_of_port_mapping(maps
, ofc_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, region
=datacenter_id
)
4395 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
4396 maps
= ovim
.get_of_port_mappings(db_filter
={"region": datacenter_id
})
4399 "sdn-controller": None,
4400 "datacenter-id": datacenter_id
,
4402 "ports_mapping": list()
4405 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
4406 if datacenter
['config']:
4407 config
= yaml
.load(datacenter
['config'])
4408 if 'sdn-controller' in config
:
4409 controller_id
= config
['sdn-controller']
4410 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
4411 result
["sdn-controller"] = controller_id
4412 result
["dpid"] = sdn_controller
["dpid"]
4414 if result
["sdn-controller"] == None:
4415 raise NfvoException("SDN controller is not defined for datacenter {}".format(datacenter_id
), HTTP_Bad_Request
)
4416 if result
["dpid"] == None:
4417 raise NfvoException("It was not possible to determine DPID for SDN controller {}".format(result
["sdn-controller"]),
4418 HTTP_Internal_Server_Error
)
4423 ports_correspondence_dict
= dict()
4425 if result
["sdn-controller"] != link
["ofc_id"]:
4426 raise NfvoException("The sdn-controller specified for different port mappings differ", HTTP_Internal_Server_Error
)
4427 if result
["dpid"] != link
["switch_dpid"]:
4428 raise NfvoException("The dpid specified for different port mappings differ", HTTP_Internal_Server_Error
)
4430 element
["pci"] = link
["pci"]
4431 if link
["switch_port"]:
4432 element
["switch_port"] = link
["switch_port"]
4433 if link
["switch_mac"]:
4434 element
["switch_mac"] = link
["switch_mac"]
4436 if not link
["compute_node"] in ports_correspondence_dict
:
4438 content
["compute_node"] = link
["compute_node"]
4439 content
["ports"] = list()
4440 ports_correspondence_dict
[link
["compute_node"]] = content
4442 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
4444 for key
in sorted(ports_correspondence_dict
):
4445 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
4449 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
4450 return ovim
.clear_of_port_mapping(db_filter
={"region":datacenter_id
})
4452 def create_RO_keypair(tenant_id
):
4454 Creates a public / private keys for a RO tenant and returns their values
4456 tenant_id: ID of the tenant
4458 public_key: Public key for the RO tenant
4459 private_key: Encrypted private key for RO tenant
4463 key
= RSA
.generate(bits
)
4465 public_key
= key
.publickey().exportKey('OpenSSH')
4466 if isinstance(public_key
, ValueError):
4467 raise NfvoException("Unable to create public key: {}".format(public_key
), HTTP_Internal_Server_Error
)
4468 private_key
= key
.exportKey(passphrase
=tenant_id
, pkcs
=8)
4469 except (ValueError, NameError) as e
:
4470 raise NfvoException("Unable to create private key: {}".format(e
), HTTP_Internal_Server_Error
)
4471 return public_key
, private_key
4473 def decrypt_key (key
, tenant_id
):
4475 Decrypts an encrypted RSA key
4477 key: Private key to be decrypted
4478 tenant_id: ID of the tenant
4480 unencrypted_key: Unencrypted private key for RO tenant
4483 key
= RSA
.importKey(key
,tenant_id
)
4484 unencrypted_key
= key
.exportKey('PEM')
4485 if isinstance(unencrypted_key
, ValueError):
4486 raise NfvoException("Unable to decrypt the private key: {}".format(unencrypted_key
), HTTP_Internal_Server_Error
)
4487 except ValueError as e
:
4488 raise NfvoException("Unable to decrypt the private key: {}".format(e
), HTTP_Internal_Server_Error
)
4489 return unencrypted_key