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 db_base
import db_base_Exception
44 from threading
import Lock
46 import openvim
.ovim
as Ovim
49 global vimconn_imported
51 global default_volume_size
52 default_volume_size
= '5' #size in GB
57 vimconn_imported
= {} # dictionary with VIM type as key, loaded module as value
58 vim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-VIMs
59 vim_persistent_info
= {}
60 logger
= logging
.getLogger('openmano.nfvo')
62 global_instance_tasks
= {}
67 class NfvoException(Exception):
68 def __init__(self
, message
, http_code
):
69 self
.http_code
= http_code
70 Exception.__init
__(self
, message
)
76 if task_id
<= last_task_id
:
77 task_id
= last_task_id
+ 0.000001
78 last_task_id
= task_id
79 return "TASK.{:.6f}".format(task_id
)
82 def new_task(name
, params
, depends
=None):
83 task_id
= get_task_id()
84 task
= {"status": "enqueued", "id": task_id
, "name": name
, "params": params
}
86 task
["depends"] = depends
91 return True if id[:5] == "TASK." else False
94 def get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_name
, tenant_id
):
95 name
= datacenter_name
[:16]
96 if name
not in vim_threads
["names"]:
97 vim_threads
["names"].append(name
)
99 name
= datacenter_name
[:16] + "." + tenant_name
[:16]
100 if name
not in vim_threads
["names"]:
101 vim_threads
["names"].append(name
)
103 name
= datacenter_id
+ "-" + tenant_id
104 vim_threads
["names"].append(name
)
108 def start_service(mydb
):
109 global db
, global_config
110 db
= nfvo_db
.nfvo_db()
111 db
.connect(global_config
['db_host'], global_config
['db_user'], global_config
['db_passwd'], global_config
['db_name'])
114 # Initialize openvim for SDN control
115 # TODO: Avoid static configuration by adding new parameters to openmanod.cfg
116 # TODO: review ovim.py to delete not needed configuration
117 ovim_configuration
= {
118 'logger_name': 'openvim',
119 'network_vlan_range_start': 1000,
120 'network_vlan_range_end': 4096,
121 'log_level_db': 'DEBUG',
122 'db_name': 'mano_vim_db',
123 'db_host': 'localhost',
125 'db_passwd': 'vimpw',
126 'database_version': '0.15',
129 'of_controller_nets_with_same_vlan': True,
130 'network_type': 'bridge',
131 #TODO: log_level_of should not be needed. To be modified in ovim
132 'log_level_of': 'DEBUG'
134 ovim
= Ovim
.ovim(ovim_configuration
)
137 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'
138 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
139 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
140 'user','passwd', 'dt.config as dt_config', 'nfvo_tenant_id')
142 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
)
144 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
145 'datacenter_id': vim
.get('datacenter_id')}
147 extra
.update(yaml
.load(vim
["config"]))
148 if vim
.get('dt_config'):
149 extra
.update(yaml
.load(vim
["dt_config"]))
150 if vim
["type"] not in vimconn_imported
:
153 module
= "vimconn_" + vim
["type"]
154 module_info
= imp
.find_module(module
)
155 vim_conn
= imp
.load_module(vim
["type"], *module_info
)
156 vimconn_imported
[vim
["type"]] = vim_conn
157 except (IOError, ImportError) as e
:
158 if module_info
and module_info
[0]:
159 file.close(module_info
[0])
160 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
161 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
163 thread_id
= vim
['datacenter_tenant_id']
164 vim_persistent_info
[thread_id
] = {}
167 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
168 myvim
= vimconn_imported
[ vim
["type"] ].vimconnector(
169 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
170 tenant_id
=vim
['vim_tenant_id'], tenant_name
=vim
['vim_tenant_name'],
171 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
172 user
=vim
['user'], passwd
=vim
['passwd'],
173 config
=extra
, persistent_info
=vim_persistent_info
[thread_id
]
175 except Exception as e
:
176 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
177 thread_name
= get_non_used_vim_name(vim
['datacenter_name'], vim
['vim_tenant_id'], vim
['vim_tenant_name'], vim
['vim_tenant_id'])
178 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, vim
['datacenter_name'],
179 vim
['datacenter_tenant_id'], db
=db
, db_lock
=db_lock
, ovim
=ovim
)
181 vim_threads
["running"][thread_id
] = new_thread
182 except db_base_Exception
as e
:
183 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
187 global ovim
, global_config
190 for thread_id
,thread
in vim_threads
["running"].items():
191 thread
.insert_task(new_task("exit", None))
192 vim_threads
["deleting"][thread_id
] = thread
193 vim_threads
["running"] = {}
194 if global_config
and global_config
.get("console_thread"):
195 for thread
in global_config
["console_thread"]:
196 thread
.terminate
= True
199 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
201 return result, content:
202 <0, error_text upon error
203 nb_records, flavor_list on success
206 WHERE_dict
['vnf_id'] = vnf_id
207 if nfvo_tenant
is not None:
208 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
210 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
211 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
212 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
213 #print "get_flavor_list result:", result
214 #print "get_flavor_list content:", content
216 for flavor
in flavors
:
217 flavorList
.append(flavor
['flavor_id'])
221 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
223 return result, content:
224 <0, error_text upon error
225 nb_records, flavor_list on success
228 WHERE_dict
['vnf_id'] = vnf_id
229 if nfvo_tenant
is not None:
230 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
232 #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
233 images
= mydb
.get_rows(FROM
='vms join images on vms.image_id=images.uuid',SELECT
=('image_id',),WHERE
=WHERE_dict
)
236 imageList
.append(image
['image_id'])
240 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
241 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None):
242 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
243 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
244 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
245 raise exception upon error
248 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
249 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
250 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
251 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
252 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
253 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
254 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
255 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'
256 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
257 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
258 'user','passwd', 'dt.config as dt_config')
260 from_
= 'datacenters as d'
261 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
263 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
266 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
267 'datacenter_id': vim
.get('datacenter_id')}
269 extra
.update(yaml
.load(vim
["config"]))
270 if vim
.get('dt_config'):
271 extra
.update(yaml
.load(vim
["dt_config"]))
272 if vim
["type"] not in vimconn_imported
:
275 module
= "vimconn_" + vim
["type"]
276 module_info
= imp
.find_module(module
)
277 vim_conn
= imp
.load_module(vim
["type"], *module_info
)
278 vimconn_imported
[vim
["type"]] = vim_conn
279 except (IOError, ImportError) as e
:
280 if module_info
and module_info
[0]:
281 file.close(module_info
[0])
282 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
283 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
286 if 'datacenter_tenant_id' in vim
:
287 thread_id
= vim
["datacenter_tenant_id"]
288 if thread_id
not in vim_persistent_info
:
289 vim_persistent_info
[thread_id
] = {}
290 persistent_info
= vim_persistent_info
[thread_id
]
294 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
295 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
296 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
297 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
),
298 tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
299 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
300 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
301 config
=extra
, persistent_info
=persistent_info
303 except Exception as e
:
304 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
306 except db_base_Exception
as e
:
307 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
310 def rollback(mydb
, vims
, rollback_list
):
312 #delete things by reverse order
313 for i
in range(len(rollback_list
)-1, -1, -1):
314 item
= rollback_list
[i
]
315 if item
["where"]=="vim":
316 if item
["vim_id"] not in vims
:
318 vim
=vims
[ item
["vim_id"] ]
320 if item
["what"]=="image":
321 vim
.delete_image(item
["uuid"])
322 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
323 elif item
["what"]=="flavor":
324 vim
.delete_flavor(item
["uuid"])
325 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
326 elif item
["what"]=="network":
327 vim
.delete_network(item
["uuid"])
328 elif item
["what"]=="vm":
329 vim
.delete_vminstance(item
["uuid"])
330 except vimconn
.vimconnException
as e
:
331 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
332 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
333 except db_base_Exception
as e
:
334 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
338 if item
["what"]=="image":
339 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
340 elif item
["what"]=="flavor":
341 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
342 except db_base_Exception
as e
:
343 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
344 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
345 if len(undeleted_items
)==0:
346 return True," Rollback successful."
348 return False," Rollback fails to delete: " + str(undeleted_items
)
351 def check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1):
353 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
355 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
357 #dataplane interfaces
358 for numa
in vnfc
.get("numas",() ):
359 for interface
in numa
.get("interfaces",()):
360 if interface
["name"] in name_dict
:
362 "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
363 vnfc
["name"], interface
["name"]),
365 name_dict
[ interface
["name"] ] = "underlay"
367 for interface
in vnfc
.get("bridge-ifaces",() ):
368 if interface
["name"] in name_dict
:
370 "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
371 vnfc
["name"], interface
["name"]),
373 name_dict
[ interface
["name"] ] = "overlay"
374 vnfc_interfaces
[ vnfc
["name"] ] = name_dict
375 # check bood-data info
376 if "boot-data" in vnfc
:
377 # check that user-data is incompatible with users and config-files
378 if (vnfc
["boot-data"].get("users") or vnfc
["boot-data"].get("config-files")) and vnfc
["boot-data"].get("user-data"):
380 "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
383 #check if the info in external_connections matches with the one in the vnfcs
385 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
386 if external_connection
["name"] in name_list
:
388 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
389 external_connection
["name"]),
391 name_list
.append(external_connection
["name"])
392 if external_connection
["VNFC"] not in vnfc_interfaces
:
394 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
395 external_connection
["name"], external_connection
["VNFC"]),
398 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
400 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
401 external_connection
["name"],
402 external_connection
["local_iface_name"]),
405 #check if the info in internal_connections matches with the one in the vnfcs
407 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
408 if internal_connection
["name"] in name_list
:
410 "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection".format(
411 internal_connection
["name"]),
413 name_list
.append(internal_connection
["name"])
414 #We should check that internal-connections of type "ptp" have only 2 elements
416 if len(internal_connection
["elements"])>2 and (internal_connection
.get("type") == "ptp" or internal_connection
.get("type") == "e-line"):
418 "Error at 'vnf:internal-connections[name:'{}']:elements', size must be 2 for a '{}' type. Consider change it to '{}' type".format(
419 internal_connection
["name"],
420 'ptp' if vnf_descriptor_version
==1 else 'e-line',
421 'data' if vnf_descriptor_version
==1 else "e-lan"),
423 for port
in internal_connection
["elements"]:
425 iface
= port
["local_iface_name"]
426 if vnf
not in vnfc_interfaces
:
428 "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
429 internal_connection
["name"], vnf
),
431 if iface
not in vnfc_interfaces
[ vnf
]:
433 "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
434 internal_connection
["name"], iface
),
436 return -HTTP_Bad_Request
,
437 if vnf_descriptor_version
==1 and "type" not in internal_connection
:
438 if vnfc_interfaces
[vnf
][iface
] == "overlay":
439 internal_connection
["type"] = "bridge"
441 internal_connection
["type"] = "data"
442 if vnf_descriptor_version
==2 and "implementation" not in internal_connection
:
443 if vnfc_interfaces
[vnf
][iface
] == "overlay":
444 internal_connection
["implementation"] = "overlay"
446 internal_connection
["implementation"] = "underlay"
447 if (internal_connection
.get("type") == "data" or internal_connection
.get("type") == "ptp" or \
448 internal_connection
.get("implementation") == "underlay") and vnfc_interfaces
[vnf
][iface
] == "overlay":
450 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
451 internal_connection
["name"],
452 iface
, 'bridge' if vnf_descriptor_version
==1 else 'overlay',
453 'data' if vnf_descriptor_version
==1 else 'underlay'),
455 if (internal_connection
.get("type") == "bridge" or internal_connection
.get("implementation") == "overlay") and \
456 vnfc_interfaces
[vnf
][iface
] == "underlay":
458 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
459 internal_connection
["name"], iface
,
460 'data' if vnf_descriptor_version
==1 else 'underlay',
461 'bridge' if vnf_descriptor_version
==1 else 'overlay'),
465 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
467 if only_create_at_vim
:
468 image_mano_id
= image_dict
['uuid']
469 if return_on_error
== None:
470 return_on_error
= True
472 if image_dict
['location']:
473 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
475 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
477 image_mano_id
= images
[0]['uuid']
479 #create image in MANO DB
480 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
481 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
482 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
484 #temp_image_dict['location'] = image_dict.get('new_location') if image_dict['location'] is None
485 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
486 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
487 #create image at every vim
488 for vim_id
,vim
in vims
.iteritems():
489 image_created
="false"
491 image_db
= mydb
.get_rows(FROM
="datacenters_images", WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
492 #look at VIM if this image exist
494 if image_dict
['location'] is not None:
495 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
498 filter_dict
['name'] = image_dict
['universal_name']
499 if image_dict
.get('checksum') != None:
500 filter_dict
['checksum'] = image_dict
['checksum']
501 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
502 vim_images
= vim
.get_image_list(filter_dict
)
503 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
504 if len(vim_images
) > 1:
505 raise vimconn
.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict
)), HTTP_Conflict
)
506 elif len(vim_images
) == 0:
507 raise vimconn
.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict
)))
509 #logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
510 image_vim_id
= vim_images
[0]['id']
512 except vimconn
.vimconnNotFoundException
as e
:
513 #Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
515 #image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
516 if image_dict
['location']:
517 image_vim_id
= vim
.new_image(image_dict
)
518 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
521 #If we reach this point, then the image has image name, and optionally checksum, and could not be found
522 raise vimconn
.vimconnException(str(e
))
523 except vimconn
.vimconnException
as e
:
525 logger
.error("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
528 logger
.warn("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
530 except vimconn
.vimconnException
as e
:
532 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
534 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
537 #if we reach here, the image has been created or existed
539 #add new vim_id at datacenters_images
540 mydb
.new_row('datacenters_images', {'datacenter_id':vim_id
, 'image_id':image_mano_id
, 'vim_id': image_vim_id
, 'created':image_created
})
541 elif image_db
[0]["vim_id"]!=image_vim_id
:
542 #modify existing vim_id at datacenters_images
543 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
545 return image_vim_id
if only_create_at_vim
else image_mano_id
548 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
549 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
550 'ram':flavor_dict
.get('ram'),
551 'vcpus':flavor_dict
.get('vcpus'),
553 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
554 del flavor_dict
['extended']
555 if 'extended' in flavor_dict
:
556 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
558 #look if flavor exist
559 if only_create_at_vim
:
560 flavor_mano_id
= flavor_dict
['uuid']
561 if return_on_error
== None:
562 return_on_error
= True
564 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
566 flavor_mano_id
= flavors
[0]['uuid']
569 #create one by one the images of aditional disks
570 dev_image_list
=[] #list of images
571 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
573 for device
in flavor_dict
['extended'].get('devices',[]):
574 if "image" not in device
and "image name" not in device
:
577 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
578 image_dict
['universal_name']=device
.get('image name')
579 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
580 image_dict
['location']=device
.get('image')
581 #image_dict['new_location']=vnfc.get('image location')
582 image_dict
['checksum']=device
.get('image checksum')
583 image_metadata_dict
= device
.get('image metadata', None)
584 image_metadata_str
= None
585 if image_metadata_dict
!= None:
586 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
587 image_dict
['metadata']=image_metadata_str
588 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
589 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
590 dev_image_list
.append(image_id
)
592 temp_flavor_dict
['name'] = flavor_dict
['name']
593 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
594 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
595 flavor_mano_id
= content
596 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
597 #create flavor at every vim
598 if 'uuid' in flavor_dict
:
599 del flavor_dict
['uuid']
601 for vim_id
,vim
in vims
.items():
602 flavor_created
="false"
604 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors", WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
605 #look at VIM if this flavor exist SKIPPED
606 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
608 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
612 #Create the flavor in VIM
613 #Translate images at devices from MANO id to VIM id
615 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
616 #make a copy of original devices
619 for device
in flavor_dict
["extended"].get("devices",[]):
622 devices_original
.append(dev
)
623 if 'image' in device
:
625 if 'image metadata' in device
:
626 del device
['image metadata']
628 for index
in range(0,len(devices_original
)) :
629 device
=devices_original
[index
]
630 if "image" not in device
and "image name" not in device
:
632 disk_list
.append({'size': device
.get('size', default_volume_size
)})
635 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
636 image_dict
['universal_name']=device
.get('image name')
637 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
638 image_dict
['location']=device
.get('image')
639 #image_dict['new_location']=device.get('image location')
640 image_dict
['checksum']=device
.get('image checksum')
641 image_metadata_dict
= device
.get('image metadata', None)
642 image_metadata_str
= None
643 if image_metadata_dict
!= None:
644 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
645 image_dict
['metadata']=image_metadata_str
646 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
647 image_dict
["uuid"]=image_mano_id
648 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
650 #save disk information (image must be based on and size
651 disk_list
.append({'image_id': image_vim_id
, 'size': device
.get('size', default_volume_size
)})
653 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
656 #check that this vim_id exist in VIM, if not create
657 flavor_vim_id
=flavor_db
[0]["vim_id"]
659 vim
.get_flavor(flavor_vim_id
)
660 continue #flavor exist
661 except vimconn
.vimconnException
:
663 #create flavor at vim
664 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
667 flavor_vim_id
=vim
.get_flavor_id_from_data(flavor_dict
)
668 flavor_create
="false"
669 except vimconn
.vimconnException
as e
:
672 if not flavor_vim_id
:
673 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
674 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
675 flavor_created
="true"
676 except vimconn
.vimconnException
as e
:
678 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
680 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
683 #if reach here the flavor has been create or exist
684 if len(flavor_db
)==0:
685 #add new vim_id at datacenters_flavors
686 extended_devices_yaml
= None
687 if len(disk_list
) > 0:
688 extended_devices
= dict()
689 extended_devices
['disks'] = disk_list
690 extended_devices_yaml
= yaml
.safe_dump(extended_devices
,default_flow_style
=True,width
=256)
691 mydb
.new_row('datacenters_flavors',
692 {'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
, 'vim_id': flavor_vim_id
,
693 'created':flavor_created
,'extended': extended_devices_yaml
})
694 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
695 #modify existing vim_id at datacenters_flavors
696 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
698 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
701 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
704 # Step 1. Check the VNF descriptor
705 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
706 # Step 2. Check tenant exist
708 if tenant_id
!= "any":
709 check_tenant(mydb
, tenant_id
)
710 if "tenant_id" in vnf_descriptor
["vnf"]:
711 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
712 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
715 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
716 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
717 if global_config
["auto_push_VNF_to_VIMs"]:
718 vims
= get_vim(mydb
, tenant_id
)
720 # Step 4. Review the descriptor and add missing fields
721 #print vnf_descriptor
722 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
723 vnf_name
= vnf_descriptor
['vnf']['name']
724 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
725 if "physical" in vnf_descriptor
['vnf']:
726 del vnf_descriptor
['vnf']['physical']
727 #print vnf_descriptor
729 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
730 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
731 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
733 #For each VNFC, we add it to the VNFCDict and we create a flavor.
734 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
735 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
737 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
738 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
740 VNFCitem
["name"] = vnfc
['name']
741 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
743 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
746 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
747 myflavorDict
["description"] = VNFCitem
["description"]
748 myflavorDict
["ram"] = vnfc
.get("ram", 0)
749 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
750 myflavorDict
["disk"] = vnfc
.get("disk", 1)
751 myflavorDict
["extended"] = {}
753 devices
= vnfc
.get("devices")
755 myflavorDict
["extended"]["devices"] = devices
758 # 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
759 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
761 # Previous code has been commented
762 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
763 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
764 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
765 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
767 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
769 # print "Error creating flavor: unknown processor model. Rollback successful."
770 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
772 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
773 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
775 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
776 myflavorDict
['extended']['numas'] = vnfc
['numas']
780 # Step 6.2 New flavors are created in the VIM
781 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
783 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
784 VNFCitem
["flavor_id"] = flavor_id
785 VNFCDict
[vnfc
['name']] = VNFCitem
787 logger
.debug("Creating new images in the VIM for each VNFC")
788 # Step 6.3 New images are created in the VIM
789 #For each VNFC, we must create the appropriate image.
790 #This "for" loop might be integrated with the previous one
791 #In case this integration is made, the VNFCDict might become a VNFClist.
792 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
793 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
795 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
796 image_dict
['universal_name']=vnfc
.get('image name')
797 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
798 image_dict
['location']=vnfc
.get('VNFC image')
799 #image_dict['new_location']=vnfc.get('image location')
800 image_dict
['checksum']=vnfc
.get('image checksum')
801 image_metadata_dict
= vnfc
.get('image metadata', None)
802 image_metadata_str
= None
803 if image_metadata_dict
is not None:
804 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
805 image_dict
['metadata']=image_metadata_str
806 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
807 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
808 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
809 VNFCDict
[vnfc
['name']]["image_id"] = image_id
810 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
811 if vnfc
.get("boot-data"):
812 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
815 # Step 7. Storing the VNF descriptor in the repository
816 if "descriptor" not in vnf_descriptor
["vnf"]:
817 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
819 # Step 8. Adding the VNF to the NFVO DB
820 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
822 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
823 _
, message
= rollback(mydb
, vims
, rollback_list
)
824 if isinstance(e
, db_base_Exception
):
825 error_text
= "Exception at database"
826 elif isinstance(e
, KeyError):
827 error_text
= "KeyError exception "
828 e
.http_code
= HTTP_Internal_Server_Error
830 error_text
= "Exception at VIM"
831 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
832 #logger.error("start_scenario %s", error_text)
833 raise NfvoException(error_text
, e
.http_code
)
836 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
839 # Step 1. Check the VNF descriptor
840 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
841 # Step 2. Check tenant exist
843 if tenant_id
!= "any":
844 check_tenant(mydb
, tenant_id
)
845 if "tenant_id" in vnf_descriptor
["vnf"]:
846 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
847 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
850 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
851 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
852 if global_config
["auto_push_VNF_to_VIMs"]:
853 vims
= get_vim(mydb
, tenant_id
)
855 # Step 4. Review the descriptor and add missing fields
856 #print vnf_descriptor
857 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
858 vnf_name
= vnf_descriptor
['vnf']['name']
859 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
860 if "physical" in vnf_descriptor
['vnf']:
861 del vnf_descriptor
['vnf']['physical']
862 #print vnf_descriptor
864 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
865 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
866 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
868 #For each VNFC, we add it to the VNFCDict and we create a flavor.
869 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
870 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
872 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
873 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
875 VNFCitem
["name"] = vnfc
['name']
876 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
878 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
881 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
882 myflavorDict
["description"] = VNFCitem
["description"]
883 myflavorDict
["ram"] = vnfc
.get("ram", 0)
884 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
885 myflavorDict
["disk"] = vnfc
.get("disk", 1)
886 myflavorDict
["extended"] = {}
888 devices
= vnfc
.get("devices")
890 myflavorDict
["extended"]["devices"] = devices
893 # 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
894 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
896 # Previous code has been commented
897 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
898 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
899 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
900 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
902 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
904 # print "Error creating flavor: unknown processor model. Rollback successful."
905 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
907 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
908 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
910 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
911 myflavorDict
['extended']['numas'] = vnfc
['numas']
915 # Step 6.2 New flavors are created in the VIM
916 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
918 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
919 VNFCitem
["flavor_id"] = flavor_id
920 VNFCDict
[vnfc
['name']] = VNFCitem
922 logger
.debug("Creating new images in the VIM for each VNFC")
923 # Step 6.3 New images are created in the VIM
924 #For each VNFC, we must create the appropriate image.
925 #This "for" loop might be integrated with the previous one
926 #In case this integration is made, the VNFCDict might become a VNFClist.
927 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
928 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
930 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
931 image_dict
['universal_name']=vnfc
.get('image name')
932 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
933 image_dict
['location']=vnfc
.get('VNFC image')
934 #image_dict['new_location']=vnfc.get('image location')
935 image_dict
['checksum']=vnfc
.get('image checksum')
936 image_metadata_dict
= vnfc
.get('image metadata', None)
937 image_metadata_str
= None
938 if image_metadata_dict
is not None:
939 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
940 image_dict
['metadata']=image_metadata_str
941 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
942 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
943 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
944 VNFCDict
[vnfc
['name']]["image_id"] = image_id
945 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
946 if vnfc
.get("boot-data"):
947 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
949 # Step 7. Storing the VNF descriptor in the repository
950 if "descriptor" not in vnf_descriptor
["vnf"]:
951 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
953 # Step 8. Adding the VNF to the NFVO DB
954 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
956 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
957 _
, message
= rollback(mydb
, vims
, rollback_list
)
958 if isinstance(e
, db_base_Exception
):
959 error_text
= "Exception at database"
960 elif isinstance(e
, KeyError):
961 error_text
= "KeyError exception "
962 e
.http_code
= HTTP_Internal_Server_Error
964 error_text
= "Exception at VIM"
965 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
966 #logger.error("start_scenario %s", error_text)
967 raise NfvoException(error_text
, e
.http_code
)
970 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
971 #check valid tenant_id
972 check_tenant(mydb
, tenant_id
)
975 if tenant_id
!= "any":
976 where_or
["tenant_id"] = tenant_id
977 where_or
["public"] = True
978 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
981 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
982 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
983 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
984 data
={'vnf' : filtered_content
}
986 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
987 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description', 'boot_data'),
988 WHERE
={'vnfs.uuid': vnf_id
} )
990 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
991 # change boot_data into boot-data
993 if vm
.get("boot_data"):
994 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
997 data
['vnf']['VNFC'] = content
998 #TODO: GET all the information from a VNFC and include it in the output.
1001 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
1002 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
1003 WHERE
={'vnfs.uuid': vnf_id
} )
1004 data
['vnf']['nets'] = content
1006 #GET ip-profile for each net
1007 for net
in data
['vnf']['nets']:
1008 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1009 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1010 WHERE
={'net_id': net
["uuid"]} )
1011 if len(ipprofiles
)==1:
1012 net
["ip_profile"] = ipprofiles
[0]
1013 elif len(ipprofiles
)>1:
1014 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
1017 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1019 #GET External Interfaces
1020 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1021 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1022 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1023 WHERE
={'vnfs.uuid': vnf_id
},
1024 WHERE_NOT
={'interfaces.external_name': None} )
1026 data
['vnf']['external-connections'] = content
1031 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1032 # Check tenant exist
1033 if tenant_id
!= "any":
1034 check_tenant(mydb
, tenant_id
)
1035 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1036 vims
= get_vim(mydb
, tenant_id
)
1040 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1042 if tenant_id
!= "any":
1043 where_or
["tenant_id"] = tenant_id
1044 where_or
["public"] = True
1045 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1046 vnf_id
= vnf
["uuid"]
1048 # "Getting the list of flavors and tenants of the VNF"
1049 flavorList
= get_flavorlist(mydb
, vnf_id
)
1050 if len(flavorList
)==0:
1051 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1053 imageList
= get_imagelist(mydb
, vnf_id
)
1054 if len(imageList
)==0:
1055 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1057 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1059 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1062 for flavor
in flavorList
:
1063 #check if flavor is used by other vnf
1065 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1067 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1069 #flavor not used, must be deleted
1071 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
1072 for flavor_vim
in c
:
1073 if flavor_vim
["datacenter_id"] not in vims
:
1075 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
1077 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
1079 myvim
.delete_flavor(flavor_vim
["vim_id"])
1080 except vimconn
.vimconnNotFoundException
as e
:
1081 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
1082 except vimconn
.vimconnException
as e
:
1083 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1084 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1085 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
1086 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1087 mydb
.delete_row_by_id('flavors', flavor
)
1088 except db_base_Exception
as e
:
1089 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1090 undeletedItems
.append("flavor %s" % flavor
)
1093 for image
in imageList
:
1095 #check if image is used by other vnf
1096 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
1098 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1100 #image not used, must be deleted
1102 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1104 if image_vim
["datacenter_id"] not in vims
:
1106 if image_vim
['created']=='false': #skip this image because not created by openmano
1108 myvim
=vims
[ image_vim
["datacenter_id"] ]
1110 myvim
.delete_image(image_vim
["vim_id"])
1111 except vimconn
.vimconnNotFoundException
as e
:
1112 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1113 except vimconn
.vimconnException
as e
:
1114 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1115 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1116 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1117 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1118 mydb
.delete_row_by_id('images', image
)
1119 except db_base_Exception
as e
:
1120 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1121 undeletedItems
.append("image %s" % image
)
1123 return vnf_id
+ " " + vnf
["name"]
1125 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1128 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1129 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1133 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
1134 myvim
= vims
.values()[0]
1135 result
,servers
= myvim
.get_hosts_info()
1137 return result
, servers
1138 topology
= {'name':myvim
['name'] , 'servers': servers
}
1139 return result
, topology
1142 def get_hosts(mydb
, nfvo_tenant_id
):
1143 vims
= get_vim(mydb
, nfvo_tenant_id
)
1145 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
1147 #print "nfvo.datacenter_action() error. Several datacenters found"
1148 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1149 myvim
= vims
.values()[0]
1151 hosts
= myvim
.get_hosts()
1152 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1154 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1156 server
={'name':host
['name'], 'vms':[]}
1157 for vm
in host
['instances']:
1158 #get internal name and model
1160 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1161 WHERE
={'vim_vm_id':vm
['id']} )
1163 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1165 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1167 except db_base_Exception
as e
:
1168 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1169 datacenter
['Datacenters'][0]['servers'].append(server
)
1170 #return -400, "en construccion"
1172 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1174 except vimconn
.vimconnException
as e
:
1175 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1178 def new_scenario(mydb
, tenant_id
, topo
):
1180 # result, vims = get_vim(mydb, tenant_id)
1182 # return result, vims
1184 if tenant_id
!= "any":
1185 check_tenant(mydb
, tenant_id
)
1186 if "tenant_id" in topo
:
1187 if topo
["tenant_id"] != tenant_id
:
1188 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1193 #1.1: get VNFs and external_networks (other_nets).
1195 other_nets
={} #external_networks, bridge_networks and data_networkds
1196 nodes
= topo
['topology']['nodes']
1197 for k
in nodes
.keys():
1198 if nodes
[k
]['type'] == 'VNF':
1200 vnfs
[k
]['ifaces'] = {}
1201 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1202 other_nets
[k
] = nodes
[k
]
1203 other_nets
[k
]['external']=True
1204 elif nodes
[k
]['type'] == 'network':
1205 other_nets
[k
] = nodes
[k
]
1206 other_nets
[k
]['external']=False
1209 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1210 for name
,vnf
in vnfs
.items():
1212 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1214 error_pos
= "'topology':'nodes':'" + name
+ "'"
1216 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1217 where
['uuid'] = vnf
['vnf_id']
1218 if 'VNF model' in vnf
:
1219 error_text
+= " 'VNF model' " + vnf
['VNF model']
1220 where
['name'] = vnf
['VNF model']
1222 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
1224 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1230 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1232 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1233 vnf
['uuid']=vnf_db
[0]['uuid']
1234 vnf
['description']=vnf_db
[0]['description']
1235 #get external interfaces
1236 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1237 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1238 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1239 for ext_iface
in ext_ifaces
:
1240 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1242 #1.4 get list of connections
1243 conections
= topo
['topology']['connections']
1244 conections_list
= []
1245 conections_list_name
= []
1246 for k
in conections
.keys():
1247 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1248 ifaces_list
= conections
[k
]['nodes'].items()
1249 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1251 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1252 for k2
in conection_pair_list
:
1255 con_type
= conections
[k
].get("type", "link")
1256 if con_type
!= "link":
1258 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
1259 other_nets
[k
] = {'external': False}
1260 if conections
[k
].get("graph"):
1261 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1262 ifaces_list
.append( (k
, None) )
1265 if con_type
== "external_network":
1266 other_nets
[k
]['external'] = True
1267 if conections
[k
].get("model"):
1268 other_nets
[k
]["model"] = conections
[k
]["model"]
1270 other_nets
[k
]["model"] = k
1271 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1272 other_nets
[k
]["model"] = con_type
1274 conections_list_name
.append(k
)
1275 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)
1276 #print set(ifaces_list)
1277 #check valid VNF and iface names
1278 for iface
in ifaces_list
:
1279 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1280 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1281 str(k
), iface
[0]), HTTP_Not_Found
)
1282 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1283 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1284 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
1286 #1.5 unify connections from the pair list to a consolidated list
1288 while index
< len(conections_list
):
1290 while index2
< len(conections_list
):
1291 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1292 conections_list
[index
] |
= conections_list
[index2
]
1293 del conections_list
[index2
]
1294 del conections_list_name
[index2
]
1297 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1299 #for k in conections_list:
1304 #1.6 Delete non external nets
1305 # for k in other_nets.keys():
1306 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1307 # for con in conections_list:
1309 # for index in range(0,len(con)):
1310 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1311 # for index in delete_indexes:
1314 #1.7: Check external_ports are present at database table datacenter_nets
1315 for k
,net
in other_nets
.items():
1316 error_pos
= "'topology':'nodes':'" + k
+ "'"
1317 if net
['external']==False:
1318 if 'name' not in net
:
1320 if 'model' not in net
:
1321 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1322 if net
['model']=='bridge_net':
1323 net
['type']='bridge';
1324 elif net
['model']=='dataplane_net':
1327 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1329 #IF we do not want to check that external network exist at datacenter
1334 # if 'net_id' in net:
1335 # error_text += " 'net_id' " + net['net_id']
1336 # WHERE_['uuid'] = net['net_id']
1337 # if 'model' in net:
1338 # error_text += " 'model' " + net['model']
1339 # WHERE_['name'] = net['model']
1340 # if len(WHERE_) == 0:
1341 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1342 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1343 # FROM='datacenter_nets', WHERE=WHERE_ )
1345 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1347 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1348 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1350 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1351 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1352 # other_nets[k].update(net_db[0])
1355 net_nb
=0 #Number of nets
1356 for con
in conections_list
:
1357 #check if this is connected to a external net
1361 for index
in range(0,len(con
)):
1362 #check if this is connected to a external net
1363 for net_key
in other_nets
.keys():
1364 if con
[index
][0]==net_key
:
1365 if other_net_index
>=0:
1366 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1367 #print "nfvo.new_scenario " + error_text
1368 raise NfvoException(error_text
, HTTP_Bad_Request
)
1370 other_net_index
= index
1371 net_target
= net_key
1373 #print "other_net_index", other_net_index
1375 if other_net_index
>=0:
1376 del con
[other_net_index
]
1377 #IF we do not want to check that external network exist at datacenter
1378 if other_nets
[net_target
]['external'] :
1379 if "name" not in other_nets
[net_target
]:
1380 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1381 if other_nets
[net_target
]["type"] == "external_network":
1382 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1383 other_nets
[net_target
]["type"] = "data"
1385 other_nets
[net_target
]["type"] = "bridge"
1387 # if other_nets[net_target]['external'] :
1388 # 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
1389 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1390 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1391 # print "nfvo.new_scenario " + error_text
1392 # return -HTTP_Bad_Request, error_text
1395 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1398 net_type_bridge
=False
1400 net_target
= "__-__net"+str(net_nb
)
1401 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
1402 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1405 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1406 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1407 if iface_type
=='mgmt' or iface_type
=='bridge':
1408 net_type_bridge
= True
1410 net_type_data
= True
1411 if net_type_bridge
and net_type_data
:
1412 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1413 #print "nfvo.new_scenario " + error_text
1414 raise NfvoException(error_text
, HTTP_Bad_Request
)
1415 elif net_type_bridge
:
1418 type_
='data' if len(con
)>2 else 'ptp'
1419 net_list
[net_target
]['type'] = type_
1422 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1423 #print "nfvo.new_scenario " + error_text
1425 raise NfvoException(error_text
, HTTP_Bad_Request
)
1427 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1428 #1.8.1 obtain management net
1429 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1430 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1431 #1.8.2 check all interfaces from all vnfs
1433 add_mgmt_net
= False
1434 for vnf
in vnfs
.values():
1435 for iface
in vnf
['ifaces'].values():
1436 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1437 #iface not connected
1438 iface
['net_key'] = 'mgmt'
1440 if add_mgmt_net
and 'mgmt' not in net_list
:
1441 net_list
['mgmt']=mgmt_net
[0]
1442 net_list
['mgmt']['external']=True
1443 net_list
['mgmt']['graph']={'visible':False}
1445 net_list
.update(other_nets
)
1447 #print 'net_list', net_list
1452 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1453 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1454 'tenant_id':tenant_id
, 'name':topo
['name'],
1455 'description':topo
.get('description',topo
['name']),
1456 'public': topo
.get('public', False)
1462 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
1463 """ This creates a new scenario for version 0.2 and 0.3"""
1464 scenario
= scenario_dict
["scenario"]
1465 if tenant_id
!= "any":
1466 check_tenant(mydb
, tenant_id
)
1467 if "tenant_id" in scenario
:
1468 if scenario
["tenant_id"] != tenant_id
:
1469 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1470 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1471 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1475 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
1476 for name
,vnf
in scenario
["vnfs"].iteritems():
1478 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1480 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1482 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1483 where
['uuid'] = vnf
['vnf_id']
1484 if 'vnf_name' in vnf
:
1485 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1486 where
['name'] = vnf
['vnf_name']
1488 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1489 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
1494 if len(vnf_db
) == 0:
1495 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1496 elif len(vnf_db
) > 1:
1497 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1498 vnf
['uuid'] = vnf_db
[0]['uuid']
1499 vnf
['description'] = vnf_db
[0]['description']
1501 # get external interfaces
1502 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
1503 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1504 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name': None} )
1505 for ext_iface
in ext_ifaces
:
1506 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
1507 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1509 # 2: Insert net_key and ip_address at every vnf interface
1510 for net_name
, net
in scenario
["networks"].items():
1511 net_type_bridge
= False
1512 net_type_data
= False
1513 for iface_dict
in net
["interfaces"]:
1514 if version
== "0.2":
1515 temp_dict
= iface_dict
1517 elif version
== "0.3":
1518 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
1519 ip_address
= iface_dict
.get('ip_address', None)
1520 for vnf
, iface
in temp_dict
.items():
1521 if vnf
not in scenario
["vnfs"]:
1522 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
1524 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1525 raise NfvoException(error_text
, HTTP_Not_Found
)
1526 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1527 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
1528 .format(net_name
, iface
)
1529 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1530 raise NfvoException(error_text
, HTTP_Bad_Request
)
1531 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1532 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
1533 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1534 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1535 raise NfvoException(error_text
, HTTP_Bad_Request
)
1536 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1537 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
1538 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1539 if iface_type
== 'mgmt' or iface_type
== 'bridge':
1540 net_type_bridge
= True
1542 net_type_data
= True
1544 if net_type_bridge
and net_type_data
:
1545 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
1547 # logger.debug("nfvo.new_scenario " + error_text)
1548 raise NfvoException(error_text
, HTTP_Bad_Request
)
1549 elif net_type_bridge
:
1552 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
1554 if net
.get("implementation"): # for v0.3
1555 if type_
== "bridge" and net
["implementation"] == "underlay":
1556 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
1557 "'network':'{}'".format(net_name
)
1558 # logger.debug(error_text)
1559 raise NfvoException(error_text
, HTTP_Bad_Request
)
1560 elif type_
!= "bridge" and net
["implementation"] == "overlay":
1561 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
1562 "'network':'{}'".format(net_name
)
1563 # logger.debug(error_text)
1564 raise NfvoException(error_text
, HTTP_Bad_Request
)
1565 net
.pop("implementation")
1566 if "type" in net
and version
== "0.3": # for v0.3
1567 if type_
== "data" and net
["type"] == "e-line":
1568 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
1569 "'e-line' at 'network':'{}'".format(net_name
)
1570 # logger.debug(error_text)
1571 raise NfvoException(error_text
, HTTP_Bad_Request
)
1572 elif type_
== "ptp" and net
["type"] == "e-lan":
1576 net
['name'] = net_name
1577 net
['external'] = net
.get('external', False)
1579 # 3: insert at database
1580 scenario
["nets"] = scenario
["networks"]
1581 scenario
['tenant_id'] = tenant_id
1582 scenario_id
= mydb
.new_scenario(scenario
)
1586 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1587 data
["uuid"] = scenario_id
1588 data
["tenant_id"] = tenant_id
1589 c
= mydb
.edit_scenario( data
)
1593 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1594 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1595 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
1596 vims
= {datacenter_id
: myvim
}
1597 myvim_tenant
= myvim
['tenant_id']
1598 datacenter_name
= myvim
['name']
1602 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1603 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1604 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
1605 scenarioDict
['datacenter_id'] = datacenter_id
1606 #print '================scenarioDict======================='
1607 #print json.dumps(scenarioDict, indent=4)
1608 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1610 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
1611 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1613 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1614 auxNetDict
['scenario'] = {}
1616 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1617 for sce_net
in scenarioDict
['nets']:
1618 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1620 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1621 myNetName
= myNetName
[0:255] #limit length
1622 myNetType
= sce_net
['type']
1624 myNetDict
["name"] = myNetName
1625 myNetDict
["type"] = myNetType
1626 myNetDict
["tenant_id"] = myvim_tenant
1627 myNetIPProfile
= sce_net
.get('ip_profile', None)
1629 #We should use the dictionary as input parameter for new_network
1631 if not sce_net
["external"]:
1632 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1633 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1634 sce_net
['vim_id'] = network_id
1635 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1636 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1637 sce_net
["created"] = True
1639 if sce_net
['vim_id'] == None:
1640 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1641 _
, message
= rollback(mydb
, vims
, rollbackList
)
1642 logger
.error("nfvo.start_scenario: %s", error_text
)
1643 raise NfvoException(error_text
, HTTP_Bad_Request
)
1644 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1645 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1647 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1648 #For each vnf net, we create it and we add it to instanceNetlist.
1649 for sce_vnf
in scenarioDict
['vnfs']:
1650 for net
in sce_vnf
['nets']:
1651 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1653 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1654 myNetName
= myNetName
[0:255] #limit length
1655 myNetType
= net
['type']
1657 myNetDict
["name"] = myNetName
1658 myNetDict
["type"] = myNetType
1659 myNetDict
["tenant_id"] = myvim_tenant
1660 myNetIPProfile
= net
.get('ip_profile', None)
1663 #We should use the dictionary as input parameter for new_network
1664 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1665 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1666 net
['vim_id'] = network_id
1667 if sce_vnf
['uuid'] not in auxNetDict
:
1668 auxNetDict
[sce_vnf
['uuid']] = {}
1669 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1670 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1671 net
["created"] = True
1673 #print "auxNetDict:"
1674 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1676 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1677 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1679 for sce_vnf
in scenarioDict
['vnfs']:
1680 for vm
in sce_vnf
['vms']:
1683 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1684 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
1685 #myVMDict['description'] = vm['description']
1686 myVMDict
['description'] = myVMDict
['name'][0:99]
1688 myVMDict
['start'] = "no"
1689 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1690 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1692 #create image at vim in case it not exist
1693 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1694 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1695 vm
['vim_image_id'] = image_id
1697 #create flavor at vim in case it not exist
1698 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1699 if flavor_dict
['extended']!=None:
1700 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1701 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1702 vm
['vim_flavor_id'] = flavor_id
1705 myVMDict
['imageRef'] = vm
['vim_image_id']
1706 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1707 myVMDict
['networks'] = []
1708 for iface
in vm
['interfaces']:
1710 if iface
['type']=="data":
1711 netDict
['type'] = iface
['model']
1712 elif "model" in iface
and iface
["model"]!=None:
1713 netDict
['model']=iface
['model']
1714 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1715 #discover type of interface looking at flavor
1716 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1717 for flavor_iface
in numa
.get('interfaces',[]):
1718 if flavor_iface
.get('name') == iface
['internal_name']:
1719 if flavor_iface
['dedicated'] == 'yes':
1720 netDict
['type']="PF" #passthrough
1721 elif flavor_iface
['dedicated'] == 'no':
1722 netDict
['type']="VF" #siov
1723 elif flavor_iface
['dedicated'] == 'yes:sriov':
1724 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1725 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1727 netDict
["use"]=iface
['type']
1728 if netDict
["use"]=="data" and not netDict
.get("type"):
1729 #print "netDict", netDict
1730 #print "iface", iface
1731 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'])
1732 if flavor_dict
.get('extended')==None:
1733 raise NfvoException(e_text
+ "After database migration some information is not available. \
1734 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1736 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1737 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1738 netDict
["type"]="virtual"
1739 if "vpci" in iface
and iface
["vpci"] is not None:
1740 netDict
['vpci'] = iface
['vpci']
1741 if "mac" in iface
and iface
["mac"] is not None:
1742 netDict
['mac_address'] = iface
['mac']
1743 if "port-security" in iface
and iface
["port-security"] is not None:
1744 netDict
['port_security'] = iface
['port-security']
1745 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
1746 netDict
['floating_ip'] = iface
['floating-ip']
1747 netDict
['name'] = iface
['internal_name']
1748 if iface
['net_id'] is None:
1749 for vnf_iface
in sce_vnf
["interfaces"]:
1752 if vnf_iface
['interface_id']==iface
['uuid']:
1753 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1756 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1757 #skip bridge ifaces not connected to any net
1758 #if 'net_id' not in netDict or netDict['net_id']==None:
1760 myVMDict
['networks'].append(netDict
)
1761 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1762 #print myVMDict['name']
1763 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1764 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1765 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1766 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1767 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1768 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1769 vm
['vim_id'] = vm_id
1770 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1771 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1772 for net
in myVMDict
['networks']:
1774 for iface
in vm
['interfaces']:
1775 if net
["name"]==iface
["internal_name"]:
1776 iface
["vim_id"]=net
["vim_id"]
1779 logger
.debug("start scenario Deployment done")
1780 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1781 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1782 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1783 return mydb
.get_instance_scenario(instance_id
)
1785 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1786 _
, message
= rollback(mydb
, vims
, rollbackList
)
1787 if isinstance(e
, db_base_Exception
):
1788 error_text
= "Exception at database"
1790 error_text
= "Exception at VIM"
1791 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1792 #logger.error("start_scenario %s", error_text)
1793 raise NfvoException(error_text
, e
.http_code
)
1796 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
1797 ''' join the cloud config information into cloud_config_preserve.
1798 In case of conflict cloud_config_preserve preserves
1801 if not cloud_config_preserve
and not cloud_config
:
1804 new_cloud_config
= {"key-pairs":[], "users":[]}
1806 if cloud_config_preserve
:
1807 for key
in cloud_config_preserve
.get("key-pairs", () ):
1808 if key
not in new_cloud_config
["key-pairs"]:
1809 new_cloud_config
["key-pairs"].append(key
)
1811 for key
in cloud_config
.get("key-pairs", () ):
1812 if key
not in new_cloud_config
["key-pairs"]:
1813 new_cloud_config
["key-pairs"].append(key
)
1814 if not new_cloud_config
["key-pairs"]:
1815 del new_cloud_config
["key-pairs"]
1819 new_cloud_config
["users"] += cloud_config
.get("users", () )
1820 if cloud_config_preserve
:
1821 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
1822 index_to_delete
= []
1823 users
= new_cloud_config
.get("users", [])
1824 for index0
in range(0,len(users
)):
1825 if index0
in index_to_delete
:
1827 for index1
in range(index0
+1,len(users
)):
1828 if index1
in index_to_delete
:
1830 if users
[index0
]["name"] == users
[index1
]["name"]:
1831 index_to_delete
.append(index1
)
1832 for key
in users
[index1
].get("key-pairs",()):
1833 if "key-pairs" not in users
[index0
]:
1834 users
[index0
]["key-pairs"] = [key
]
1835 elif key
not in users
[index0
]["key-pairs"]:
1836 users
[index0
]["key-pairs"].append(key
)
1837 index_to_delete
.sort(reverse
=True)
1838 for index
in index_to_delete
:
1840 if not new_cloud_config
["users"]:
1841 del new_cloud_config
["users"]
1844 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
1845 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
1846 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
1847 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
1850 if cloud_config
and cloud_config
.get("user-data") != None:
1851 new_cloud_config
["user-data"] = cloud_config
["user-data"]
1852 if cloud_config_preserve
and cloud_config_preserve
.get("user-data") != None:
1853 new_cloud_config
["user-data"] = cloud_config_preserve
["user-data"]
1856 new_cloud_config
["config-files"] = []
1857 if cloud_config
and cloud_config
.get("config-files") != None:
1858 new_cloud_config
["config-files"] += cloud_config
["config-files"]
1859 if cloud_config_preserve
:
1860 for file in cloud_config_preserve
.get("config-files", ()):
1861 for index
in range(0, len(new_cloud_config
["config-files"])):
1862 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
1863 new_cloud_config
["config-files"][index
] = file
1866 new_cloud_config
["config-files"].append(file)
1867 if not new_cloud_config
["config-files"]:
1868 del new_cloud_config
["config-files"]
1869 return new_cloud_config
1872 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
1873 datacenter_id
= None
1874 datacenter_name
= None
1877 if datacenter_tenant_id
:
1878 thread_id
= datacenter_tenant_id
1879 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
1881 where_
={"td.nfvo_tenant_id": tenant_id
}
1882 if datacenter_id_name
:
1883 if utils
.check_valid_uuid(datacenter_id_name
):
1884 datacenter_id
= datacenter_id_name
1885 where_
["dt.datacenter_id"] = datacenter_id
1887 datacenter_name
= datacenter_id_name
1888 where_
["d.name"] = datacenter_name
1889 if datacenter_tenant_id
:
1890 where_
["dt.uuid"] = datacenter_tenant_id
1891 datacenters
= mydb
.get_rows(
1892 SELECT
=("dt.uuid as datacenter_tenant_id",),
1893 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
1894 "join datacenters as d on d.uuid=dt.datacenter_id",
1896 if len(datacenters
) > 1:
1897 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1899 thread_id
= datacenters
[0]["datacenter_tenant_id"]
1900 thread
= vim_threads
["running"].get(thread_id
)
1902 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1903 return thread_id
, thread
1904 except db_base_Exception
as e
:
1905 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
1907 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
1908 datacenter_id
= None
1909 datacenter_name
= None
1910 if datacenter_id_name
:
1911 if utils
.check_valid_uuid(datacenter_id_name
):
1912 datacenter_id
= datacenter_id_name
1914 datacenter_name
= datacenter_id_name
1915 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
1917 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1919 #print "nfvo.datacenter_action() error. Several datacenters found"
1920 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1921 return vims
.keys()[0], vims
.values()[0]
1925 '''Takes dict d and updates it with the values in dict u.'''
1926 '''It merges all depth levels'''
1927 for k
, v
in u
.iteritems():
1928 if isinstance(v
, collections
.Mapping
):
1929 r
= update(d
.get(k
, {}), v
)
1936 def create_instance(mydb
, tenant_id
, instance_dict
):
1937 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1938 # logger.debug("Creating instance...")
1939 scenario
= instance_dict
["scenario"]
1941 #find main datacenter
1943 myvim_threads_id
= {}
1946 datacenter
= instance_dict
.get("datacenter")
1947 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
1948 myvims
[default_datacenter_id
] = vim
1949 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
1950 tasks_to_launch
[myvim_threads_id
[default_datacenter_id
]] = []
1951 #myvim_tenant = myvim['tenant_id']
1952 # default_datacenter_name = vim['name']
1955 #print "Checking that the scenario exists and getting the scenario dictionary"
1956 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, default_datacenter_id
)
1958 #logger.debug(">>>>>>> Dictionaries before merging")
1959 #logger.debug(">>>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
1960 #logger.debug(">>>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
1962 scenarioDict
['datacenter_id'] = default_datacenter_id
1964 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1965 auxNetDict
['scenario'] = {}
1967 logger
.debug("Creating instance from scenario-dict:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)) #TODO remove
1968 instance_name
= instance_dict
["name"]
1969 instance_description
= instance_dict
.get("description")
1971 # 0 check correct parameters
1972 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1974 for scenario_net
in scenarioDict
['nets']:
1975 if net_name
== scenario_net
["name"]:
1979 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
), HTTP_Bad_Request
)
1980 if "sites" not in net_instance_desc
:
1981 net_instance_desc
["sites"] = [ {} ]
1982 site_without_datacenter_field
= False
1983 for site
in net_instance_desc
["sites"]:
1984 if site
.get("datacenter"):
1985 if site
["datacenter"] not in myvims
:
1986 #Add this datacenter to myvims
1987 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
1989 myvim_threads_id
[d
],_
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
1990 tasks_to_launch
[myvim_threads_id
[d
]] = []
1991 site
["datacenter"] = d
#change name to id
1993 if site_without_datacenter_field
:
1994 raise NfvoException("Found more than one entries without datacenter field at instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
1995 site_without_datacenter_field
= True
1996 site
["datacenter"] = default_datacenter_id
#change name to id
1998 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
2000 for scenario_vnf
in scenarioDict
['vnfs']:
2001 if vnf_name
== scenario_vnf
['name']:
2005 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
2006 if "datacenter" in vnf_instance_desc
:
2007 # Add this datacenter to myvims
2008 if vnf_instance_desc
["datacenter"] not in myvims
:
2009 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2011 myvim_threads_id
[d
],_
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2012 tasks_to_launch
[myvim_threads_id
[d
]] = []
2013 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
2015 #0.1 parse cloud-config parameters
2016 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
2018 #0.2 merge instance information into scenario
2019 #Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
2020 #However, this is not possible yet.
2021 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
2022 for scenario_net
in scenarioDict
['nets']:
2023 if net_name
== scenario_net
["name"]:
2024 if 'ip-profile' in net_instance_desc
:
2025 ipprofile
= net_instance_desc
['ip-profile']
2026 ipprofile
['subnet_address'] = ipprofile
.pop('subnet-address',None)
2027 ipprofile
['ip_version'] = ipprofile
.pop('ip-version','IPv4')
2028 ipprofile
['gateway_address'] = ipprofile
.pop('gateway-address',None)
2029 ipprofile
['dns_address'] = ipprofile
.pop('dns-address',None)
2030 if 'dhcp' in ipprofile
:
2031 ipprofile
['dhcp_start_address'] = ipprofile
['dhcp'].get('start-address',None)
2032 ipprofile
['dhcp_enabled'] = ipprofile
['dhcp'].get('enabled',True)
2033 ipprofile
['dhcp_count'] = ipprofile
['dhcp'].get('count',None)
2034 del ipprofile
['dhcp']
2035 if 'ip_profile' not in scenario_net
:
2036 scenario_net
['ip_profile'] = ipprofile
2038 update(scenario_net
['ip_profile'],ipprofile
)
2039 for interface
in net_instance_desc
.get('interfaces', () ):
2040 if 'ip_address' in interface
:
2041 for vnf
in scenarioDict
['vnfs']:
2042 if interface
['vnf'] == vnf
['name']:
2043 for vnf_interface
in vnf
['interfaces']:
2044 if interface
['vnf_interface'] == vnf_interface
['external_name']:
2045 vnf_interface
['ip_address']=interface
['ip_address']
2047 #logger.debug(">>>>>>>> Merged dictionary")
2048 logger
.debug("Creating instance scenario-dict MERGED:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False))
2051 # 1. Creating new nets (sce_nets) in the VIM"
2052 for sce_net
in scenarioDict
['nets']:
2053 sce_net
["vim_id_sites"]={}
2054 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
2055 net_name
= descriptor_net
.get("vim-network-name")
2056 auxNetDict
['scenario'][sce_net
['uuid']] = {}
2058 sites
= descriptor_net
.get("sites", [ {} ])
2060 if site
.get("datacenter"):
2061 vim
= myvims
[ site
["datacenter"] ]
2062 datacenter_id
= site
["datacenter"]
2063 myvim_thread_id
= myvim_threads_id
[ site
["datacenter"] ]
2065 vim
= myvims
[ default_datacenter_id
]
2066 datacenter_id
= default_datacenter_id
2067 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2068 net_type
= sce_net
['type']
2069 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
2070 if sce_net
["external"]:
2072 net_name
= sce_net
["name"]
2073 if "netmap-use" in site
or "netmap-create" in site
:
2074 create_network
= False
2075 lookfor_network
= False
2076 if "netmap-use" in site
:
2077 lookfor_network
= True
2078 if utils
.check_valid_uuid(site
["netmap-use"]):
2079 filter_text
= "scenario id '%s'" % site
["netmap-use"]
2080 lookfor_filter
["id"] = site
["netmap-use"]
2082 filter_text
= "scenario name '%s'" % site
["netmap-use"]
2083 lookfor_filter
["name"] = site
["netmap-use"]
2084 if "netmap-create" in site
:
2085 create_network
= True
2086 net_vim_name
= net_name
2087 if site
["netmap-create"]:
2088 net_vim_name
= site
["netmap-create"]
2090 elif sce_net
['vim_id'] != None:
2091 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
2092 create_network
= False
2093 lookfor_network
= True
2094 lookfor_filter
["id"] = sce_net
['vim_id']
2095 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
2096 #look for network at datacenter and return error
2098 #There is not a netmap, look at datacenter for a net with this name and create if not found
2099 create_network
= True
2100 lookfor_network
= True
2101 lookfor_filter
["name"] = sce_net
["name"]
2102 net_vim_name
= sce_net
["name"]
2103 filter_text
= "scenario name '%s'" % sce_net
["name"]
2106 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
2107 net_name
= net_name
[:255] #limit length
2108 net_vim_name
= net_name
2109 create_network
= True
2110 lookfor_network
= False
2113 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
2114 if len(vim_nets
) > 1:
2115 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2116 elif len(vim_nets
) == 0:
2117 if not create_network
:
2118 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2120 sce_net
["vim_id_sites"][datacenter_id
] = vim_nets
[0]['id']
2121 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
2122 create_network
= False
2124 #if network is not external
2125 task
= new_task("new-net", (net_vim_name
, net_type
, sce_net
.get('ip_profile',None)))
2126 task_id
= task
["id"]
2127 instance_tasks
[task_id
] = task
2128 tasks_to_launch
[myvim_thread_id
].append(task
)
2129 #network_id = vim.new_network(net_vim_name, net_type, sce_net.get('ip_profile',None))
2130 sce_net
["vim_id_sites"][datacenter_id
] = task_id
2131 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = task_id
2132 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':task_id
})
2133 sce_net
["created"] = True
2135 # 2. Creating new nets (vnf internal nets) in the VIM"
2136 #For each vnf net, we create it and we add it to instanceNetlist.
2137 for sce_vnf
in scenarioDict
['vnfs']:
2138 for net
in sce_vnf
['nets']:
2139 if sce_vnf
.get("datacenter"):
2140 vim
= myvims
[ sce_vnf
["datacenter"] ]
2141 datacenter_id
= sce_vnf
["datacenter"]
2142 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"]]
2144 vim
= myvims
[ default_datacenter_id
]
2145 datacenter_id
= default_datacenter_id
2146 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2147 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
2148 net_name
= descriptor_net
.get("name")
2150 net_name
= "%s.%s" %(instance_name
, net
["name"])
2151 net_name
= net_name
[:255] #limit length
2152 net_type
= net
['type']
2153 task
= new_task("new-net", (net_name
, net_type
, net
.get('ip_profile',None)))
2154 task_id
= task
["id"]
2155 instance_tasks
[task_id
] = task
2156 tasks_to_launch
[myvim_thread_id
].append(task
)
2157 # network_id = vim.new_network(net_name, net_type, net.get('ip_profile',None))
2158 net
['vim_id'] = task_id
2159 if sce_vnf
['uuid'] not in auxNetDict
:
2160 auxNetDict
[sce_vnf
['uuid']] = {}
2161 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = task_id
2162 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':task_id
})
2163 net
["created"] = True
2166 #print "auxNetDict:"
2167 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2169 # 3. Creating new vm instances in the VIM
2170 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2171 for sce_vnf
in scenarioDict
['vnfs']:
2172 if sce_vnf
.get("datacenter"):
2173 vim
= myvims
[ sce_vnf
["datacenter"] ]
2174 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"] ]
2175 datacenter_id
= sce_vnf
["datacenter"]
2177 vim
= myvims
[ default_datacenter_id
]
2178 myvim_thread_id
= myvim_threads_id
[ default_datacenter_id
]
2179 datacenter_id
= default_datacenter_id
2180 sce_vnf
["datacenter_id"] = datacenter_id
2182 for vm
in sce_vnf
['vms']:
2185 myVMDict
['name'] = "{}.{}.{}".format(instance_name
,sce_vnf
['name'],chr(96+i
))
2186 myVMDict
['description'] = myVMDict
['name'][0:99]
2188 # myVMDict['start'] = "no"
2189 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2190 #create image at vim in case it not exist
2191 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2192 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
2193 vm
['vim_image_id'] = image_id
2195 #create flavor at vim in case it not exist
2196 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2197 if flavor_dict
['extended']!=None:
2198 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2199 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
2201 #Obtain information for additional disks
2202 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',), WHERE
={'vim_id': flavor_id
})
2203 if not extended_flavor_dict
:
2204 raise NfvoException("flavor '{}' not found".format(flavor_id
), HTTP_Not_Found
)
2207 #extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
2208 myVMDict
['disks'] = None
2209 extended_info
= extended_flavor_dict
[0]['extended']
2210 if extended_info
!= None:
2211 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
2212 if 'disks' in extended_flavor_dict_yaml
:
2213 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
2215 vm
['vim_flavor_id'] = flavor_id
2216 myVMDict
['imageRef'] = vm
['vim_image_id']
2217 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2218 myVMDict
['networks'] = []
2220 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
2221 for iface
in vm
['interfaces']:
2223 if iface
['type']=="data":
2224 netDict
['type'] = iface
['model']
2225 elif "model" in iface
and iface
["model"]!=None:
2226 netDict
['model']=iface
['model']
2227 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2228 #discover type of interface looking at flavor
2229 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2230 for flavor_iface
in numa
.get('interfaces',[]):
2231 if flavor_iface
.get('name') == iface
['internal_name']:
2232 if flavor_iface
['dedicated'] == 'yes':
2233 netDict
['type']="PF" #passthrough
2234 elif flavor_iface
['dedicated'] == 'no':
2235 netDict
['type']="VF" #siov
2236 elif flavor_iface
['dedicated'] == 'yes:sriov':
2237 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2238 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2240 netDict
["use"]=iface
['type']
2241 if netDict
["use"]=="data" and not netDict
.get("type"):
2242 #print "netDict", netDict
2243 #print "iface", iface
2244 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'])
2245 if flavor_dict
.get('extended')==None:
2246 raise NfvoException(e_text
+ "After database migration some information is not available. \
2247 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
2249 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
2250 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2251 netDict
["type"]="virtual"
2252 if "vpci" in iface
and iface
["vpci"] is not None:
2253 netDict
['vpci'] = iface
['vpci']
2254 if "mac" in iface
and iface
["mac"] is not None:
2255 netDict
['mac_address'] = iface
['mac']
2256 if "port-security" in iface
and iface
["port-security"] is not None:
2257 netDict
['port_security'] = iface
['port-security']
2258 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2259 netDict
['floating_ip'] = iface
['floating-ip']
2260 netDict
['name'] = iface
['internal_name']
2261 if iface
['net_id'] is None:
2262 for vnf_iface
in sce_vnf
["interfaces"]:
2265 if vnf_iface
['interface_id']==iface
['uuid']:
2266 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
2269 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2270 if netDict
.get('net_id') and is_task_id(netDict
['net_id']):
2271 task_depends
[netDict
['net_id']] = instance_tasks
[netDict
['net_id']]
2272 #skip bridge ifaces not connected to any net
2273 #if 'net_id' not in netDict or netDict['net_id']==None:
2275 myVMDict
['networks'].append(netDict
)
2276 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2277 #print myVMDict['name']
2278 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2279 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2280 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2281 if vm
.get("boot_data"):
2282 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config
)
2284 cloud_config_vm
= cloud_config
2285 task
= new_task("new-vm", (myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2286 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2287 cloud_config_vm
, myVMDict
['disks']), depends
=task_depends
)
2288 instance_tasks
[task
["id"]] = task
2289 tasks_to_launch
[myvim_thread_id
].append(task
)
2291 vm
['vim_id'] = vm_id
2292 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2293 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2294 for net
in myVMDict
['networks']:
2296 for iface
in vm
['interfaces']:
2297 if net
["name"]==iface
["internal_name"]:
2298 iface
["vim_id"]=net
["vim_id"]
2300 scenarioDict
["datacenter2tenant"] = myvim_threads_id
2301 logger
.debug("create_instance Deployment done scenarioDict: %s",
2302 yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False) )
2303 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
2304 for myvim_thread_id
,task_list
in tasks_to_launch
.items():
2305 for task
in task_list
:
2306 vim_threads
["running"][myvim_thread_id
].insert_task(task
)
2308 global_instance_tasks
[instance_id
] = instance_tasks
2309 # Update database with those ended instance_tasks
2310 # for task in instance_tasks.values():
2311 # if task["status"] == "ok":
2312 # if task["name"] == "new-vm":
2313 # mydb.update_rows("instance_vms", UPDATE={"vim_vm_id": task["result"]},
2314 # WHERE={"vim_vm_id": task["id"]})
2315 # elif task["name"] == "new-net":
2316 # mydb.update_rows("instance_nets", UPDATE={"vim_net_id": task["result"]},
2317 # WHERE={"vim_net_id": task["id"]})
2318 return mydb
.get_instance_scenario(instance_id
)
2319 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
2320 message
= rollback(mydb
, myvims
, rollbackList
)
2321 if isinstance(e
, db_base_Exception
):
2322 error_text
= "database Exception"
2323 elif isinstance(e
, vimconn
.vimconnException
):
2324 error_text
= "VIM Exception"
2326 error_text
= "Exception"
2327 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2328 #logger.error("create_instance: %s", error_text)
2329 raise NfvoException(error_text
, e
.http_code
)
2332 def delete_instance(mydb
, tenant_id
, instance_id
):
2333 #print "Checking that the instance_id exists and getting the instance dictionary"
2334 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
2335 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2336 tenant_id
= instanceDict
["tenant_id"]
2337 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2339 #1. Delete from Database
2340 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
2349 for sce_vnf
in instanceDict
['vnfs']:
2350 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2351 if datacenter_key
not in myvims
:
2353 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2354 except NfvoException
as e
:
2355 logger
.error(str(e
))
2357 myvim_threads
[datacenter_key
] = myvim_thread
2358 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
2359 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2361 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
2362 sce_vnf
["datacenter_tenant_id"]))
2363 myvims
[datacenter_key
] = None
2365 myvims
[datacenter_key
] = vims
.values()[0]
2366 myvim
= myvims
[datacenter_key
]
2367 myvim_thread
= myvim_threads
[datacenter_key
]
2368 for vm
in sce_vnf
['vms']:
2370 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2374 if is_task_id(vm
['vim_vm_id']):
2375 task_id
= vm
['vim_vm_id']
2376 old_task
= global_instance_tasks
[instance_id
].get(task_id
)
2378 error_msg
+= "\n VM was scheduled for create, but task {} is not found".format(task_id
)
2381 if old_task
["status"] == "enqueued":
2382 old_task
["status"] = "deleted"
2383 elif old_task
["status"] == "error":
2385 elif old_task
["status"] == "processing":
2386 task
= new_task("del-vm", (task_id
, vm
["interfaces"]), depends
={task_id
: old_task
})
2388 task
= new_task("del-vm", (old_task
["result"], vm
["interfaces"]))
2390 task
= new_task("del-vm", (vm
['vim_vm_id'], vm
["interfaces"]) )
2392 myvim_thread
.insert_task(task
)
2393 except vimconn
.vimconnNotFoundException
as e
:
2394 error_msg
+="\n VM VIM_id={} not found at datacenter={}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2395 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
2396 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
2397 except vimconn
.vimconnException
as e
:
2398 error_msg
+="\n VM VIM_id={} at datacenter={} Error: {} {}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"], e
.http_code
, str(e
))
2399 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s",
2400 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
2404 for net
in instanceDict
['nets']:
2405 if not net
['created']:
2406 continue #skip not created nets
2407 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2408 if datacenter_key
not in myvims
:
2410 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2411 except NfvoException
as e
:
2412 logger
.error(str(e
))
2414 myvim_threads
[datacenter_key
] = myvim_thread
2415 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
2416 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2418 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2419 myvims
[datacenter_key
] = None
2421 myvims
[datacenter_key
] = vims
.values()[0]
2422 myvim
= myvims
[datacenter_key
]
2423 myvim_thread
= myvim_threads
[datacenter_key
]
2426 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
2430 if is_task_id(net
['vim_net_id']):
2431 task_id
= net
['vim_net_id']
2432 old_task
= global_instance_tasks
[instance_id
].get(task_id
)
2434 error_msg
+= "\n NET was scheduled for create, but task {} is not found".format(task_id
)
2437 if old_task
["status"] == "enqueued":
2438 old_task
["status"] = "deleted"
2439 elif old_task
["status"] == "error":
2441 elif old_task
["status"] == "processing":
2442 task
= new_task("del-net", task_id
, depends
={task_id
: old_task
})
2444 task
= new_task("del-net", old_task
["result"])
2446 task
= new_task("del-net", (net
['vim_net_id'], net
['sdn_net_id']))
2448 myvim_thread
.insert_task(task
)
2449 except vimconn
.vimconnNotFoundException
as e
:
2450 error_msg
+= "\n NET VIM_id={} not found at datacenter={}".format(net
['vim_net_id'], net
["datacenter_id"])
2451 logger
.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found",
2452 net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']))
2453 except vimconn
.vimconnException
as e
:
2454 error_msg
+= "\n NET VIM_id={} at datacenter={} Error: {} {}".format(net
['vim_net_id'],
2455 net
["datacenter_id"],
2456 e
.http_code
, str(e
))
2457 logger
.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s",
2458 e
.http_code
, net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']), str(e
))
2459 if len(error_msg
) > 0:
2460 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
2462 return 'instance ' + message
+ ' deleted'
2465 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
2466 '''Refreshes a scenario instance. It modifies instanceDict'''
2468 - 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
2471 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
2472 # #print "nfvo.refresh_instance begins"
2473 # #print json.dumps(instanceDict, indent=4)
2475 # #print "Getting the VIM URL and the VIM tenant_id"
2478 # # 1. Getting VIM vm and net list
2479 # vms_updated = [] #List of VM instance uuids in openmano that were updated
2482 # for sce_vnf in instanceDict['vnfs']:
2483 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
2484 # if datacenter_key not in vm_list:
2485 # vm_list[datacenter_key] = []
2486 # if datacenter_key not in myvims:
2487 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
2488 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
2489 # if len(vims) == 0:
2490 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
2491 # myvims[datacenter_key] = None
2493 # myvims[datacenter_key] = vims.values()[0]
2494 # for vm in sce_vnf['vms']:
2495 # vm_list[datacenter_key].append(vm['vim_vm_id'])
2496 # vms_notupdated.append(vm["uuid"])
2498 # nets_updated = [] #List of VM instance uuids in openmano that were updated
2499 # nets_notupdated=[]
2501 # for net in instanceDict['nets']:
2502 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
2503 # if datacenter_key not in net_list:
2504 # net_list[datacenter_key] = []
2505 # if datacenter_key not in myvims:
2506 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
2507 # datacenter_tenant_id=net["datacenter_tenant_id"])
2508 # if len(vims) == 0:
2509 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
2510 # myvims[datacenter_key] = None
2512 # myvims[datacenter_key] = vims.values()[0]
2514 # net_list[datacenter_key].append(net['vim_net_id'])
2515 # nets_notupdated.append(net["uuid"])
2517 # # 1. Getting the status of all VMs
2519 # for datacenter_key in myvims:
2520 # if not vm_list.get(datacenter_key):
2524 # if not myvims[datacenter_key]:
2525 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
2528 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
2530 # except vimconn.vimconnException as e:
2531 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
2532 # failed_message = str(e)
2534 # for vm in vm_list[datacenter_key]:
2535 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
2537 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
2538 # for sce_vnf in instanceDict['vnfs']:
2539 # for vm in sce_vnf['vms']:
2540 # vm_id = vm['vim_vm_id']
2541 # interfaces = vm_dict[vm_id].pop('interfaces', [])
2542 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
2543 # has_mgmt_iface = False
2544 # for iface in vm["interfaces"]:
2545 # if iface["type"]=="mgmt":
2546 # has_mgmt_iface = True
2547 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
2548 # vm_dict[vm_id]['status'] = "ACTIVE"
2549 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
2550 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
2551 # 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'):
2552 # vm['status'] = vm_dict[vm_id]['status']
2553 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
2554 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
2555 # # 2.1. Update in openmano DB the VMs whose status changed
2557 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
2558 # vms_notupdated.remove(vm["uuid"])
2560 # vms_updated.append(vm["uuid"])
2561 # except db_base_Exception as e:
2562 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
2563 # # 2.2. Update in openmano DB the interface VMs
2564 # for interface in interfaces:
2565 # #translate from vim_net_id to instance_net_id
2566 # network_id_list=[]
2567 # for net in instanceDict['nets']:
2568 # if net["vim_net_id"] == interface["vim_net_id"]:
2569 # network_id_list.append(net["uuid"])
2570 # if not network_id_list:
2572 # del interface["vim_net_id"]
2574 # for network_id in network_id_list:
2575 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
2576 # except db_base_Exception as e:
2577 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
2579 # # 3. Getting the status of all nets
2581 # for datacenter_key in myvims:
2582 # if not net_list.get(datacenter_key):
2585 # failed_message = ""
2586 # if not myvims[datacenter_key]:
2587 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
2590 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
2592 # except vimconn.vimconnException as e:
2593 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
2594 # failed_message = str(e)
2596 # for net in net_list[datacenter_key]:
2597 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
2599 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
2600 # # TODO: update nets inside a vnf
2601 # for net in instanceDict['nets']:
2602 # net_id = net['vim_net_id']
2603 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
2604 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
2605 # 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'):
2606 # net['status'] = net_dict[net_id]['status']
2607 # net['error_msg'] = net_dict[net_id].get('error_msg')
2608 # net['vim_info'] = net_dict[net_id].get('vim_info')
2609 # # 5.1. Update in openmano DB the nets whose status changed
2611 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
2612 # nets_notupdated.remove(net["uuid"])
2614 # nets_updated.append(net["uuid"])
2615 # except db_base_Exception as e:
2616 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
2618 # # Returns appropriate output
2619 # #print "nfvo.refresh_instance finishes"
2620 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
2621 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
2622 instance_id
= instanceDict
['uuid']
2623 # if len(vms_notupdated)+len(nets_notupdated)>0:
2624 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
2625 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
2627 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
2630 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
2631 #print "Checking that the instance_id exists and getting the instance dictionary"
2632 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
2633 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2635 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2636 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2638 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2639 myvim
= vims
.values()[0]
2642 input_vnfs
= action_dict
.pop("vnfs", [])
2643 input_vms
= action_dict
.pop("vms", [])
2644 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
2648 for sce_vnf
in instanceDict
['vnfs']:
2649 for vm
in sce_vnf
['vms']:
2650 if not action_over_all
:
2651 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
2652 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
2655 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
2656 if "console" in action_dict
:
2657 if not global_config
["http_console_proxy"]:
2658 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2659 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2660 protocol
=data
["protocol"],
2661 ip
= data
["server"],
2662 port
= data
["port"],
2663 suffix
= data
["suffix"]),
2667 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
2668 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
2669 "description": "this console is only reachable by local interface",
2674 #print "console data", data
2676 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
2677 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2678 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2679 protocol
=data
["protocol"],
2680 ip
= global_config
["http_console_host"],
2681 port
= console_thread
.port
,
2682 suffix
= data
["suffix"]),
2686 except NfvoException
as e
:
2687 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2691 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
2693 except vimconn
.vimconnException
as e
:
2694 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2697 if vm_ok
==0: #all goes wrong
2703 def create_or_use_console_proxy_thread(console_server
, console_port
):
2704 #look for a non-used port
2705 console_thread_key
= console_server
+ ":" + str(console_port
)
2706 if console_thread_key
in global_config
["console_thread"]:
2707 #global_config["console_thread"][console_thread_key].start_timeout()
2708 return global_config
["console_thread"][console_thread_key
]
2710 for port
in global_config
["console_port_iterator"]():
2711 #print "create_or_use_console_proxy_thread() port:", port
2712 if port
in global_config
["console_ports"]:
2715 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
2717 global_config
["console_thread"][console_thread_key
] = clithread
2718 global_config
["console_ports"][port
] = console_thread_key
2720 except cli
.ConsoleProxyExceptionPortUsed
as e
:
2721 #port used, try with onoher
2723 except cli
.ConsoleProxyException
as e
:
2724 raise NfvoException(str(e
), HTTP_Bad_Request
)
2725 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
2728 def check_tenant(mydb
, tenant_id
):
2729 '''check that tenant exists at database'''
2730 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
2732 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
2736 def new_tenant(mydb
, tenant_dict
):
2737 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
2741 def delete_tenant(mydb
, tenant
):
2742 #get nfvo_tenant info
2744 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
2745 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
2746 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
2749 def new_datacenter(mydb
, datacenter_descriptor
):
2750 if "config" in datacenter_descriptor
:
2751 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2752 #Check that datacenter-type is correct
2753 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
2756 module
= "vimconn_" + datacenter_type
2757 module_info
= imp
.find_module(module
)
2758 except (IOError, ImportError):
2759 if module_info
and module_info
[0]:
2760 file.close(module_info
[0])
2761 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
2763 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
2764 return datacenter_id
2767 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2768 #obtain data, check that only one exist
2769 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2771 datacenter_id
= datacenter
['uuid']
2772 where
={'uuid': datacenter
['uuid']}
2773 if "config" in datacenter_descriptor
:
2774 if datacenter_descriptor
['config']!=None:
2776 new_config_dict
= datacenter_descriptor
["config"]
2779 for k
in new_config_dict
:
2780 if new_config_dict
[k
]==None:
2783 config_text
= datacenter
.get("config")
2786 config_dict
= yaml
.load(config_text
)
2787 config_dict
.update(new_config_dict
)
2791 except Exception as e
:
2792 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
2793 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
2794 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
2795 return datacenter_id
2798 def delete_datacenter(mydb
, datacenter
):
2799 #get nfvo_tenant info
2800 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
2801 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
2802 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
2805 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):
2806 #get datacenter info
2807 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2808 datacenter_name
= myvim
["name"]
2810 create_vim_tenant
= True if not vim_tenant_id
and not vim_tenant_name
else False
2812 # get nfvo_tenant info
2813 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2814 if vim_tenant_name
==None:
2815 vim_tenant_name
=tenant_dict
['name']
2817 #check that this association does not exist before
2818 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2819 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2820 if len(tenants_datacenters
)>0:
2821 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
2823 vim_tenant_id_exist_atdb
=False
2824 if not create_vim_tenant
:
2825 where_
={"datacenter_id": datacenter_id
}
2826 if vim_tenant_id
!=None:
2827 where_
["vim_tenant_id"] = vim_tenant_id
2828 if vim_tenant_name
!=None:
2829 where_
["vim_tenant_name"] = vim_tenant_name
2830 #check if vim_tenant_id is already at database
2831 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
2832 if len(datacenter_tenants_dict
)>=1:
2833 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2834 vim_tenant_id_exist_atdb
=True
2835 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2837 datacenter_tenants_dict
= {}
2838 #insert at table datacenter_tenants
2839 else: #if vim_tenant_id==None:
2840 #create tenant at VIM if not provided
2842 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2843 except vimconn
.vimconnException
as e
:
2844 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
2845 datacenter_tenants_dict
= {}
2846 datacenter_tenants_dict
["created"]="true"
2848 #fill datacenter_tenants table
2849 if not vim_tenant_id_exist_atdb
:
2850 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2851 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2852 datacenter_tenants_dict
["user"] = vim_username
2853 datacenter_tenants_dict
["passwd"] = vim_password
2854 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2856 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
2857 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
2858 datacenter_tenants_dict
["uuid"] = id_
2860 #fill tenants_datacenters table
2861 tenants_datacenter_dict
["datacenter_tenant_id"]=datacenter_tenants_dict
["uuid"]
2862 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
2864 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_dict
['uuid'], datacenter_id
) # reload data
2865 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
2866 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, datacenter_name
, db
=db
, db_lock
=db_lock
, ovim
=ovim
)
2868 thread_id
= datacenter_tenants_dict
["uuid"]
2869 vim_threads
["running"][thread_id
] = new_thread
2870 return datacenter_id
2872 def edit_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=None, vim_tenant_name
=None, vim_username
=None, vim_password
=None, config
=None):
2873 #Obtain the data of this datacenter_tenant_id
2874 vim_data
= mydb
.get_rows(
2875 SELECT
=("datacenter_tenants.vim_tenant_name", "datacenter_tenants.vim_tenant_id", "datacenter_tenants.user",
2876 "datacenter_tenants.passwd", "datacenter_tenants.config"),
2877 FROM
="datacenter_tenants JOIN tenants_datacenters ON datacenter_tenants.uuid=tenants_datacenters.datacenter_tenant_id",
2878 WHERE
={"tenants_datacenters.nfvo_tenant_id": nfvo_tenant
,
2879 "tenants_datacenters.datacenter_id": datacenter_id
})
2881 logger
.debug(str(vim_data
))
2882 if len(vim_data
) < 1:
2883 raise NfvoException("Datacenter {} is not attached for tenant {}".format(datacenter_id
, nfvo_tenant
), HTTP_Conflict
)
2887 v
['config'] = yaml
.load(v
['config'])
2890 v
['vim_tenant_id'] = vim_tenant_id
2892 v
['vim_tenant_name'] = vim_tenant_name
2894 v
['user'] = vim_username
2896 v
['passwd'] = vim_password
2900 v
['config'].update(config
)
2902 logger
.debug(str(v
))
2903 deassociate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'])
2904 associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'], vim_tenant_name
=v
['vim_tenant_name'],
2905 vim_username
=v
['user'], vim_password
=v
['passwd'], config
=v
['config'])
2907 return datacenter_id
2909 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2910 #get datacenter info
2911 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2913 #get nfvo_tenant info
2914 if not tenant_id
or tenant_id
=="any":
2917 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
2918 tenant_uuid
= tenant_dict
['uuid']
2920 #check that this association exist before
2921 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
2923 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
2924 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2925 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
2926 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
2928 #delete this association
2929 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2931 #get vim_tenant info and deletes
2933 for tenant_datacenter_item
in tenant_datacenter_list
:
2934 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2935 #try to delete vim:tenant
2937 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2938 if vim_tenant_dict
['created']=='true':
2939 #delete tenant at VIM if created by NFVO
2941 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2942 except vimconn
.vimconnException
as e
:
2943 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
2944 logger
.warn(warning
)
2945 except db_base_Exception
as e
:
2946 logger
.error("Cannot delete datacenter_tenants " + str(e
))
2947 pass # the error will be caused because dependencies, vim_tenant can not be deleted
2948 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
2949 thread
= vim_threads
["running"][thread_id
]
2950 thread
.insert_task(new_task("exit", None))
2951 vim_threads
["deleting"][thread_id
] = thread
2952 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
2955 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
2957 #get datacenter info
2958 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2960 if 'net-update' in action_dict
:
2962 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2964 except vimconn
.vimconnException
as e
:
2965 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
2966 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2967 #update nets Change from VIM format to NFVO format
2970 net_nfvo
={'datacenter_id': datacenter_id
}
2971 net_nfvo
['name'] = net
['name']
2972 #net_nfvo['description']= net['name']
2973 net_nfvo
['vim_net_id'] = net
['id']
2974 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2975 net_nfvo
['shared'] = net
['shared']
2976 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2977 net_list
.append(net_nfvo
)
2978 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
2979 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
2981 elif 'net-edit' in action_dict
:
2982 net
= action_dict
['net-edit'].pop('net')
2983 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2984 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
2985 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2987 elif 'net-delete' in action_dict
:
2988 net
= action_dict
['net-deelte'].get('net')
2989 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2990 result
= mydb
.delete_row(FROM
='datacenter_nets',
2991 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2995 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
2998 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
2999 #get datacenter info
3000 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3002 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
3003 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
3004 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
3008 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
3009 #get datacenter info
3010 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3013 action_dict
= action_dict
["netmap"]
3014 if 'vim_id' in action_dict
:
3015 filter_dict
["id"] = action_dict
['vim_id']
3016 if 'vim_name' in action_dict
:
3017 filter_dict
["name"] = action_dict
['vim_name']
3019 filter_dict
["shared"] = True
3022 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
3023 except vimconn
.vimconnException
as e
:
3024 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
3025 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
3026 if len(vim_nets
)>1 and action_dict
:
3027 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
3028 elif len(vim_nets
)==0: # and action_dict:
3029 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
3031 for net
in vim_nets
:
3032 net_nfvo
={'datacenter_id': datacenter_id
}
3033 if action_dict
and "name" in action_dict
:
3034 net_nfvo
['name'] = action_dict
['name']
3036 net_nfvo
['name'] = net
['name']
3037 #net_nfvo['description']= net['name']
3038 net_nfvo
['vim_net_id'] = net
['id']
3039 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
3040 net_nfvo
['shared'] = net
['shared']
3041 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
3043 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
3044 net_nfvo
["status"] = "OK"
3045 net_nfvo
["uuid"] = net_id
3046 except db_base_Exception
as e
:
3050 net_nfvo
["status"] = "FAIL: " + str(e
)
3051 net_list
.append(net_nfvo
)
3055 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
3056 #get datacenter info
3057 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3060 if utils
.check_valid_uuid(name
):
3061 filter_dict
["id"] = name
3063 filter_dict
["name"] = name
3065 if item
=="networks":
3066 #filter_dict['tenant_id'] = myvim['tenant_id']
3067 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
3068 elif item
=="tenants":
3069 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
3070 elif item
== "images":
3071 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
3073 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3074 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
3075 if name
and len(content
)==1:
3076 return {item
[:-1]: content
[0]}
3077 elif name
and len(content
)==0:
3078 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
3081 return {item
: content
}
3082 except vimconn
.vimconnException
as e
:
3083 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
3084 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
3087 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
3088 #get datacenter info
3089 if tenant_id
== "any":
3092 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3094 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
3095 logger
.debug("vim_action_delete vim response: " + str(content
))
3096 items
= content
.values()[0]
3097 if type(items
)==list and len(items
)==0:
3098 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
3099 elif type(items
)==list and len(items
)>1:
3100 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
3101 else: # it is a dict
3102 item_id
= items
["id"]
3103 item_name
= str(items
.get("name"))
3106 if item
=="networks":
3107 content
= myvim
.delete_network(item_id
)
3108 elif item
=="tenants":
3109 content
= myvim
.delete_tenant(item_id
)
3110 elif item
== "images":
3111 content
= myvim
.delete_image(item_id
)
3113 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3114 except vimconn
.vimconnException
as e
:
3115 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
3116 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
3118 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
3121 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
3122 #get datacenter info
3123 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
3124 if tenant_id
== "any":
3126 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3128 if item
=="networks":
3129 net
= descriptor
["network"]
3130 net_name
= net
.pop("name")
3131 net_type
= net
.pop("type", "bridge")
3132 net_public
= net
.pop("shared", False)
3133 net_ipprofile
= net
.pop("ip_profile", None)
3134 net_vlan
= net
.pop("vlan", None)
3135 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
3136 elif item
=="tenants":
3137 tenant
= descriptor
["tenant"]
3138 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
3140 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3141 except vimconn
.vimconnException
as e
:
3142 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
3144 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
3146 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
3147 data
= ovim
.new_of_controller(sdn_controller
)
3148 logger
.debug('New SDN controller created with uuid {}'.format(data
))
3151 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
3152 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
3153 msg
= 'SDN controller {} updated'.format(data
)
3157 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
3158 if controller_id
== None:
3159 data
= ovim
.get_of_controllers()
3161 data
= ovim
.show_of_controller(controller_id
)
3163 msg
= 'SDN controller list:\n {}'.format(data
)
3167 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
3168 select_
= ('uuid', 'config')
3169 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
3170 for datacenter
in datacenters
:
3171 if datacenter
['config']:
3172 config
= yaml
.load(datacenter
['config'])
3173 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
3174 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), HTTP_Conflict
)
3176 data
= ovim
.delete_of_controller(controller_id
)
3177 msg
= 'SDN controller {} deleted'.format(data
)
3181 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
3182 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
3183 if len(controller
) < 1:
3184 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), HTTP_Not_Found
)
3187 sdn_controller_id
= yaml
.load(controller
[0]["config"])["sdn-controller"]
3189 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), HTTP_Bad_Request
)
3191 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
3192 switch_dpid
= sdn_controller
["dpid"]
3195 for compute_node
in sdn_port_mapping
:
3196 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
3198 element
["compute_node"] = compute_node
["compute_node"]
3199 for port
in compute_node
["ports"]:
3200 element
["pci"] = port
.get("pci")
3201 element
["switch_port"] = port
.get("switch_port")
3202 element
["switch_mac"] = port
.get("switch_mac")
3203 if not element
["pci"] or not (element
["switch_port"] or element
["switch_mac"]):
3204 raise NfvoException ("The mapping must contain the 'pci' and at least one of the elements 'switch_port'"
3205 " or 'switch_mac'", HTTP_Bad_Request
)
3206 maps
.append(dict(element
))
3208 return ovim
.set_of_port_mapping(maps
, ofc_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, region
=datacenter_id
)
3210 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
3211 maps
= ovim
.get_of_port_mappings(db_filter
={"region": datacenter_id
})
3214 "sdn-controller": None,
3215 "datacenter-id": datacenter_id
,
3217 "ports_mapping": list()
3220 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
3221 if datacenter
['config']:
3222 config
= yaml
.load(datacenter
['config'])
3223 if 'sdn-controller' in config
:
3224 controller_id
= config
['sdn-controller']
3225 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
3226 result
["sdn-controller"] = controller_id
3227 result
["dpid"] = sdn_controller
["dpid"]
3229 if result
["sdn-controller"] == None or result
["dpid"] == None:
3230 raise NfvoException("Not all SDN controller information for datacenter {} could be found: {}".format(datacenter_id
, result
),
3231 HTTP_Internal_Server_Error
)
3236 ports_correspondence_dict
= dict()
3238 if result
["sdn-controller"] != link
["ofc_id"]:
3239 raise NfvoException("The sdn-controller specified for different port mappings differ", HTTP_Internal_Server_Error
)
3240 if result
["dpid"] != link
["switch_dpid"]:
3241 raise NfvoException("The dpid specified for different port mappings differ", HTTP_Internal_Server_Error
)
3243 element
["pci"] = link
["pci"]
3244 if link
["switch_port"]:
3245 element
["switch_port"] = link
["switch_port"]
3246 if link
["switch_mac"]:
3247 element
["switch_mac"] = link
["switch_mac"]
3249 if not link
["compute_node"] in ports_correspondence_dict
:
3251 content
["compute_node"] = link
["compute_node"]
3252 content
["ports"] = list()
3253 ports_correspondence_dict
[link
["compute_node"]] = content
3255 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
3257 for key
in sorted(ports_correspondence_dict
):
3258 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
3262 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
3263 return ovim
.clear_of_port_mapping(db_filter
={"region":datacenter_id
})