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 ovim
as ovim_module
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': 'openmano.ovim',
119 'network_vlan_range_start': 1000,
120 'network_vlan_range_end': 4096,
121 'db_name': global_config
["db_ovim_name"],
122 'db_host': global_config
["db_ovim_host"],
123 'db_user': global_config
["db_ovim_user"],
124 'db_passwd': global_config
["db_ovim_passwd"],
127 'network_type': 'bridge',
128 #TODO: log_level_of should not be needed. To be modified in ovim
129 'log_level_of': 'DEBUG'
131 ovim
= ovim_module
.ovim(ovim_configuration
)
134 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'
135 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
136 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
137 'user','passwd', 'dt.config as dt_config', 'nfvo_tenant_id')
139 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
)
141 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
142 'datacenter_id': vim
.get('datacenter_id')}
144 extra
.update(yaml
.load(vim
["config"]))
145 if vim
.get('dt_config'):
146 extra
.update(yaml
.load(vim
["dt_config"]))
147 if vim
["type"] not in vimconn_imported
:
150 module
= "vimconn_" + vim
["type"]
151 module_info
= imp
.find_module(module
)
152 vim_conn
= imp
.load_module(vim
["type"], *module_info
)
153 vimconn_imported
[vim
["type"]] = vim_conn
154 except (IOError, ImportError) as e
:
155 if module_info
and module_info
[0]:
156 file.close(module_info
[0])
157 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
158 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
160 thread_id
= vim
['datacenter_tenant_id']
161 vim_persistent_info
[thread_id
] = {}
164 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
165 myvim
= vimconn_imported
[ vim
["type"] ].vimconnector(
166 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
167 tenant_id
=vim
['vim_tenant_id'], tenant_name
=vim
['vim_tenant_name'],
168 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
169 user
=vim
['user'], passwd
=vim
['passwd'],
170 config
=extra
, persistent_info
=vim_persistent_info
[thread_id
]
172 except Exception as e
:
173 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
174 thread_name
= get_non_used_vim_name(vim
['datacenter_name'], vim
['vim_tenant_id'], vim
['vim_tenant_name'], vim
['vim_tenant_id'])
175 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, vim
['datacenter_name'],
176 vim
['datacenter_tenant_id'], db
=db
, db_lock
=db_lock
, ovim
=ovim
)
178 vim_threads
["running"][thread_id
] = new_thread
179 except db_base_Exception
as e
:
180 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
184 global ovim
, global_config
187 for thread_id
,thread
in vim_threads
["running"].items():
188 thread
.insert_task(new_task("exit", None))
189 vim_threads
["deleting"][thread_id
] = thread
190 vim_threads
["running"] = {}
191 if global_config
and global_config
.get("console_thread"):
192 for thread
in global_config
["console_thread"]:
193 thread
.terminate
= True
196 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
198 return result, content:
199 <0, error_text upon error
200 nb_records, flavor_list on success
203 WHERE_dict
['vnf_id'] = vnf_id
204 if nfvo_tenant
is not None:
205 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
207 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
208 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
209 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
210 #print "get_flavor_list result:", result
211 #print "get_flavor_list content:", content
213 for flavor
in flavors
:
214 flavorList
.append(flavor
['flavor_id'])
218 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
220 return result, content:
221 <0, error_text upon error
222 nb_records, flavor_list on success
225 WHERE_dict
['vnf_id'] = vnf_id
226 if nfvo_tenant
is not None:
227 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
229 #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
230 images
= mydb
.get_rows(FROM
='vms join images on vms.image_id=images.uuid',SELECT
=('image_id',),WHERE
=WHERE_dict
)
233 imageList
.append(image
['image_id'])
237 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
238 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None):
239 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
240 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
241 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
242 raise exception upon error
245 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
246 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
247 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
248 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
249 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
250 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
251 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
252 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'
253 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
254 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
255 'user','passwd', 'dt.config as dt_config')
257 from_
= 'datacenters as d'
258 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
260 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
263 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
264 'datacenter_id': vim
.get('datacenter_id')}
266 extra
.update(yaml
.load(vim
["config"]))
267 if vim
.get('dt_config'):
268 extra
.update(yaml
.load(vim
["dt_config"]))
269 if vim
["type"] not in vimconn_imported
:
272 module
= "vimconn_" + vim
["type"]
273 module_info
= imp
.find_module(module
)
274 vim_conn
= imp
.load_module(vim
["type"], *module_info
)
275 vimconn_imported
[vim
["type"]] = vim_conn
276 except (IOError, ImportError) as e
:
277 if module_info
and module_info
[0]:
278 file.close(module_info
[0])
279 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
280 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
283 if 'datacenter_tenant_id' in vim
:
284 thread_id
= vim
["datacenter_tenant_id"]
285 if thread_id
not in vim_persistent_info
:
286 vim_persistent_info
[thread_id
] = {}
287 persistent_info
= vim_persistent_info
[thread_id
]
291 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
292 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
293 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
294 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
),
295 tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
296 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
297 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
298 config
=extra
, persistent_info
=persistent_info
300 except Exception as e
:
301 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
303 except db_base_Exception
as e
:
304 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
307 def rollback(mydb
, vims
, rollback_list
):
309 #delete things by reverse order
310 for i
in range(len(rollback_list
)-1, -1, -1):
311 item
= rollback_list
[i
]
312 if item
["where"]=="vim":
313 if item
["vim_id"] not in vims
:
315 vim
=vims
[ item
["vim_id"] ]
317 if item
["what"]=="image":
318 vim
.delete_image(item
["uuid"])
319 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
320 elif item
["what"]=="flavor":
321 vim
.delete_flavor(item
["uuid"])
322 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
323 elif item
["what"]=="network":
324 vim
.delete_network(item
["uuid"])
325 elif item
["what"]=="vm":
326 vim
.delete_vminstance(item
["uuid"])
327 except vimconn
.vimconnException
as e
:
328 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
329 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
330 except db_base_Exception
as e
:
331 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
335 if item
["what"]=="image":
336 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
337 elif item
["what"]=="flavor":
338 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
339 except db_base_Exception
as e
:
340 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
341 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
342 if len(undeleted_items
)==0:
343 return True," Rollback successful."
345 return False," Rollback fails to delete: " + str(undeleted_items
)
348 def check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1):
350 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
352 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
354 #dataplane interfaces
355 for numa
in vnfc
.get("numas",() ):
356 for interface
in numa
.get("interfaces",()):
357 if interface
["name"] in name_dict
:
359 "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
360 vnfc
["name"], interface
["name"]),
362 name_dict
[ interface
["name"] ] = "underlay"
364 for interface
in vnfc
.get("bridge-ifaces",() ):
365 if interface
["name"] in name_dict
:
367 "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
368 vnfc
["name"], interface
["name"]),
370 name_dict
[ interface
["name"] ] = "overlay"
371 vnfc_interfaces
[ vnfc
["name"] ] = name_dict
372 # check bood-data info
373 if "boot-data" in vnfc
:
374 # check that user-data is incompatible with users and config-files
375 if (vnfc
["boot-data"].get("users") or vnfc
["boot-data"].get("config-files")) and vnfc
["boot-data"].get("user-data"):
377 "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
380 #check if the info in external_connections matches with the one in the vnfcs
382 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
383 if external_connection
["name"] in name_list
:
385 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
386 external_connection
["name"]),
388 name_list
.append(external_connection
["name"])
389 if external_connection
["VNFC"] not in vnfc_interfaces
:
391 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
392 external_connection
["name"], external_connection
["VNFC"]),
395 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
397 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
398 external_connection
["name"],
399 external_connection
["local_iface_name"]),
402 #check if the info in internal_connections matches with the one in the vnfcs
404 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
405 if internal_connection
["name"] in name_list
:
407 "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection".format(
408 internal_connection
["name"]),
410 name_list
.append(internal_connection
["name"])
411 #We should check that internal-connections of type "ptp" have only 2 elements
413 if len(internal_connection
["elements"])>2 and (internal_connection
.get("type") == "ptp" or internal_connection
.get("type") == "e-line"):
415 "Error at 'vnf:internal-connections[name:'{}']:elements', size must be 2 for a '{}' type. Consider change it to '{}' type".format(
416 internal_connection
["name"],
417 'ptp' if vnf_descriptor_version
==1 else 'e-line',
418 'data' if vnf_descriptor_version
==1 else "e-lan"),
420 for port
in internal_connection
["elements"]:
422 iface
= port
["local_iface_name"]
423 if vnf
not in vnfc_interfaces
:
425 "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
426 internal_connection
["name"], vnf
),
428 if iface
not in vnfc_interfaces
[ vnf
]:
430 "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
431 internal_connection
["name"], iface
),
433 return -HTTP_Bad_Request
,
434 if vnf_descriptor_version
==1 and "type" not in internal_connection
:
435 if vnfc_interfaces
[vnf
][iface
] == "overlay":
436 internal_connection
["type"] = "bridge"
438 internal_connection
["type"] = "data"
439 if vnf_descriptor_version
==2 and "implementation" not in internal_connection
:
440 if vnfc_interfaces
[vnf
][iface
] == "overlay":
441 internal_connection
["implementation"] = "overlay"
443 internal_connection
["implementation"] = "underlay"
444 if (internal_connection
.get("type") == "data" or internal_connection
.get("type") == "ptp" or \
445 internal_connection
.get("implementation") == "underlay") and vnfc_interfaces
[vnf
][iface
] == "overlay":
447 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
448 internal_connection
["name"],
449 iface
, 'bridge' if vnf_descriptor_version
==1 else 'overlay',
450 'data' if vnf_descriptor_version
==1 else 'underlay'),
452 if (internal_connection
.get("type") == "bridge" or internal_connection
.get("implementation") == "overlay") and \
453 vnfc_interfaces
[vnf
][iface
] == "underlay":
455 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
456 internal_connection
["name"], iface
,
457 'data' if vnf_descriptor_version
==1 else 'underlay',
458 'bridge' if vnf_descriptor_version
==1 else 'overlay'),
462 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
464 if only_create_at_vim
:
465 image_mano_id
= image_dict
['uuid']
466 if return_on_error
== None:
467 return_on_error
= True
469 if image_dict
['location']:
470 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
472 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
474 image_mano_id
= images
[0]['uuid']
476 #create image in MANO DB
477 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
478 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
479 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
481 #temp_image_dict['location'] = image_dict.get('new_location') if image_dict['location'] is None
482 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
483 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
484 #create image at every vim
485 for vim_id
,vim
in vims
.iteritems():
486 image_created
="false"
488 image_db
= mydb
.get_rows(FROM
="datacenters_images", WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
489 #look at VIM if this image exist
491 if image_dict
['location'] is not None:
492 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
495 filter_dict
['name'] = image_dict
['universal_name']
496 if image_dict
.get('checksum') != None:
497 filter_dict
['checksum'] = image_dict
['checksum']
498 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
499 vim_images
= vim
.get_image_list(filter_dict
)
500 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
501 if len(vim_images
) > 1:
502 raise vimconn
.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict
)), HTTP_Conflict
)
503 elif len(vim_images
) == 0:
504 raise vimconn
.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict
)))
506 #logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
507 image_vim_id
= vim_images
[0]['id']
509 except vimconn
.vimconnNotFoundException
as e
:
510 #Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
512 #image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
513 if image_dict
['location']:
514 image_vim_id
= vim
.new_image(image_dict
)
515 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
518 #If we reach this point, then the image has image name, and optionally checksum, and could not be found
519 raise vimconn
.vimconnException(str(e
))
520 except vimconn
.vimconnException
as e
:
522 logger
.error("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
525 logger
.warn("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
527 except vimconn
.vimconnException
as e
:
529 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
531 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
534 #if we reach here, the image has been created or existed
536 #add new vim_id at datacenters_images
537 mydb
.new_row('datacenters_images', {'datacenter_id':vim_id
, 'image_id':image_mano_id
, 'vim_id': image_vim_id
, 'created':image_created
})
538 elif image_db
[0]["vim_id"]!=image_vim_id
:
539 #modify existing vim_id at datacenters_images
540 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
542 return image_vim_id
if only_create_at_vim
else image_mano_id
545 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
546 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
547 'ram':flavor_dict
.get('ram'),
548 'vcpus':flavor_dict
.get('vcpus'),
550 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
551 del flavor_dict
['extended']
552 if 'extended' in flavor_dict
:
553 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
555 #look if flavor exist
556 if only_create_at_vim
:
557 flavor_mano_id
= flavor_dict
['uuid']
558 if return_on_error
== None:
559 return_on_error
= True
561 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
563 flavor_mano_id
= flavors
[0]['uuid']
566 #create one by one the images of aditional disks
567 dev_image_list
=[] #list of images
568 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
570 for device
in flavor_dict
['extended'].get('devices',[]):
571 if "image" not in device
and "image name" not in device
:
574 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
575 image_dict
['universal_name']=device
.get('image name')
576 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
577 image_dict
['location']=device
.get('image')
578 #image_dict['new_location']=vnfc.get('image location')
579 image_dict
['checksum']=device
.get('image checksum')
580 image_metadata_dict
= device
.get('image metadata', None)
581 image_metadata_str
= None
582 if image_metadata_dict
!= None:
583 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
584 image_dict
['metadata']=image_metadata_str
585 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
586 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
587 dev_image_list
.append(image_id
)
589 temp_flavor_dict
['name'] = flavor_dict
['name']
590 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
591 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
592 flavor_mano_id
= content
593 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
594 #create flavor at every vim
595 if 'uuid' in flavor_dict
:
596 del flavor_dict
['uuid']
598 for vim_id
,vim
in vims
.items():
599 flavor_created
="false"
601 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors", WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
602 #look at VIM if this flavor exist SKIPPED
603 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
605 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
609 #Create the flavor in VIM
610 #Translate images at devices from MANO id to VIM id
612 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
613 #make a copy of original devices
616 for device
in flavor_dict
["extended"].get("devices",[]):
619 devices_original
.append(dev
)
620 if 'image' in device
:
622 if 'image metadata' in device
:
623 del device
['image metadata']
625 for index
in range(0,len(devices_original
)) :
626 device
=devices_original
[index
]
627 if "image" not in device
and "image name" not in device
:
629 disk_list
.append({'size': device
.get('size', default_volume_size
)})
632 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
633 image_dict
['universal_name']=device
.get('image name')
634 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
635 image_dict
['location']=device
.get('image')
636 #image_dict['new_location']=device.get('image location')
637 image_dict
['checksum']=device
.get('image checksum')
638 image_metadata_dict
= device
.get('image metadata', None)
639 image_metadata_str
= None
640 if image_metadata_dict
!= None:
641 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
642 image_dict
['metadata']=image_metadata_str
643 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
644 image_dict
["uuid"]=image_mano_id
645 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
647 #save disk information (image must be based on and size
648 disk_list
.append({'image_id': image_vim_id
, 'size': device
.get('size', default_volume_size
)})
650 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
653 #check that this vim_id exist in VIM, if not create
654 flavor_vim_id
=flavor_db
[0]["vim_id"]
656 vim
.get_flavor(flavor_vim_id
)
657 continue #flavor exist
658 except vimconn
.vimconnException
:
660 #create flavor at vim
661 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
664 flavor_vim_id
=vim
.get_flavor_id_from_data(flavor_dict
)
665 flavor_create
="false"
666 except vimconn
.vimconnException
as e
:
669 if not flavor_vim_id
:
670 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
671 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
672 flavor_created
="true"
673 except vimconn
.vimconnException
as e
:
675 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
677 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
680 #if reach here the flavor has been create or exist
681 if len(flavor_db
)==0:
682 #add new vim_id at datacenters_flavors
683 extended_devices_yaml
= None
684 if len(disk_list
) > 0:
685 extended_devices
= dict()
686 extended_devices
['disks'] = disk_list
687 extended_devices_yaml
= yaml
.safe_dump(extended_devices
,default_flow_style
=True,width
=256)
688 mydb
.new_row('datacenters_flavors',
689 {'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
, 'vim_id': flavor_vim_id
,
690 'created':flavor_created
,'extended': extended_devices_yaml
})
691 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
692 #modify existing vim_id at datacenters_flavors
693 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
695 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
698 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
701 # Step 1. Check the VNF descriptor
702 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
703 # Step 2. Check tenant exist
705 if tenant_id
!= "any":
706 check_tenant(mydb
, tenant_id
)
707 if "tenant_id" in vnf_descriptor
["vnf"]:
708 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
709 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
712 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
713 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
714 if global_config
["auto_push_VNF_to_VIMs"]:
715 vims
= get_vim(mydb
, tenant_id
)
717 # Step 4. Review the descriptor and add missing fields
718 #print vnf_descriptor
719 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
720 vnf_name
= vnf_descriptor
['vnf']['name']
721 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
722 if "physical" in vnf_descriptor
['vnf']:
723 del vnf_descriptor
['vnf']['physical']
724 #print vnf_descriptor
726 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
727 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
728 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
730 #For each VNFC, we add it to the VNFCDict and we create a flavor.
731 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
732 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
734 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
735 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
737 VNFCitem
["name"] = vnfc
['name']
738 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
740 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
743 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
744 myflavorDict
["description"] = VNFCitem
["description"]
745 myflavorDict
["ram"] = vnfc
.get("ram", 0)
746 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
747 myflavorDict
["disk"] = vnfc
.get("disk", 1)
748 myflavorDict
["extended"] = {}
750 devices
= vnfc
.get("devices")
752 myflavorDict
["extended"]["devices"] = devices
755 # 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
756 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
758 # Previous code has been commented
759 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
760 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
761 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
762 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
764 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
766 # print "Error creating flavor: unknown processor model. Rollback successful."
767 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
769 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
770 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
772 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
773 myflavorDict
['extended']['numas'] = vnfc
['numas']
777 # Step 6.2 New flavors are created in the VIM
778 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
780 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
781 VNFCitem
["flavor_id"] = flavor_id
782 VNFCDict
[vnfc
['name']] = VNFCitem
784 logger
.debug("Creating new images in the VIM for each VNFC")
785 # Step 6.3 New images are created in the VIM
786 #For each VNFC, we must create the appropriate image.
787 #This "for" loop might be integrated with the previous one
788 #In case this integration is made, the VNFCDict might become a VNFClist.
789 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
790 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
792 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
793 image_dict
['universal_name']=vnfc
.get('image name')
794 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
795 image_dict
['location']=vnfc
.get('VNFC image')
796 #image_dict['new_location']=vnfc.get('image location')
797 image_dict
['checksum']=vnfc
.get('image checksum')
798 image_metadata_dict
= vnfc
.get('image metadata', None)
799 image_metadata_str
= None
800 if image_metadata_dict
is not None:
801 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
802 image_dict
['metadata']=image_metadata_str
803 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
804 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
805 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
806 VNFCDict
[vnfc
['name']]["image_id"] = image_id
807 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
808 if vnfc
.get("boot-data"):
809 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
812 # Step 7. Storing the VNF descriptor in the repository
813 if "descriptor" not in vnf_descriptor
["vnf"]:
814 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
816 # Step 8. Adding the VNF to the NFVO DB
817 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
819 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
820 _
, message
= rollback(mydb
, vims
, rollback_list
)
821 if isinstance(e
, db_base_Exception
):
822 error_text
= "Exception at database"
823 elif isinstance(e
, KeyError):
824 error_text
= "KeyError exception "
825 e
.http_code
= HTTP_Internal_Server_Error
827 error_text
= "Exception at VIM"
828 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
829 #logger.error("start_scenario %s", error_text)
830 raise NfvoException(error_text
, e
.http_code
)
833 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
836 # Step 1. Check the VNF descriptor
837 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
838 # Step 2. Check tenant exist
840 if tenant_id
!= "any":
841 check_tenant(mydb
, tenant_id
)
842 if "tenant_id" in vnf_descriptor
["vnf"]:
843 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
844 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
847 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
848 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
849 if global_config
["auto_push_VNF_to_VIMs"]:
850 vims
= get_vim(mydb
, tenant_id
)
852 # Step 4. Review the descriptor and add missing fields
853 #print vnf_descriptor
854 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
855 vnf_name
= vnf_descriptor
['vnf']['name']
856 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
857 if "physical" in vnf_descriptor
['vnf']:
858 del vnf_descriptor
['vnf']['physical']
859 #print vnf_descriptor
861 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
862 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
863 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
865 #For each VNFC, we add it to the VNFCDict and we create a flavor.
866 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
867 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
869 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
870 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
872 VNFCitem
["name"] = vnfc
['name']
873 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
875 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
878 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
879 myflavorDict
["description"] = VNFCitem
["description"]
880 myflavorDict
["ram"] = vnfc
.get("ram", 0)
881 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
882 myflavorDict
["disk"] = vnfc
.get("disk", 1)
883 myflavorDict
["extended"] = {}
885 devices
= vnfc
.get("devices")
887 myflavorDict
["extended"]["devices"] = devices
890 # 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
891 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
893 # Previous code has been commented
894 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
895 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
896 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
897 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
899 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
901 # print "Error creating flavor: unknown processor model. Rollback successful."
902 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
904 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
905 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
907 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
908 myflavorDict
['extended']['numas'] = vnfc
['numas']
912 # Step 6.2 New flavors are created in the VIM
913 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
915 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
916 VNFCitem
["flavor_id"] = flavor_id
917 VNFCDict
[vnfc
['name']] = VNFCitem
919 logger
.debug("Creating new images in the VIM for each VNFC")
920 # Step 6.3 New images are created in the VIM
921 #For each VNFC, we must create the appropriate image.
922 #This "for" loop might be integrated with the previous one
923 #In case this integration is made, the VNFCDict might become a VNFClist.
924 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
925 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
927 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
928 image_dict
['universal_name']=vnfc
.get('image name')
929 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
930 image_dict
['location']=vnfc
.get('VNFC image')
931 #image_dict['new_location']=vnfc.get('image location')
932 image_dict
['checksum']=vnfc
.get('image checksum')
933 image_metadata_dict
= vnfc
.get('image metadata', None)
934 image_metadata_str
= None
935 if image_metadata_dict
is not None:
936 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
937 image_dict
['metadata']=image_metadata_str
938 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
939 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
940 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
941 VNFCDict
[vnfc
['name']]["image_id"] = image_id
942 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
943 if vnfc
.get("boot-data"):
944 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
946 # Step 7. Storing the VNF descriptor in the repository
947 if "descriptor" not in vnf_descriptor
["vnf"]:
948 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
950 # Step 8. Adding the VNF to the NFVO DB
951 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
953 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
954 _
, message
= rollback(mydb
, vims
, rollback_list
)
955 if isinstance(e
, db_base_Exception
):
956 error_text
= "Exception at database"
957 elif isinstance(e
, KeyError):
958 error_text
= "KeyError exception "
959 e
.http_code
= HTTP_Internal_Server_Error
961 error_text
= "Exception at VIM"
962 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
963 #logger.error("start_scenario %s", error_text)
964 raise NfvoException(error_text
, e
.http_code
)
967 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
968 #check valid tenant_id
969 check_tenant(mydb
, tenant_id
)
972 if tenant_id
!= "any":
973 where_or
["tenant_id"] = tenant_id
974 where_or
["public"] = True
975 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
978 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
979 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
980 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
981 data
={'vnf' : filtered_content
}
983 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
984 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description', 'boot_data'),
985 WHERE
={'vnfs.uuid': vnf_id
} )
987 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
988 # change boot_data into boot-data
990 if vm
.get("boot_data"):
991 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
994 data
['vnf']['VNFC'] = content
995 #TODO: GET all the information from a VNFC and include it in the output.
998 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
999 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
1000 WHERE
={'vnfs.uuid': vnf_id
} )
1001 data
['vnf']['nets'] = content
1003 #GET ip-profile for each net
1004 for net
in data
['vnf']['nets']:
1005 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1006 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1007 WHERE
={'net_id': net
["uuid"]} )
1008 if len(ipprofiles
)==1:
1009 net
["ip_profile"] = ipprofiles
[0]
1010 elif len(ipprofiles
)>1:
1011 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
1014 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1016 #GET External Interfaces
1017 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1018 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1019 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1020 WHERE
={'vnfs.uuid': vnf_id
},
1021 WHERE_NOT
={'interfaces.external_name': None} )
1023 data
['vnf']['external-connections'] = content
1028 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1029 # Check tenant exist
1030 if tenant_id
!= "any":
1031 check_tenant(mydb
, tenant_id
)
1032 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1033 vims
= get_vim(mydb
, tenant_id
)
1037 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1039 if tenant_id
!= "any":
1040 where_or
["tenant_id"] = tenant_id
1041 where_or
["public"] = True
1042 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1043 vnf_id
= vnf
["uuid"]
1045 # "Getting the list of flavors and tenants of the VNF"
1046 flavorList
= get_flavorlist(mydb
, vnf_id
)
1047 if len(flavorList
)==0:
1048 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1050 imageList
= get_imagelist(mydb
, vnf_id
)
1051 if len(imageList
)==0:
1052 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1054 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1056 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1059 for flavor
in flavorList
:
1060 #check if flavor is used by other vnf
1062 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1064 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1066 #flavor not used, must be deleted
1068 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
1069 for flavor_vim
in c
:
1070 if flavor_vim
["datacenter_id"] not in vims
:
1072 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
1074 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
1076 myvim
.delete_flavor(flavor_vim
["vim_id"])
1077 except vimconn
.vimconnNotFoundException
as e
:
1078 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
1079 except vimconn
.vimconnException
as e
:
1080 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1081 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1082 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
1083 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1084 mydb
.delete_row_by_id('flavors', flavor
)
1085 except db_base_Exception
as e
:
1086 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1087 undeletedItems
.append("flavor %s" % flavor
)
1090 for image
in imageList
:
1092 #check if image is used by other vnf
1093 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
1095 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1097 #image not used, must be deleted
1099 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1101 if image_vim
["datacenter_id"] not in vims
:
1103 if image_vim
['created']=='false': #skip this image because not created by openmano
1105 myvim
=vims
[ image_vim
["datacenter_id"] ]
1107 myvim
.delete_image(image_vim
["vim_id"])
1108 except vimconn
.vimconnNotFoundException
as e
:
1109 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1110 except vimconn
.vimconnException
as e
:
1111 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1112 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1113 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1114 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1115 mydb
.delete_row_by_id('images', image
)
1116 except db_base_Exception
as e
:
1117 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1118 undeletedItems
.append("image %s" % image
)
1120 return vnf_id
+ " " + vnf
["name"]
1122 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1125 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1126 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1130 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
1131 myvim
= vims
.values()[0]
1132 result
,servers
= myvim
.get_hosts_info()
1134 return result
, servers
1135 topology
= {'name':myvim
['name'] , 'servers': servers
}
1136 return result
, topology
1139 def get_hosts(mydb
, nfvo_tenant_id
):
1140 vims
= get_vim(mydb
, nfvo_tenant_id
)
1142 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
1144 #print "nfvo.datacenter_action() error. Several datacenters found"
1145 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1146 myvim
= vims
.values()[0]
1148 hosts
= myvim
.get_hosts()
1149 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1151 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1153 server
={'name':host
['name'], 'vms':[]}
1154 for vm
in host
['instances']:
1155 #get internal name and model
1157 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1158 WHERE
={'vim_vm_id':vm
['id']} )
1160 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1162 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1164 except db_base_Exception
as e
:
1165 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1166 datacenter
['Datacenters'][0]['servers'].append(server
)
1167 #return -400, "en construccion"
1169 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1171 except vimconn
.vimconnException
as e
:
1172 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1175 def new_scenario(mydb
, tenant_id
, topo
):
1177 # result, vims = get_vim(mydb, tenant_id)
1179 # return result, vims
1181 if tenant_id
!= "any":
1182 check_tenant(mydb
, tenant_id
)
1183 if "tenant_id" in topo
:
1184 if topo
["tenant_id"] != tenant_id
:
1185 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1190 #1.1: get VNFs and external_networks (other_nets).
1192 other_nets
={} #external_networks, bridge_networks and data_networkds
1193 nodes
= topo
['topology']['nodes']
1194 for k
in nodes
.keys():
1195 if nodes
[k
]['type'] == 'VNF':
1197 vnfs
[k
]['ifaces'] = {}
1198 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1199 other_nets
[k
] = nodes
[k
]
1200 other_nets
[k
]['external']=True
1201 elif nodes
[k
]['type'] == 'network':
1202 other_nets
[k
] = nodes
[k
]
1203 other_nets
[k
]['external']=False
1206 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1207 for name
,vnf
in vnfs
.items():
1209 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1211 error_pos
= "'topology':'nodes':'" + name
+ "'"
1213 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1214 where
['uuid'] = vnf
['vnf_id']
1215 if 'VNF model' in vnf
:
1216 error_text
+= " 'VNF model' " + vnf
['VNF model']
1217 where
['name'] = vnf
['VNF model']
1219 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
1221 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1227 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1229 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1230 vnf
['uuid']=vnf_db
[0]['uuid']
1231 vnf
['description']=vnf_db
[0]['description']
1232 #get external interfaces
1233 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1234 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1235 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1236 for ext_iface
in ext_ifaces
:
1237 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1239 #1.4 get list of connections
1240 conections
= topo
['topology']['connections']
1241 conections_list
= []
1242 conections_list_name
= []
1243 for k
in conections
.keys():
1244 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1245 ifaces_list
= conections
[k
]['nodes'].items()
1246 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1248 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1249 for k2
in conection_pair_list
:
1252 con_type
= conections
[k
].get("type", "link")
1253 if con_type
!= "link":
1255 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
1256 other_nets
[k
] = {'external': False}
1257 if conections
[k
].get("graph"):
1258 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1259 ifaces_list
.append( (k
, None) )
1262 if con_type
== "external_network":
1263 other_nets
[k
]['external'] = True
1264 if conections
[k
].get("model"):
1265 other_nets
[k
]["model"] = conections
[k
]["model"]
1267 other_nets
[k
]["model"] = k
1268 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1269 other_nets
[k
]["model"] = con_type
1271 conections_list_name
.append(k
)
1272 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)
1273 #print set(ifaces_list)
1274 #check valid VNF and iface names
1275 for iface
in ifaces_list
:
1276 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1277 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1278 str(k
), iface
[0]), HTTP_Not_Found
)
1279 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1280 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1281 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
1283 #1.5 unify connections from the pair list to a consolidated list
1285 while index
< len(conections_list
):
1287 while index2
< len(conections_list
):
1288 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1289 conections_list
[index
] |
= conections_list
[index2
]
1290 del conections_list
[index2
]
1291 del conections_list_name
[index2
]
1294 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1296 #for k in conections_list:
1301 #1.6 Delete non external nets
1302 # for k in other_nets.keys():
1303 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1304 # for con in conections_list:
1306 # for index in range(0,len(con)):
1307 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1308 # for index in delete_indexes:
1311 #1.7: Check external_ports are present at database table datacenter_nets
1312 for k
,net
in other_nets
.items():
1313 error_pos
= "'topology':'nodes':'" + k
+ "'"
1314 if net
['external']==False:
1315 if 'name' not in net
:
1317 if 'model' not in net
:
1318 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1319 if net
['model']=='bridge_net':
1320 net
['type']='bridge';
1321 elif net
['model']=='dataplane_net':
1324 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1326 #IF we do not want to check that external network exist at datacenter
1331 # if 'net_id' in net:
1332 # error_text += " 'net_id' " + net['net_id']
1333 # WHERE_['uuid'] = net['net_id']
1334 # if 'model' in net:
1335 # error_text += " 'model' " + net['model']
1336 # WHERE_['name'] = net['model']
1337 # if len(WHERE_) == 0:
1338 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1339 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1340 # FROM='datacenter_nets', WHERE=WHERE_ )
1342 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1344 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1345 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1347 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1348 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1349 # other_nets[k].update(net_db[0])
1352 net_nb
=0 #Number of nets
1353 for con
in conections_list
:
1354 #check if this is connected to a external net
1358 for index
in range(0,len(con
)):
1359 #check if this is connected to a external net
1360 for net_key
in other_nets
.keys():
1361 if con
[index
][0]==net_key
:
1362 if other_net_index
>=0:
1363 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1364 #print "nfvo.new_scenario " + error_text
1365 raise NfvoException(error_text
, HTTP_Bad_Request
)
1367 other_net_index
= index
1368 net_target
= net_key
1370 #print "other_net_index", other_net_index
1372 if other_net_index
>=0:
1373 del con
[other_net_index
]
1374 #IF we do not want to check that external network exist at datacenter
1375 if other_nets
[net_target
]['external'] :
1376 if "name" not in other_nets
[net_target
]:
1377 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1378 if other_nets
[net_target
]["type"] == "external_network":
1379 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1380 other_nets
[net_target
]["type"] = "data"
1382 other_nets
[net_target
]["type"] = "bridge"
1384 # if other_nets[net_target]['external'] :
1385 # 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
1386 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1387 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1388 # print "nfvo.new_scenario " + error_text
1389 # return -HTTP_Bad_Request, error_text
1392 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1395 net_type_bridge
=False
1397 net_target
= "__-__net"+str(net_nb
)
1398 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
1399 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1402 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1403 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1404 if iface_type
=='mgmt' or iface_type
=='bridge':
1405 net_type_bridge
= True
1407 net_type_data
= True
1408 if net_type_bridge
and net_type_data
:
1409 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1410 #print "nfvo.new_scenario " + error_text
1411 raise NfvoException(error_text
, HTTP_Bad_Request
)
1412 elif net_type_bridge
:
1415 type_
='data' if len(con
)>2 else 'ptp'
1416 net_list
[net_target
]['type'] = type_
1419 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1420 #print "nfvo.new_scenario " + error_text
1422 raise NfvoException(error_text
, HTTP_Bad_Request
)
1424 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1425 #1.8.1 obtain management net
1426 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1427 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1428 #1.8.2 check all interfaces from all vnfs
1430 add_mgmt_net
= False
1431 for vnf
in vnfs
.values():
1432 for iface
in vnf
['ifaces'].values():
1433 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1434 #iface not connected
1435 iface
['net_key'] = 'mgmt'
1437 if add_mgmt_net
and 'mgmt' not in net_list
:
1438 net_list
['mgmt']=mgmt_net
[0]
1439 net_list
['mgmt']['external']=True
1440 net_list
['mgmt']['graph']={'visible':False}
1442 net_list
.update(other_nets
)
1444 #print 'net_list', net_list
1449 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1450 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1451 'tenant_id':tenant_id
, 'name':topo
['name'],
1452 'description':topo
.get('description',topo
['name']),
1453 'public': topo
.get('public', False)
1459 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
1460 """ This creates a new scenario for version 0.2 and 0.3"""
1461 scenario
= scenario_dict
["scenario"]
1462 if tenant_id
!= "any":
1463 check_tenant(mydb
, tenant_id
)
1464 if "tenant_id" in scenario
:
1465 if scenario
["tenant_id"] != tenant_id
:
1466 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1467 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1468 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1472 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
1473 for name
,vnf
in scenario
["vnfs"].iteritems():
1475 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1477 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1479 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1480 where
['uuid'] = vnf
['vnf_id']
1481 if 'vnf_name' in vnf
:
1482 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1483 where
['name'] = vnf
['vnf_name']
1485 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1486 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
1491 if len(vnf_db
) == 0:
1492 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1493 elif len(vnf_db
) > 1:
1494 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1495 vnf
['uuid'] = vnf_db
[0]['uuid']
1496 vnf
['description'] = vnf_db
[0]['description']
1498 # get external interfaces
1499 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
1500 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1501 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name': None} )
1502 for ext_iface
in ext_ifaces
:
1503 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
1504 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1506 # 2: Insert net_key and ip_address at every vnf interface
1507 for net_name
, net
in scenario
["networks"].items():
1508 net_type_bridge
= False
1509 net_type_data
= False
1510 for iface_dict
in net
["interfaces"]:
1511 if version
== "0.2":
1512 temp_dict
= iface_dict
1514 elif version
== "0.3":
1515 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
1516 ip_address
= iface_dict
.get('ip_address', None)
1517 for vnf
, iface
in temp_dict
.items():
1518 if vnf
not in scenario
["vnfs"]:
1519 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
1521 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1522 raise NfvoException(error_text
, HTTP_Not_Found
)
1523 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1524 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
1525 .format(net_name
, iface
)
1526 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1527 raise NfvoException(error_text
, HTTP_Bad_Request
)
1528 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1529 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
1530 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1531 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1532 raise NfvoException(error_text
, HTTP_Bad_Request
)
1533 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1534 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
1535 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1536 if iface_type
== 'mgmt' or iface_type
== 'bridge':
1537 net_type_bridge
= True
1539 net_type_data
= True
1541 if net_type_bridge
and net_type_data
:
1542 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
1544 # logger.debug("nfvo.new_scenario " + error_text)
1545 raise NfvoException(error_text
, HTTP_Bad_Request
)
1546 elif net_type_bridge
:
1549 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
1551 if net
.get("implementation"): # for v0.3
1552 if type_
== "bridge" and net
["implementation"] == "underlay":
1553 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
1554 "'network':'{}'".format(net_name
)
1555 # logger.debug(error_text)
1556 raise NfvoException(error_text
, HTTP_Bad_Request
)
1557 elif type_
!= "bridge" and net
["implementation"] == "overlay":
1558 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
1559 "'network':'{}'".format(net_name
)
1560 # logger.debug(error_text)
1561 raise NfvoException(error_text
, HTTP_Bad_Request
)
1562 net
.pop("implementation")
1563 if "type" in net
and version
== "0.3": # for v0.3
1564 if type_
== "data" and net
["type"] == "e-line":
1565 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
1566 "'e-line' at 'network':'{}'".format(net_name
)
1567 # logger.debug(error_text)
1568 raise NfvoException(error_text
, HTTP_Bad_Request
)
1569 elif type_
== "ptp" and net
["type"] == "e-lan":
1573 net
['name'] = net_name
1574 net
['external'] = net
.get('external', False)
1576 # 3: insert at database
1577 scenario
["nets"] = scenario
["networks"]
1578 scenario
['tenant_id'] = tenant_id
1579 scenario_id
= mydb
.new_scenario(scenario
)
1583 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1584 data
["uuid"] = scenario_id
1585 data
["tenant_id"] = tenant_id
1586 c
= mydb
.edit_scenario( data
)
1590 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1591 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1592 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
1593 vims
= {datacenter_id
: myvim
}
1594 myvim_tenant
= myvim
['tenant_id']
1595 datacenter_name
= myvim
['name']
1599 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1600 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1601 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
1602 scenarioDict
['datacenter_id'] = datacenter_id
1603 #print '================scenarioDict======================='
1604 #print json.dumps(scenarioDict, indent=4)
1605 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1607 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
1608 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1610 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1611 auxNetDict
['scenario'] = {}
1613 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1614 for sce_net
in scenarioDict
['nets']:
1615 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1617 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1618 myNetName
= myNetName
[0:255] #limit length
1619 myNetType
= sce_net
['type']
1621 myNetDict
["name"] = myNetName
1622 myNetDict
["type"] = myNetType
1623 myNetDict
["tenant_id"] = myvim_tenant
1624 myNetIPProfile
= sce_net
.get('ip_profile', None)
1626 #We should use the dictionary as input parameter for new_network
1628 if not sce_net
["external"]:
1629 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1630 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1631 sce_net
['vim_id'] = network_id
1632 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1633 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1634 sce_net
["created"] = True
1636 if sce_net
['vim_id'] == None:
1637 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1638 _
, message
= rollback(mydb
, vims
, rollbackList
)
1639 logger
.error("nfvo.start_scenario: %s", error_text
)
1640 raise NfvoException(error_text
, HTTP_Bad_Request
)
1641 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1642 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1644 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1645 #For each vnf net, we create it and we add it to instanceNetlist.
1646 for sce_vnf
in scenarioDict
['vnfs']:
1647 for net
in sce_vnf
['nets']:
1648 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1650 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1651 myNetName
= myNetName
[0:255] #limit length
1652 myNetType
= net
['type']
1654 myNetDict
["name"] = myNetName
1655 myNetDict
["type"] = myNetType
1656 myNetDict
["tenant_id"] = myvim_tenant
1657 myNetIPProfile
= net
.get('ip_profile', None)
1660 #We should use the dictionary as input parameter for new_network
1661 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1662 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1663 net
['vim_id'] = network_id
1664 if sce_vnf
['uuid'] not in auxNetDict
:
1665 auxNetDict
[sce_vnf
['uuid']] = {}
1666 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1667 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1668 net
["created"] = True
1670 #print "auxNetDict:"
1671 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1673 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1674 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1676 for sce_vnf
in scenarioDict
['vnfs']:
1677 for vm
in sce_vnf
['vms']:
1680 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1681 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
1682 #myVMDict['description'] = vm['description']
1683 myVMDict
['description'] = myVMDict
['name'][0:99]
1685 myVMDict
['start'] = "no"
1686 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1687 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1689 #create image at vim in case it not exist
1690 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1691 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1692 vm
['vim_image_id'] = image_id
1694 #create flavor at vim in case it not exist
1695 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1696 if flavor_dict
['extended']!=None:
1697 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1698 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1699 vm
['vim_flavor_id'] = flavor_id
1702 myVMDict
['imageRef'] = vm
['vim_image_id']
1703 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1704 myVMDict
['networks'] = []
1705 for iface
in vm
['interfaces']:
1707 if iface
['type']=="data":
1708 netDict
['type'] = iface
['model']
1709 elif "model" in iface
and iface
["model"]!=None:
1710 netDict
['model']=iface
['model']
1711 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1712 #discover type of interface looking at flavor
1713 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1714 for flavor_iface
in numa
.get('interfaces',[]):
1715 if flavor_iface
.get('name') == iface
['internal_name']:
1716 if flavor_iface
['dedicated'] == 'yes':
1717 netDict
['type']="PF" #passthrough
1718 elif flavor_iface
['dedicated'] == 'no':
1719 netDict
['type']="VF" #siov
1720 elif flavor_iface
['dedicated'] == 'yes:sriov':
1721 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1722 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1724 netDict
["use"]=iface
['type']
1725 if netDict
["use"]=="data" and not netDict
.get("type"):
1726 #print "netDict", netDict
1727 #print "iface", iface
1728 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'])
1729 if flavor_dict
.get('extended')==None:
1730 raise NfvoException(e_text
+ "After database migration some information is not available. \
1731 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1733 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1734 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1735 netDict
["type"]="virtual"
1736 if "vpci" in iface
and iface
["vpci"] is not None:
1737 netDict
['vpci'] = iface
['vpci']
1738 if "mac" in iface
and iface
["mac"] is not None:
1739 netDict
['mac_address'] = iface
['mac']
1740 if "port-security" in iface
and iface
["port-security"] is not None:
1741 netDict
['port_security'] = iface
['port-security']
1742 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
1743 netDict
['floating_ip'] = iface
['floating-ip']
1744 netDict
['name'] = iface
['internal_name']
1745 if iface
['net_id'] is None:
1746 for vnf_iface
in sce_vnf
["interfaces"]:
1749 if vnf_iface
['interface_id']==iface
['uuid']:
1750 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1753 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1754 #skip bridge ifaces not connected to any net
1755 #if 'net_id' not in netDict or netDict['net_id']==None:
1757 myVMDict
['networks'].append(netDict
)
1758 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1759 #print myVMDict['name']
1760 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1761 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1762 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1763 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1764 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1765 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1766 vm
['vim_id'] = vm_id
1767 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1768 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1769 for net
in myVMDict
['networks']:
1771 for iface
in vm
['interfaces']:
1772 if net
["name"]==iface
["internal_name"]:
1773 iface
["vim_id"]=net
["vim_id"]
1776 logger
.debug("start scenario Deployment done")
1777 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1778 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1779 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1780 return mydb
.get_instance_scenario(instance_id
)
1782 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1783 _
, message
= rollback(mydb
, vims
, rollbackList
)
1784 if isinstance(e
, db_base_Exception
):
1785 error_text
= "Exception at database"
1787 error_text
= "Exception at VIM"
1788 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1789 #logger.error("start_scenario %s", error_text)
1790 raise NfvoException(error_text
, e
.http_code
)
1793 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
1794 ''' join the cloud config information into cloud_config_preserve.
1795 In case of conflict cloud_config_preserve preserves
1798 if not cloud_config_preserve
and not cloud_config
:
1801 new_cloud_config
= {"key-pairs":[], "users":[]}
1803 if cloud_config_preserve
:
1804 for key
in cloud_config_preserve
.get("key-pairs", () ):
1805 if key
not in new_cloud_config
["key-pairs"]:
1806 new_cloud_config
["key-pairs"].append(key
)
1808 for key
in cloud_config
.get("key-pairs", () ):
1809 if key
not in new_cloud_config
["key-pairs"]:
1810 new_cloud_config
["key-pairs"].append(key
)
1811 if not new_cloud_config
["key-pairs"]:
1812 del new_cloud_config
["key-pairs"]
1816 new_cloud_config
["users"] += cloud_config
.get("users", () )
1817 if cloud_config_preserve
:
1818 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
1819 index_to_delete
= []
1820 users
= new_cloud_config
.get("users", [])
1821 for index0
in range(0,len(users
)):
1822 if index0
in index_to_delete
:
1824 for index1
in range(index0
+1,len(users
)):
1825 if index1
in index_to_delete
:
1827 if users
[index0
]["name"] == users
[index1
]["name"]:
1828 index_to_delete
.append(index1
)
1829 for key
in users
[index1
].get("key-pairs",()):
1830 if "key-pairs" not in users
[index0
]:
1831 users
[index0
]["key-pairs"] = [key
]
1832 elif key
not in users
[index0
]["key-pairs"]:
1833 users
[index0
]["key-pairs"].append(key
)
1834 index_to_delete
.sort(reverse
=True)
1835 for index
in index_to_delete
:
1837 if not new_cloud_config
["users"]:
1838 del new_cloud_config
["users"]
1841 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
1842 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
1843 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
1844 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
1847 if cloud_config
and cloud_config
.get("user-data") != None:
1848 new_cloud_config
["user-data"] = cloud_config
["user-data"]
1849 if cloud_config_preserve
and cloud_config_preserve
.get("user-data") != None:
1850 new_cloud_config
["user-data"] = cloud_config_preserve
["user-data"]
1853 new_cloud_config
["config-files"] = []
1854 if cloud_config
and cloud_config
.get("config-files") != None:
1855 new_cloud_config
["config-files"] += cloud_config
["config-files"]
1856 if cloud_config_preserve
:
1857 for file in cloud_config_preserve
.get("config-files", ()):
1858 for index
in range(0, len(new_cloud_config
["config-files"])):
1859 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
1860 new_cloud_config
["config-files"][index
] = file
1863 new_cloud_config
["config-files"].append(file)
1864 if not new_cloud_config
["config-files"]:
1865 del new_cloud_config
["config-files"]
1866 return new_cloud_config
1869 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
1870 datacenter_id
= None
1871 datacenter_name
= None
1874 if datacenter_tenant_id
:
1875 thread_id
= datacenter_tenant_id
1876 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
1878 where_
={"td.nfvo_tenant_id": tenant_id
}
1879 if datacenter_id_name
:
1880 if utils
.check_valid_uuid(datacenter_id_name
):
1881 datacenter_id
= datacenter_id_name
1882 where_
["dt.datacenter_id"] = datacenter_id
1884 datacenter_name
= datacenter_id_name
1885 where_
["d.name"] = datacenter_name
1886 if datacenter_tenant_id
:
1887 where_
["dt.uuid"] = datacenter_tenant_id
1888 datacenters
= mydb
.get_rows(
1889 SELECT
=("dt.uuid as datacenter_tenant_id",),
1890 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
1891 "join datacenters as d on d.uuid=dt.datacenter_id",
1893 if len(datacenters
) > 1:
1894 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1896 thread_id
= datacenters
[0]["datacenter_tenant_id"]
1897 thread
= vim_threads
["running"].get(thread_id
)
1899 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1900 return thread_id
, thread
1901 except db_base_Exception
as e
:
1902 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
1904 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
1905 datacenter_id
= None
1906 datacenter_name
= None
1907 if datacenter_id_name
:
1908 if utils
.check_valid_uuid(datacenter_id_name
):
1909 datacenter_id
= datacenter_id_name
1911 datacenter_name
= datacenter_id_name
1912 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
1914 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1916 #print "nfvo.datacenter_action() error. Several datacenters found"
1917 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1918 return vims
.keys()[0], vims
.values()[0]
1922 '''Takes dict d and updates it with the values in dict u.'''
1923 '''It merges all depth levels'''
1924 for k
, v
in u
.iteritems():
1925 if isinstance(v
, collections
.Mapping
):
1926 r
= update(d
.get(k
, {}), v
)
1933 def create_instance(mydb
, tenant_id
, instance_dict
):
1934 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1935 # logger.debug("Creating instance...")
1936 scenario
= instance_dict
["scenario"]
1938 #find main datacenter
1940 myvim_threads_id
= {}
1943 datacenter
= instance_dict
.get("datacenter")
1944 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
1945 myvims
[default_datacenter_id
] = vim
1946 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
1947 tasks_to_launch
[myvim_threads_id
[default_datacenter_id
]] = []
1948 #myvim_tenant = myvim['tenant_id']
1949 # default_datacenter_name = vim['name']
1952 #print "Checking that the scenario exists and getting the scenario dictionary"
1953 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, default_datacenter_id
)
1955 #logger.debug(">>>>>>> Dictionaries before merging")
1956 #logger.debug(">>>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
1957 #logger.debug(">>>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
1959 scenarioDict
['datacenter_id'] = default_datacenter_id
1961 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1962 auxNetDict
['scenario'] = {}
1964 logger
.debug("Creating instance from scenario-dict:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)) #TODO remove
1965 instance_name
= instance_dict
["name"]
1966 instance_description
= instance_dict
.get("description")
1968 # 0 check correct parameters
1969 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1971 for scenario_net
in scenarioDict
['nets']:
1972 if net_name
== scenario_net
["name"]:
1976 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
), HTTP_Bad_Request
)
1977 if "sites" not in net_instance_desc
:
1978 net_instance_desc
["sites"] = [ {} ]
1979 site_without_datacenter_field
= False
1980 for site
in net_instance_desc
["sites"]:
1981 if site
.get("datacenter"):
1982 if site
["datacenter"] not in myvims
:
1983 #Add this datacenter to myvims
1984 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
1986 myvim_threads_id
[d
],_
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
1987 tasks_to_launch
[myvim_threads_id
[d
]] = []
1988 site
["datacenter"] = d
#change name to id
1990 if site_without_datacenter_field
:
1991 raise NfvoException("Found more than one entries without datacenter field at instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
1992 site_without_datacenter_field
= True
1993 site
["datacenter"] = default_datacenter_id
#change name to id
1995 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
1997 for scenario_vnf
in scenarioDict
['vnfs']:
1998 if vnf_name
== scenario_vnf
['name']:
2002 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
2003 if "datacenter" in vnf_instance_desc
:
2004 # Add this datacenter to myvims
2005 if vnf_instance_desc
["datacenter"] not in myvims
:
2006 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2008 myvim_threads_id
[d
],_
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2009 tasks_to_launch
[myvim_threads_id
[d
]] = []
2010 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
2012 #0.1 parse cloud-config parameters
2013 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
2015 #0.2 merge instance information into scenario
2016 #Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
2017 #However, this is not possible yet.
2018 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
2019 for scenario_net
in scenarioDict
['nets']:
2020 if net_name
== scenario_net
["name"]:
2021 if 'ip-profile' in net_instance_desc
:
2022 ipprofile
= net_instance_desc
['ip-profile']
2023 ipprofile
['subnet_address'] = ipprofile
.pop('subnet-address',None)
2024 ipprofile
['ip_version'] = ipprofile
.pop('ip-version','IPv4')
2025 ipprofile
['gateway_address'] = ipprofile
.pop('gateway-address',None)
2026 ipprofile
['dns_address'] = ipprofile
.pop('dns-address',None)
2027 if 'dhcp' in ipprofile
:
2028 ipprofile
['dhcp_start_address'] = ipprofile
['dhcp'].get('start-address',None)
2029 ipprofile
['dhcp_enabled'] = ipprofile
['dhcp'].get('enabled',True)
2030 ipprofile
['dhcp_count'] = ipprofile
['dhcp'].get('count',None)
2031 del ipprofile
['dhcp']
2032 if 'ip_profile' not in scenario_net
:
2033 scenario_net
['ip_profile'] = ipprofile
2035 update(scenario_net
['ip_profile'],ipprofile
)
2036 for interface
in net_instance_desc
.get('interfaces', () ):
2037 if 'ip_address' in interface
:
2038 for vnf
in scenarioDict
['vnfs']:
2039 if interface
['vnf'] == vnf
['name']:
2040 for vnf_interface
in vnf
['interfaces']:
2041 if interface
['vnf_interface'] == vnf_interface
['external_name']:
2042 vnf_interface
['ip_address']=interface
['ip_address']
2044 #logger.debug(">>>>>>>> Merged dictionary")
2045 logger
.debug("Creating instance scenario-dict MERGED:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False))
2048 # 1. Creating new nets (sce_nets) in the VIM"
2049 for sce_net
in scenarioDict
['nets']:
2050 sce_net
["vim_id_sites"]={}
2051 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
2052 net_name
= descriptor_net
.get("vim-network-name")
2053 auxNetDict
['scenario'][sce_net
['uuid']] = {}
2055 sites
= descriptor_net
.get("sites", [ {} ])
2057 if site
.get("datacenter"):
2058 vim
= myvims
[ site
["datacenter"] ]
2059 datacenter_id
= site
["datacenter"]
2060 myvim_thread_id
= myvim_threads_id
[ site
["datacenter"] ]
2062 vim
= myvims
[ default_datacenter_id
]
2063 datacenter_id
= default_datacenter_id
2064 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2065 net_type
= sce_net
['type']
2066 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
2067 if sce_net
["external"]:
2069 net_name
= sce_net
["name"]
2070 if "netmap-use" in site
or "netmap-create" in site
:
2071 create_network
= False
2072 lookfor_network
= False
2073 if "netmap-use" in site
:
2074 lookfor_network
= True
2075 if utils
.check_valid_uuid(site
["netmap-use"]):
2076 filter_text
= "scenario id '%s'" % site
["netmap-use"]
2077 lookfor_filter
["id"] = site
["netmap-use"]
2079 filter_text
= "scenario name '%s'" % site
["netmap-use"]
2080 lookfor_filter
["name"] = site
["netmap-use"]
2081 if "netmap-create" in site
:
2082 create_network
= True
2083 net_vim_name
= net_name
2084 if site
["netmap-create"]:
2085 net_vim_name
= site
["netmap-create"]
2087 elif sce_net
['vim_id'] != None:
2088 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
2089 create_network
= False
2090 lookfor_network
= True
2091 lookfor_filter
["id"] = sce_net
['vim_id']
2092 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
2093 #look for network at datacenter and return error
2095 #There is not a netmap, look at datacenter for a net with this name and create if not found
2096 create_network
= True
2097 lookfor_network
= True
2098 lookfor_filter
["name"] = sce_net
["name"]
2099 net_vim_name
= sce_net
["name"]
2100 filter_text
= "scenario name '%s'" % sce_net
["name"]
2103 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
2104 net_name
= net_name
[:255] #limit length
2105 net_vim_name
= net_name
2106 create_network
= True
2107 lookfor_network
= False
2110 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
2111 if len(vim_nets
) > 1:
2112 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2113 elif len(vim_nets
) == 0:
2114 if not create_network
:
2115 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2117 sce_net
["vim_id_sites"][datacenter_id
] = vim_nets
[0]['id']
2118 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
2119 create_network
= False
2121 #if network is not external
2122 task
= new_task("new-net", (net_vim_name
, net_type
, sce_net
.get('ip_profile',None)))
2123 task_id
= task
["id"]
2124 instance_tasks
[task_id
] = task
2125 tasks_to_launch
[myvim_thread_id
].append(task
)
2126 #network_id = vim.new_network(net_vim_name, net_type, sce_net.get('ip_profile',None))
2127 sce_net
["vim_id_sites"][datacenter_id
] = task_id
2128 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = task_id
2129 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':task_id
})
2130 sce_net
["created"] = True
2132 # 2. Creating new nets (vnf internal nets) in the VIM"
2133 #For each vnf net, we create it and we add it to instanceNetlist.
2134 for sce_vnf
in scenarioDict
['vnfs']:
2135 for net
in sce_vnf
['nets']:
2136 if sce_vnf
.get("datacenter"):
2137 vim
= myvims
[ sce_vnf
["datacenter"] ]
2138 datacenter_id
= sce_vnf
["datacenter"]
2139 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"]]
2141 vim
= myvims
[ default_datacenter_id
]
2142 datacenter_id
= default_datacenter_id
2143 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2144 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
2145 net_name
= descriptor_net
.get("name")
2147 net_name
= "%s.%s" %(instance_name
, net
["name"])
2148 net_name
= net_name
[:255] #limit length
2149 net_type
= net
['type']
2150 task
= new_task("new-net", (net_name
, net_type
, net
.get('ip_profile',None)))
2151 task_id
= task
["id"]
2152 instance_tasks
[task_id
] = task
2153 tasks_to_launch
[myvim_thread_id
].append(task
)
2154 # network_id = vim.new_network(net_name, net_type, net.get('ip_profile',None))
2155 net
['vim_id'] = task_id
2156 if sce_vnf
['uuid'] not in auxNetDict
:
2157 auxNetDict
[sce_vnf
['uuid']] = {}
2158 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = task_id
2159 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':task_id
})
2160 net
["created"] = True
2163 #print "auxNetDict:"
2164 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2166 # 3. Creating new vm instances in the VIM
2167 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2168 for sce_vnf
in scenarioDict
['vnfs']:
2169 if sce_vnf
.get("datacenter"):
2170 vim
= myvims
[ sce_vnf
["datacenter"] ]
2171 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"] ]
2172 datacenter_id
= sce_vnf
["datacenter"]
2174 vim
= myvims
[ default_datacenter_id
]
2175 myvim_thread_id
= myvim_threads_id
[ default_datacenter_id
]
2176 datacenter_id
= default_datacenter_id
2177 sce_vnf
["datacenter_id"] = datacenter_id
2179 for vm
in sce_vnf
['vms']:
2182 myVMDict
['name'] = "{}.{}.{}".format(instance_name
,sce_vnf
['name'],chr(96+i
))
2183 myVMDict
['description'] = myVMDict
['name'][0:99]
2185 # myVMDict['start'] = "no"
2186 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2187 #create image at vim in case it not exist
2188 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2189 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
2190 vm
['vim_image_id'] = image_id
2192 #create flavor at vim in case it not exist
2193 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2194 if flavor_dict
['extended']!=None:
2195 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2196 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
2198 #Obtain information for additional disks
2199 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',), WHERE
={'vim_id': flavor_id
})
2200 if not extended_flavor_dict
:
2201 raise NfvoException("flavor '{}' not found".format(flavor_id
), HTTP_Not_Found
)
2204 #extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
2205 myVMDict
['disks'] = None
2206 extended_info
= extended_flavor_dict
[0]['extended']
2207 if extended_info
!= None:
2208 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
2209 if 'disks' in extended_flavor_dict_yaml
:
2210 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
2212 vm
['vim_flavor_id'] = flavor_id
2213 myVMDict
['imageRef'] = vm
['vim_image_id']
2214 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2215 myVMDict
['networks'] = []
2217 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
2218 for iface
in vm
['interfaces']:
2220 if iface
['type']=="data":
2221 netDict
['type'] = iface
['model']
2222 elif "model" in iface
and iface
["model"]!=None:
2223 netDict
['model']=iface
['model']
2224 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2225 #discover type of interface looking at flavor
2226 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2227 for flavor_iface
in numa
.get('interfaces',[]):
2228 if flavor_iface
.get('name') == iface
['internal_name']:
2229 if flavor_iface
['dedicated'] == 'yes':
2230 netDict
['type']="PF" #passthrough
2231 elif flavor_iface
['dedicated'] == 'no':
2232 netDict
['type']="VF" #siov
2233 elif flavor_iface
['dedicated'] == 'yes:sriov':
2234 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2235 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2237 netDict
["use"]=iface
['type']
2238 if netDict
["use"]=="data" and not netDict
.get("type"):
2239 #print "netDict", netDict
2240 #print "iface", iface
2241 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'])
2242 if flavor_dict
.get('extended')==None:
2243 raise NfvoException(e_text
+ "After database migration some information is not available. \
2244 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
2246 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
2247 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2248 netDict
["type"]="virtual"
2249 if "vpci" in iface
and iface
["vpci"] is not None:
2250 netDict
['vpci'] = iface
['vpci']
2251 if "mac" in iface
and iface
["mac"] is not None:
2252 netDict
['mac_address'] = iface
['mac']
2253 if "port-security" in iface
and iface
["port-security"] is not None:
2254 netDict
['port_security'] = iface
['port-security']
2255 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2256 netDict
['floating_ip'] = iface
['floating-ip']
2257 netDict
['name'] = iface
['internal_name']
2258 if iface
['net_id'] is None:
2259 for vnf_iface
in sce_vnf
["interfaces"]:
2262 if vnf_iface
['interface_id']==iface
['uuid']:
2263 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
2266 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2267 if netDict
.get('net_id') and is_task_id(netDict
['net_id']):
2268 task_depends
[netDict
['net_id']] = instance_tasks
[netDict
['net_id']]
2269 #skip bridge ifaces not connected to any net
2270 #if 'net_id' not in netDict or netDict['net_id']==None:
2272 myVMDict
['networks'].append(netDict
)
2273 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2274 #print myVMDict['name']
2275 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2276 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2277 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2278 if vm
.get("boot_data"):
2279 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config
)
2281 cloud_config_vm
= cloud_config
2282 task
= new_task("new-vm", (myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2283 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2284 cloud_config_vm
, myVMDict
['disks']), depends
=task_depends
)
2285 instance_tasks
[task
["id"]] = task
2286 tasks_to_launch
[myvim_thread_id
].append(task
)
2288 vm
['vim_id'] = vm_id
2289 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2290 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2291 for net
in myVMDict
['networks']:
2293 for iface
in vm
['interfaces']:
2294 if net
["name"]==iface
["internal_name"]:
2295 iface
["vim_id"]=net
["vim_id"]
2297 scenarioDict
["datacenter2tenant"] = myvim_threads_id
2298 logger
.debug("create_instance Deployment done scenarioDict: %s",
2299 yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False) )
2300 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
2301 for myvim_thread_id
,task_list
in tasks_to_launch
.items():
2302 for task
in task_list
:
2303 vim_threads
["running"][myvim_thread_id
].insert_task(task
)
2305 global_instance_tasks
[instance_id
] = instance_tasks
2306 # Update database with those ended instance_tasks
2307 # for task in instance_tasks.values():
2308 # if task["status"] == "ok":
2309 # if task["name"] == "new-vm":
2310 # mydb.update_rows("instance_vms", UPDATE={"vim_vm_id": task["result"]},
2311 # WHERE={"vim_vm_id": task["id"]})
2312 # elif task["name"] == "new-net":
2313 # mydb.update_rows("instance_nets", UPDATE={"vim_net_id": task["result"]},
2314 # WHERE={"vim_net_id": task["id"]})
2315 return mydb
.get_instance_scenario(instance_id
)
2316 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
2317 message
= rollback(mydb
, myvims
, rollbackList
)
2318 if isinstance(e
, db_base_Exception
):
2319 error_text
= "database Exception"
2320 elif isinstance(e
, vimconn
.vimconnException
):
2321 error_text
= "VIM Exception"
2323 error_text
= "Exception"
2324 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2325 #logger.error("create_instance: %s", error_text)
2326 raise NfvoException(error_text
, e
.http_code
)
2329 def delete_instance(mydb
, tenant_id
, instance_id
):
2330 #print "Checking that the instance_id exists and getting the instance dictionary"
2331 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
2332 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2333 tenant_id
= instanceDict
["tenant_id"]
2334 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2336 #1. Delete from Database
2337 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
2346 for sce_vnf
in instanceDict
['vnfs']:
2347 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2348 if datacenter_key
not in myvims
:
2350 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2351 except NfvoException
as e
:
2352 logger
.error(str(e
))
2354 myvim_threads
[datacenter_key
] = myvim_thread
2355 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
2356 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2358 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
2359 sce_vnf
["datacenter_tenant_id"]))
2360 myvims
[datacenter_key
] = None
2362 myvims
[datacenter_key
] = vims
.values()[0]
2363 myvim
= myvims
[datacenter_key
]
2364 myvim_thread
= myvim_threads
[datacenter_key
]
2365 for vm
in sce_vnf
['vms']:
2367 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2371 if is_task_id(vm
['vim_vm_id']):
2372 task_id
= vm
['vim_vm_id']
2373 old_task
= global_instance_tasks
[instance_id
].get(task_id
)
2375 error_msg
+= "\n VM was scheduled for create, but task {} is not found".format(task_id
)
2378 if old_task
["status"] == "enqueued":
2379 old_task
["status"] = "deleted"
2380 elif old_task
["status"] == "error":
2382 elif old_task
["status"] == "processing":
2383 task
= new_task("del-vm", (task_id
, vm
["interfaces"]), depends
={task_id
: old_task
})
2385 task
= new_task("del-vm", (old_task
["result"], vm
["interfaces"]))
2387 task
= new_task("del-vm", (vm
['vim_vm_id'], vm
["interfaces"]) )
2389 myvim_thread
.insert_task(task
)
2390 except vimconn
.vimconnNotFoundException
as e
:
2391 error_msg
+="\n VM VIM_id={} not found at datacenter={}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2392 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
2393 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
2394 except vimconn
.vimconnException
as e
:
2395 error_msg
+="\n VM VIM_id={} at datacenter={} Error: {} {}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"], e
.http_code
, str(e
))
2396 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s",
2397 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
2401 for net
in instanceDict
['nets']:
2402 if not net
['created']:
2403 continue #skip not created nets
2404 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2405 if datacenter_key
not in myvims
:
2407 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2408 except NfvoException
as e
:
2409 logger
.error(str(e
))
2411 myvim_threads
[datacenter_key
] = myvim_thread
2412 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
2413 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2415 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2416 myvims
[datacenter_key
] = None
2418 myvims
[datacenter_key
] = vims
.values()[0]
2419 myvim
= myvims
[datacenter_key
]
2420 myvim_thread
= myvim_threads
[datacenter_key
]
2423 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
2427 if is_task_id(net
['vim_net_id']):
2428 task_id
= net
['vim_net_id']
2429 old_task
= global_instance_tasks
[instance_id
].get(task_id
)
2431 error_msg
+= "\n NET was scheduled for create, but task {} is not found".format(task_id
)
2434 if old_task
["status"] == "enqueued":
2435 old_task
["status"] = "deleted"
2436 elif old_task
["status"] == "error":
2438 elif old_task
["status"] == "processing":
2439 task
= new_task("del-net", task_id
, depends
={task_id
: old_task
})
2441 task
= new_task("del-net", old_task
["result"])
2443 task
= new_task("del-net", (net
['vim_net_id'], net
['sdn_net_id']))
2445 myvim_thread
.insert_task(task
)
2446 except vimconn
.vimconnNotFoundException
as e
:
2447 error_msg
+= "\n NET VIM_id={} not found at datacenter={}".format(net
['vim_net_id'], net
["datacenter_id"])
2448 logger
.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found",
2449 net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']))
2450 except vimconn
.vimconnException
as e
:
2451 error_msg
+= "\n NET VIM_id={} at datacenter={} Error: {} {}".format(net
['vim_net_id'],
2452 net
["datacenter_id"],
2453 e
.http_code
, str(e
))
2454 logger
.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s",
2455 e
.http_code
, net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']), str(e
))
2456 if len(error_msg
) > 0:
2457 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
2459 return 'instance ' + message
+ ' deleted'
2462 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
2463 '''Refreshes a scenario instance. It modifies instanceDict'''
2465 - 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
2468 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
2469 # #print "nfvo.refresh_instance begins"
2470 # #print json.dumps(instanceDict, indent=4)
2472 # #print "Getting the VIM URL and the VIM tenant_id"
2475 # # 1. Getting VIM vm and net list
2476 # vms_updated = [] #List of VM instance uuids in openmano that were updated
2479 # for sce_vnf in instanceDict['vnfs']:
2480 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
2481 # if datacenter_key not in vm_list:
2482 # vm_list[datacenter_key] = []
2483 # if datacenter_key not in myvims:
2484 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
2485 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
2486 # if len(vims) == 0:
2487 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
2488 # myvims[datacenter_key] = None
2490 # myvims[datacenter_key] = vims.values()[0]
2491 # for vm in sce_vnf['vms']:
2492 # vm_list[datacenter_key].append(vm['vim_vm_id'])
2493 # vms_notupdated.append(vm["uuid"])
2495 # nets_updated = [] #List of VM instance uuids in openmano that were updated
2496 # nets_notupdated=[]
2498 # for net in instanceDict['nets']:
2499 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
2500 # if datacenter_key not in net_list:
2501 # net_list[datacenter_key] = []
2502 # if datacenter_key not in myvims:
2503 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
2504 # datacenter_tenant_id=net["datacenter_tenant_id"])
2505 # if len(vims) == 0:
2506 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
2507 # myvims[datacenter_key] = None
2509 # myvims[datacenter_key] = vims.values()[0]
2511 # net_list[datacenter_key].append(net['vim_net_id'])
2512 # nets_notupdated.append(net["uuid"])
2514 # # 1. Getting the status of all VMs
2516 # for datacenter_key in myvims:
2517 # if not vm_list.get(datacenter_key):
2521 # if not myvims[datacenter_key]:
2522 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
2525 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
2527 # except vimconn.vimconnException as e:
2528 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
2529 # failed_message = str(e)
2531 # for vm in vm_list[datacenter_key]:
2532 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
2534 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
2535 # for sce_vnf in instanceDict['vnfs']:
2536 # for vm in sce_vnf['vms']:
2537 # vm_id = vm['vim_vm_id']
2538 # interfaces = vm_dict[vm_id].pop('interfaces', [])
2539 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
2540 # has_mgmt_iface = False
2541 # for iface in vm["interfaces"]:
2542 # if iface["type"]=="mgmt":
2543 # has_mgmt_iface = True
2544 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
2545 # vm_dict[vm_id]['status'] = "ACTIVE"
2546 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
2547 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
2548 # 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'):
2549 # vm['status'] = vm_dict[vm_id]['status']
2550 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
2551 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
2552 # # 2.1. Update in openmano DB the VMs whose status changed
2554 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
2555 # vms_notupdated.remove(vm["uuid"])
2557 # vms_updated.append(vm["uuid"])
2558 # except db_base_Exception as e:
2559 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
2560 # # 2.2. Update in openmano DB the interface VMs
2561 # for interface in interfaces:
2562 # #translate from vim_net_id to instance_net_id
2563 # network_id_list=[]
2564 # for net in instanceDict['nets']:
2565 # if net["vim_net_id"] == interface["vim_net_id"]:
2566 # network_id_list.append(net["uuid"])
2567 # if not network_id_list:
2569 # del interface["vim_net_id"]
2571 # for network_id in network_id_list:
2572 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
2573 # except db_base_Exception as e:
2574 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
2576 # # 3. Getting the status of all nets
2578 # for datacenter_key in myvims:
2579 # if not net_list.get(datacenter_key):
2582 # failed_message = ""
2583 # if not myvims[datacenter_key]:
2584 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
2587 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
2589 # except vimconn.vimconnException as e:
2590 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
2591 # failed_message = str(e)
2593 # for net in net_list[datacenter_key]:
2594 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
2596 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
2597 # # TODO: update nets inside a vnf
2598 # for net in instanceDict['nets']:
2599 # net_id = net['vim_net_id']
2600 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
2601 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
2602 # 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'):
2603 # net['status'] = net_dict[net_id]['status']
2604 # net['error_msg'] = net_dict[net_id].get('error_msg')
2605 # net['vim_info'] = net_dict[net_id].get('vim_info')
2606 # # 5.1. Update in openmano DB the nets whose status changed
2608 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
2609 # nets_notupdated.remove(net["uuid"])
2611 # nets_updated.append(net["uuid"])
2612 # except db_base_Exception as e:
2613 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
2615 # # Returns appropriate output
2616 # #print "nfvo.refresh_instance finishes"
2617 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
2618 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
2619 instance_id
= instanceDict
['uuid']
2620 # if len(vms_notupdated)+len(nets_notupdated)>0:
2621 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
2622 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
2624 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
2627 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
2628 #print "Checking that the instance_id exists and getting the instance dictionary"
2629 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
2630 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2632 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2633 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2635 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2636 myvim
= vims
.values()[0]
2639 input_vnfs
= action_dict
.pop("vnfs", [])
2640 input_vms
= action_dict
.pop("vms", [])
2641 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
2645 for sce_vnf
in instanceDict
['vnfs']:
2646 for vm
in sce_vnf
['vms']:
2647 if not action_over_all
:
2648 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
2649 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
2652 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
2653 if "console" in action_dict
:
2654 if not global_config
["http_console_proxy"]:
2655 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2656 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2657 protocol
=data
["protocol"],
2658 ip
= data
["server"],
2659 port
= data
["port"],
2660 suffix
= data
["suffix"]),
2664 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
2665 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
2666 "description": "this console is only reachable by local interface",
2671 #print "console data", data
2673 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
2674 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2675 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2676 protocol
=data
["protocol"],
2677 ip
= global_config
["http_console_host"],
2678 port
= console_thread
.port
,
2679 suffix
= data
["suffix"]),
2683 except NfvoException
as e
:
2684 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2688 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
2690 except vimconn
.vimconnException
as e
:
2691 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2694 if vm_ok
==0: #all goes wrong
2700 def create_or_use_console_proxy_thread(console_server
, console_port
):
2701 #look for a non-used port
2702 console_thread_key
= console_server
+ ":" + str(console_port
)
2703 if console_thread_key
in global_config
["console_thread"]:
2704 #global_config["console_thread"][console_thread_key].start_timeout()
2705 return global_config
["console_thread"][console_thread_key
]
2707 for port
in global_config
["console_port_iterator"]():
2708 #print "create_or_use_console_proxy_thread() port:", port
2709 if port
in global_config
["console_ports"]:
2712 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
2714 global_config
["console_thread"][console_thread_key
] = clithread
2715 global_config
["console_ports"][port
] = console_thread_key
2717 except cli
.ConsoleProxyExceptionPortUsed
as e
:
2718 #port used, try with onoher
2720 except cli
.ConsoleProxyException
as e
:
2721 raise NfvoException(str(e
), HTTP_Bad_Request
)
2722 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
2725 def check_tenant(mydb
, tenant_id
):
2726 '''check that tenant exists at database'''
2727 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
2729 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
2733 def new_tenant(mydb
, tenant_dict
):
2734 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
2738 def delete_tenant(mydb
, tenant
):
2739 #get nfvo_tenant info
2741 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
2742 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
2743 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
2746 def new_datacenter(mydb
, datacenter_descriptor
):
2747 if "config" in datacenter_descriptor
:
2748 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2749 #Check that datacenter-type is correct
2750 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
2753 module
= "vimconn_" + datacenter_type
2754 module_info
= imp
.find_module(module
)
2755 except (IOError, ImportError):
2756 if module_info
and module_info
[0]:
2757 file.close(module_info
[0])
2758 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
2760 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
2761 return datacenter_id
2764 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2765 #obtain data, check that only one exist
2766 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2768 datacenter_id
= datacenter
['uuid']
2769 where
={'uuid': datacenter
['uuid']}
2770 if "config" in datacenter_descriptor
:
2771 if datacenter_descriptor
['config']!=None:
2773 new_config_dict
= datacenter_descriptor
["config"]
2776 for k
in new_config_dict
:
2777 if new_config_dict
[k
]==None:
2780 config_text
= datacenter
.get("config")
2783 config_dict
= yaml
.load(config_text
)
2784 config_dict
.update(new_config_dict
)
2788 except Exception as e
:
2789 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
2790 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
2791 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
2792 return datacenter_id
2795 def delete_datacenter(mydb
, datacenter
):
2796 #get nfvo_tenant info
2797 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
2798 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
2799 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
2802 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):
2803 #get datacenter info
2804 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2805 datacenter_name
= myvim
["name"]
2807 create_vim_tenant
= True if not vim_tenant_id
and not vim_tenant_name
else False
2809 # get nfvo_tenant info
2810 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2811 if vim_tenant_name
==None:
2812 vim_tenant_name
=tenant_dict
['name']
2814 #check that this association does not exist before
2815 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2816 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2817 if len(tenants_datacenters
)>0:
2818 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
2820 vim_tenant_id_exist_atdb
=False
2821 if not create_vim_tenant
:
2822 where_
={"datacenter_id": datacenter_id
}
2823 if vim_tenant_id
!=None:
2824 where_
["vim_tenant_id"] = vim_tenant_id
2825 if vim_tenant_name
!=None:
2826 where_
["vim_tenant_name"] = vim_tenant_name
2827 #check if vim_tenant_id is already at database
2828 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
2829 if len(datacenter_tenants_dict
)>=1:
2830 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2831 vim_tenant_id_exist_atdb
=True
2832 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2834 datacenter_tenants_dict
= {}
2835 #insert at table datacenter_tenants
2836 else: #if vim_tenant_id==None:
2837 #create tenant at VIM if not provided
2839 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2840 except vimconn
.vimconnException
as e
:
2841 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
2842 datacenter_tenants_dict
= {}
2843 datacenter_tenants_dict
["created"]="true"
2845 #fill datacenter_tenants table
2846 if not vim_tenant_id_exist_atdb
:
2847 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2848 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2849 datacenter_tenants_dict
["user"] = vim_username
2850 datacenter_tenants_dict
["passwd"] = vim_password
2851 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2853 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
2854 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
2855 datacenter_tenants_dict
["uuid"] = id_
2857 #fill tenants_datacenters table
2858 tenants_datacenter_dict
["datacenter_tenant_id"]=datacenter_tenants_dict
["uuid"]
2859 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
2861 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_dict
['uuid'], datacenter_id
) # reload data
2862 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
2863 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, datacenter_name
, db
=db
, db_lock
=db_lock
, ovim
=ovim
)
2865 thread_id
= datacenter_tenants_dict
["uuid"]
2866 vim_threads
["running"][thread_id
] = new_thread
2867 return datacenter_id
2869 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):
2870 #Obtain the data of this datacenter_tenant_id
2871 vim_data
= mydb
.get_rows(
2872 SELECT
=("datacenter_tenants.vim_tenant_name", "datacenter_tenants.vim_tenant_id", "datacenter_tenants.user",
2873 "datacenter_tenants.passwd", "datacenter_tenants.config"),
2874 FROM
="datacenter_tenants JOIN tenants_datacenters ON datacenter_tenants.uuid=tenants_datacenters.datacenter_tenant_id",
2875 WHERE
={"tenants_datacenters.nfvo_tenant_id": nfvo_tenant
,
2876 "tenants_datacenters.datacenter_id": datacenter_id
})
2878 logger
.debug(str(vim_data
))
2879 if len(vim_data
) < 1:
2880 raise NfvoException("Datacenter {} is not attached for tenant {}".format(datacenter_id
, nfvo_tenant
), HTTP_Conflict
)
2884 v
['config'] = yaml
.load(v
['config'])
2887 v
['vim_tenant_id'] = vim_tenant_id
2889 v
['vim_tenant_name'] = vim_tenant_name
2891 v
['user'] = vim_username
2893 v
['passwd'] = vim_password
2897 v
['config'].update(config
)
2899 logger
.debug(str(v
))
2900 deassociate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'])
2901 associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'], vim_tenant_name
=v
['vim_tenant_name'],
2902 vim_username
=v
['user'], vim_password
=v
['passwd'], config
=v
['config'])
2904 return datacenter_id
2906 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2907 #get datacenter info
2908 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2910 #get nfvo_tenant info
2911 if not tenant_id
or tenant_id
=="any":
2914 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
2915 tenant_uuid
= tenant_dict
['uuid']
2917 #check that this association exist before
2918 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
2920 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
2921 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2922 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
2923 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
2925 #delete this association
2926 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2928 #get vim_tenant info and deletes
2930 for tenant_datacenter_item
in tenant_datacenter_list
:
2931 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2932 #try to delete vim:tenant
2934 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2935 if vim_tenant_dict
['created']=='true':
2936 #delete tenant at VIM if created by NFVO
2938 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2939 except vimconn
.vimconnException
as e
:
2940 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
2941 logger
.warn(warning
)
2942 except db_base_Exception
as e
:
2943 logger
.error("Cannot delete datacenter_tenants " + str(e
))
2944 pass # the error will be caused because dependencies, vim_tenant can not be deleted
2945 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
2946 thread
= vim_threads
["running"][thread_id
]
2947 thread
.insert_task(new_task("exit", None))
2948 vim_threads
["deleting"][thread_id
] = thread
2949 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
2952 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
2954 #get datacenter info
2955 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2957 if 'net-update' in action_dict
:
2959 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2961 except vimconn
.vimconnException
as e
:
2962 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
2963 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2964 #update nets Change from VIM format to NFVO format
2967 net_nfvo
={'datacenter_id': datacenter_id
}
2968 net_nfvo
['name'] = net
['name']
2969 #net_nfvo['description']= net['name']
2970 net_nfvo
['vim_net_id'] = net
['id']
2971 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2972 net_nfvo
['shared'] = net
['shared']
2973 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2974 net_list
.append(net_nfvo
)
2975 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
2976 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
2978 elif 'net-edit' in action_dict
:
2979 net
= action_dict
['net-edit'].pop('net')
2980 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2981 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
2982 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2984 elif 'net-delete' in action_dict
:
2985 net
= action_dict
['net-deelte'].get('net')
2986 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2987 result
= mydb
.delete_row(FROM
='datacenter_nets',
2988 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2992 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
2995 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
2996 #get datacenter info
2997 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2999 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
3000 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
3001 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
3005 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
3006 #get datacenter info
3007 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3010 action_dict
= action_dict
["netmap"]
3011 if 'vim_id' in action_dict
:
3012 filter_dict
["id"] = action_dict
['vim_id']
3013 if 'vim_name' in action_dict
:
3014 filter_dict
["name"] = action_dict
['vim_name']
3016 filter_dict
["shared"] = True
3019 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
3020 except vimconn
.vimconnException
as e
:
3021 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
3022 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
3023 if len(vim_nets
)>1 and action_dict
:
3024 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
3025 elif len(vim_nets
)==0: # and action_dict:
3026 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
3028 for net
in vim_nets
:
3029 net_nfvo
={'datacenter_id': datacenter_id
}
3030 if action_dict
and "name" in action_dict
:
3031 net_nfvo
['name'] = action_dict
['name']
3033 net_nfvo
['name'] = net
['name']
3034 #net_nfvo['description']= net['name']
3035 net_nfvo
['vim_net_id'] = net
['id']
3036 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
3037 net_nfvo
['shared'] = net
['shared']
3038 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
3040 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
3041 net_nfvo
["status"] = "OK"
3042 net_nfvo
["uuid"] = net_id
3043 except db_base_Exception
as e
:
3047 net_nfvo
["status"] = "FAIL: " + str(e
)
3048 net_list
.append(net_nfvo
)
3052 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
3053 #get datacenter info
3054 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3057 if utils
.check_valid_uuid(name
):
3058 filter_dict
["id"] = name
3060 filter_dict
["name"] = name
3062 if item
=="networks":
3063 #filter_dict['tenant_id'] = myvim['tenant_id']
3064 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
3065 elif item
=="tenants":
3066 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
3067 elif item
== "images":
3068 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
3070 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3071 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
3072 if name
and len(content
)==1:
3073 return {item
[:-1]: content
[0]}
3074 elif name
and len(content
)==0:
3075 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
3078 return {item
: content
}
3079 except vimconn
.vimconnException
as e
:
3080 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
3081 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
3084 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
3085 #get datacenter info
3086 if tenant_id
== "any":
3089 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3091 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
3092 logger
.debug("vim_action_delete vim response: " + str(content
))
3093 items
= content
.values()[0]
3094 if type(items
)==list and len(items
)==0:
3095 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
3096 elif type(items
)==list and len(items
)>1:
3097 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
3098 else: # it is a dict
3099 item_id
= items
["id"]
3100 item_name
= str(items
.get("name"))
3103 if item
=="networks":
3104 content
= myvim
.delete_network(item_id
)
3105 elif item
=="tenants":
3106 content
= myvim
.delete_tenant(item_id
)
3107 elif item
== "images":
3108 content
= myvim
.delete_image(item_id
)
3110 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3111 except vimconn
.vimconnException
as e
:
3112 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
3113 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
3115 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
3118 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
3119 #get datacenter info
3120 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
3121 if tenant_id
== "any":
3123 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3125 if item
=="networks":
3126 net
= descriptor
["network"]
3127 net_name
= net
.pop("name")
3128 net_type
= net
.pop("type", "bridge")
3129 net_public
= net
.pop("shared", False)
3130 net_ipprofile
= net
.pop("ip_profile", None)
3131 net_vlan
= net
.pop("vlan", None)
3132 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
3133 elif item
=="tenants":
3134 tenant
= descriptor
["tenant"]
3135 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
3137 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3138 except vimconn
.vimconnException
as e
:
3139 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
3141 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
3143 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
3144 data
= ovim
.new_of_controller(sdn_controller
)
3145 logger
.debug('New SDN controller created with uuid {}'.format(data
))
3148 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
3149 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
3150 msg
= 'SDN controller {} updated'.format(data
)
3154 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
3155 if controller_id
== None:
3156 data
= ovim
.get_of_controllers()
3158 data
= ovim
.show_of_controller(controller_id
)
3160 msg
= 'SDN controller list:\n {}'.format(data
)
3164 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
3165 select_
= ('uuid', 'config')
3166 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
3167 for datacenter
in datacenters
:
3168 if datacenter
['config']:
3169 config
= yaml
.load(datacenter
['config'])
3170 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
3171 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), HTTP_Conflict
)
3173 data
= ovim
.delete_of_controller(controller_id
)
3174 msg
= 'SDN controller {} deleted'.format(data
)
3178 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
3179 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
3180 if len(controller
) < 1:
3181 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), HTTP_Not_Found
)
3184 sdn_controller_id
= yaml
.load(controller
[0]["config"])["sdn-controller"]
3186 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), HTTP_Bad_Request
)
3188 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
3189 switch_dpid
= sdn_controller
["dpid"]
3192 for compute_node
in sdn_port_mapping
:
3193 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
3195 element
["compute_node"] = compute_node
["compute_node"]
3196 for port
in compute_node
["ports"]:
3197 element
["pci"] = port
.get("pci")
3198 element
["switch_port"] = port
.get("switch_port")
3199 element
["switch_mac"] = port
.get("switch_mac")
3200 if not element
["pci"] or not (element
["switch_port"] or element
["switch_mac"]):
3201 raise NfvoException ("The mapping must contain the 'pci' and at least one of the elements 'switch_port'"
3202 " or 'switch_mac'", HTTP_Bad_Request
)
3203 maps
.append(dict(element
))
3205 return ovim
.set_of_port_mapping(maps
, ofc_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, region
=datacenter_id
)
3207 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
3208 maps
= ovim
.get_of_port_mappings(db_filter
={"region": datacenter_id
})
3211 "sdn-controller": None,
3212 "datacenter-id": datacenter_id
,
3214 "ports_mapping": list()
3217 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
3218 if datacenter
['config']:
3219 config
= yaml
.load(datacenter
['config'])
3220 if 'sdn-controller' in config
:
3221 controller_id
= config
['sdn-controller']
3222 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
3223 result
["sdn-controller"] = controller_id
3224 result
["dpid"] = sdn_controller
["dpid"]
3226 if result
["sdn-controller"] == None or result
["dpid"] == None:
3227 raise NfvoException("Not all SDN controller information for datacenter {} could be found: {}".format(datacenter_id
, result
),
3228 HTTP_Internal_Server_Error
)
3233 ports_correspondence_dict
= dict()
3235 if result
["sdn-controller"] != link
["ofc_id"]:
3236 raise NfvoException("The sdn-controller specified for different port mappings differ", HTTP_Internal_Server_Error
)
3237 if result
["dpid"] != link
["switch_dpid"]:
3238 raise NfvoException("The dpid specified for different port mappings differ", HTTP_Internal_Server_Error
)
3240 element
["pci"] = link
["pci"]
3241 if link
["switch_port"]:
3242 element
["switch_port"] = link
["switch_port"]
3243 if link
["switch_mac"]:
3244 element
["switch_mac"] = link
["switch_mac"]
3246 if not link
["compute_node"] in ports_correspondence_dict
:
3248 content
["compute_node"] = link
["compute_node"]
3249 content
["ports"] = list()
3250 ports_correspondence_dict
[link
["compute_node"]] = content
3252 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
3254 for key
in sorted(ports_correspondence_dict
):
3255 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
3259 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
3260 return ovim
.clear_of_port_mapping(db_filter
={"region":datacenter_id
})