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 from lib_osm_openvim
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 pkg
= __import__("osm_ro." + module
)
152 vim_conn
= getattr(pkg
, module
)
153 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
154 # vim_conn = imp.load_module(vim["type"], *module_info)
155 vimconn_imported
[vim
["type"]] = vim_conn
156 except (IOError, ImportError) as e
:
157 # if module_info and module_info[0]:
158 # file.close(module_info[0])
159 raise NfvoException("Unknown vim type '{}'. Cannot open file '{}.py'; {}: {}".format(
160 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
162 thread_id
= vim
['datacenter_tenant_id']
163 vim_persistent_info
[thread_id
] = {}
166 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
167 myvim
= vimconn_imported
[ vim
["type"] ].vimconnector(
168 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
169 tenant_id
=vim
['vim_tenant_id'], tenant_name
=vim
['vim_tenant_name'],
170 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
171 user
=vim
['user'], passwd
=vim
['passwd'],
172 config
=extra
, persistent_info
=vim_persistent_info
[thread_id
]
174 except Exception as e
:
175 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
176 thread_name
= get_non_used_vim_name(vim
['datacenter_name'], vim
['vim_tenant_id'], vim
['vim_tenant_name'], vim
['vim_tenant_id'])
177 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, vim
['datacenter_name'],
178 vim
['datacenter_tenant_id'], db
=db
, db_lock
=db_lock
, ovim
=ovim
)
180 vim_threads
["running"][thread_id
] = new_thread
181 except db_base_Exception
as e
:
182 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
186 global ovim
, global_config
189 for thread_id
,thread
in vim_threads
["running"].items():
190 thread
.insert_task(new_task("exit", None))
191 vim_threads
["deleting"][thread_id
] = thread
192 vim_threads
["running"] = {}
193 if global_config
and global_config
.get("console_thread"):
194 for thread
in global_config
["console_thread"]:
195 thread
.terminate
= True
198 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
200 return result, content:
201 <0, error_text upon error
202 nb_records, flavor_list on success
205 WHERE_dict
['vnf_id'] = vnf_id
206 if nfvo_tenant
is not None:
207 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
209 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
210 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
211 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
212 #print "get_flavor_list result:", result
213 #print "get_flavor_list content:", content
215 for flavor
in flavors
:
216 flavorList
.append(flavor
['flavor_id'])
220 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
222 return result, content:
223 <0, error_text upon error
224 nb_records, flavor_list on success
227 WHERE_dict
['vnf_id'] = vnf_id
228 if nfvo_tenant
is not None:
229 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
231 #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
232 images
= mydb
.get_rows(FROM
='vms join images on vms.image_id=images.uuid',SELECT
=('image_id',),WHERE
=WHERE_dict
)
235 imageList
.append(image
['image_id'])
239 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
240 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None):
241 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
242 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
243 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
244 raise exception upon error
247 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
248 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
249 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
250 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
251 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
252 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
253 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
254 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'
255 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
256 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
257 'user','passwd', 'dt.config as dt_config')
259 from_
= 'datacenters as d'
260 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
262 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
265 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
266 'datacenter_id': vim
.get('datacenter_id')}
268 extra
.update(yaml
.load(vim
["config"]))
269 if vim
.get('dt_config'):
270 extra
.update(yaml
.load(vim
["dt_config"]))
271 if vim
["type"] not in vimconn_imported
:
274 module
= "vimconn_" + vim
["type"]
275 pkg
= __import__("osm_ro." + module
)
276 vim_conn
= getattr(pkg
, module
)
277 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
278 # vim_conn = imp.load_module(vim["type"], *module_info)
279 vimconn_imported
[vim
["type"]] = vim_conn
280 except (IOError, ImportError) as e
:
281 # if module_info and module_info[0]:
282 # file.close(module_info[0])
283 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
284 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
287 if 'datacenter_tenant_id' in vim
:
288 thread_id
= vim
["datacenter_tenant_id"]
289 if thread_id
not in vim_persistent_info
:
290 vim_persistent_info
[thread_id
] = {}
291 persistent_info
= vim_persistent_info
[thread_id
]
295 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
296 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
297 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
298 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
),
299 tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
300 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
301 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
302 config
=extra
, persistent_info
=persistent_info
304 except Exception as e
:
305 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
307 except db_base_Exception
as e
:
308 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
311 def rollback(mydb
, vims
, rollback_list
):
313 #delete things by reverse order
314 for i
in range(len(rollback_list
)-1, -1, -1):
315 item
= rollback_list
[i
]
316 if item
["where"]=="vim":
317 if item
["vim_id"] not in vims
:
319 vim
=vims
[ item
["vim_id"] ]
321 if item
["what"]=="image":
322 vim
.delete_image(item
["uuid"])
323 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
324 elif item
["what"]=="flavor":
325 vim
.delete_flavor(item
["uuid"])
326 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
327 elif item
["what"]=="network":
328 vim
.delete_network(item
["uuid"])
329 elif item
["what"]=="vm":
330 vim
.delete_vminstance(item
["uuid"])
331 except vimconn
.vimconnException
as e
:
332 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
333 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
334 except db_base_Exception
as e
:
335 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
339 if item
["what"]=="image":
340 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
341 elif item
["what"]=="flavor":
342 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
343 except db_base_Exception
as e
:
344 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
345 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
346 if len(undeleted_items
)==0:
347 return True," Rollback successful."
349 return False," Rollback fails to delete: " + str(undeleted_items
)
352 def check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1):
354 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
356 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
358 #dataplane interfaces
359 for numa
in vnfc
.get("numas",() ):
360 for interface
in numa
.get("interfaces",()):
361 if interface
["name"] in name_dict
:
363 "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
364 vnfc
["name"], interface
["name"]),
366 name_dict
[ interface
["name"] ] = "underlay"
368 for interface
in vnfc
.get("bridge-ifaces",() ):
369 if interface
["name"] in name_dict
:
371 "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
372 vnfc
["name"], interface
["name"]),
374 name_dict
[ interface
["name"] ] = "overlay"
375 vnfc_interfaces
[ vnfc
["name"] ] = name_dict
376 # check bood-data info
377 if "boot-data" in vnfc
:
378 # check that user-data is incompatible with users and config-files
379 if (vnfc
["boot-data"].get("users") or vnfc
["boot-data"].get("config-files")) and vnfc
["boot-data"].get("user-data"):
381 "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
384 #check if the info in external_connections matches with the one in the vnfcs
386 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
387 if external_connection
["name"] in name_list
:
389 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
390 external_connection
["name"]),
392 name_list
.append(external_connection
["name"])
393 if external_connection
["VNFC"] not in vnfc_interfaces
:
395 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
396 external_connection
["name"], external_connection
["VNFC"]),
399 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
401 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
402 external_connection
["name"],
403 external_connection
["local_iface_name"]),
406 #check if the info in internal_connections matches with the one in the vnfcs
408 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
409 if internal_connection
["name"] in name_list
:
411 "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection".format(
412 internal_connection
["name"]),
414 name_list
.append(internal_connection
["name"])
415 #We should check that internal-connections of type "ptp" have only 2 elements
417 if len(internal_connection
["elements"])>2 and (internal_connection
.get("type") == "ptp" or internal_connection
.get("type") == "e-line"):
419 "Error at 'vnf:internal-connections[name:'{}']:elements', size must be 2 for a '{}' type. Consider change it to '{}' type".format(
420 internal_connection
["name"],
421 'ptp' if vnf_descriptor_version
==1 else 'e-line',
422 'data' if vnf_descriptor_version
==1 else "e-lan"),
424 for port
in internal_connection
["elements"]:
426 iface
= port
["local_iface_name"]
427 if vnf
not in vnfc_interfaces
:
429 "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
430 internal_connection
["name"], vnf
),
432 if iface
not in vnfc_interfaces
[ vnf
]:
434 "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
435 internal_connection
["name"], iface
),
437 return -HTTP_Bad_Request
,
438 if vnf_descriptor_version
==1 and "type" not in internal_connection
:
439 if vnfc_interfaces
[vnf
][iface
] == "overlay":
440 internal_connection
["type"] = "bridge"
442 internal_connection
["type"] = "data"
443 if vnf_descriptor_version
==2 and "implementation" not in internal_connection
:
444 if vnfc_interfaces
[vnf
][iface
] == "overlay":
445 internal_connection
["implementation"] = "overlay"
447 internal_connection
["implementation"] = "underlay"
448 if (internal_connection
.get("type") == "data" or internal_connection
.get("type") == "ptp" or \
449 internal_connection
.get("implementation") == "underlay") and vnfc_interfaces
[vnf
][iface
] == "overlay":
451 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
452 internal_connection
["name"],
453 iface
, 'bridge' if vnf_descriptor_version
==1 else 'overlay',
454 'data' if vnf_descriptor_version
==1 else 'underlay'),
456 if (internal_connection
.get("type") == "bridge" or internal_connection
.get("implementation") == "overlay") and \
457 vnfc_interfaces
[vnf
][iface
] == "underlay":
459 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
460 internal_connection
["name"], iface
,
461 'data' if vnf_descriptor_version
==1 else 'underlay',
462 'bridge' if vnf_descriptor_version
==1 else 'overlay'),
466 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
468 if only_create_at_vim
:
469 image_mano_id
= image_dict
['uuid']
470 if return_on_error
== None:
471 return_on_error
= True
473 if image_dict
['location']:
474 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
476 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
478 image_mano_id
= images
[0]['uuid']
480 #create image in MANO DB
481 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
482 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
483 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
485 #temp_image_dict['location'] = image_dict.get('new_location') if image_dict['location'] is None
486 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
487 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
488 #create image at every vim
489 for vim_id
,vim
in vims
.iteritems():
490 image_created
="false"
492 image_db
= mydb
.get_rows(FROM
="datacenters_images", WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
493 #look at VIM if this image exist
495 if image_dict
['location'] is not None:
496 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
499 filter_dict
['name'] = image_dict
['universal_name']
500 if image_dict
.get('checksum') != None:
501 filter_dict
['checksum'] = image_dict
['checksum']
502 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
503 vim_images
= vim
.get_image_list(filter_dict
)
504 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
505 if len(vim_images
) > 1:
506 raise vimconn
.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict
)), HTTP_Conflict
)
507 elif len(vim_images
) == 0:
508 raise vimconn
.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict
)))
510 #logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
511 image_vim_id
= vim_images
[0]['id']
513 except vimconn
.vimconnNotFoundException
as e
:
514 #Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
516 #image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
517 if image_dict
['location']:
518 image_vim_id
= vim
.new_image(image_dict
)
519 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
522 #If we reach this point, then the image has image name, and optionally checksum, and could not be found
523 raise vimconn
.vimconnException(str(e
))
524 except vimconn
.vimconnException
as e
:
526 logger
.error("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
529 logger
.warn("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
531 except vimconn
.vimconnException
as e
:
533 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
535 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
538 #if we reach here, the image has been created or existed
540 #add new vim_id at datacenters_images
541 mydb
.new_row('datacenters_images', {'datacenter_id':vim_id
, 'image_id':image_mano_id
, 'vim_id': image_vim_id
, 'created':image_created
})
542 elif image_db
[0]["vim_id"]!=image_vim_id
:
543 #modify existing vim_id at datacenters_images
544 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
546 return image_vim_id
if only_create_at_vim
else image_mano_id
549 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
550 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
551 'ram':flavor_dict
.get('ram'),
552 'vcpus':flavor_dict
.get('vcpus'),
554 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
555 del flavor_dict
['extended']
556 if 'extended' in flavor_dict
:
557 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
559 #look if flavor exist
560 if only_create_at_vim
:
561 flavor_mano_id
= flavor_dict
['uuid']
562 if return_on_error
== None:
563 return_on_error
= True
565 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
567 flavor_mano_id
= flavors
[0]['uuid']
570 #create one by one the images of aditional disks
571 dev_image_list
=[] #list of images
572 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
574 for device
in flavor_dict
['extended'].get('devices',[]):
575 if "image" not in device
and "image name" not in device
:
578 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
579 image_dict
['universal_name']=device
.get('image name')
580 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
581 image_dict
['location']=device
.get('image')
582 #image_dict['new_location']=vnfc.get('image location')
583 image_dict
['checksum']=device
.get('image checksum')
584 image_metadata_dict
= device
.get('image metadata', None)
585 image_metadata_str
= None
586 if image_metadata_dict
!= None:
587 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
588 image_dict
['metadata']=image_metadata_str
589 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
590 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
591 dev_image_list
.append(image_id
)
593 temp_flavor_dict
['name'] = flavor_dict
['name']
594 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
595 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
596 flavor_mano_id
= content
597 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
598 #create flavor at every vim
599 if 'uuid' in flavor_dict
:
600 del flavor_dict
['uuid']
602 for vim_id
,vim
in vims
.items():
603 flavor_created
="false"
605 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors", WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
606 #look at VIM if this flavor exist SKIPPED
607 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
609 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
613 #Create the flavor in VIM
614 #Translate images at devices from MANO id to VIM id
616 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
617 #make a copy of original devices
620 for device
in flavor_dict
["extended"].get("devices",[]):
623 devices_original
.append(dev
)
624 if 'image' in device
:
626 if 'image metadata' in device
:
627 del device
['image metadata']
629 for index
in range(0,len(devices_original
)) :
630 device
=devices_original
[index
]
631 if "image" not in device
and "image name" not in device
:
633 disk_list
.append({'size': device
.get('size', default_volume_size
)})
636 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
637 image_dict
['universal_name']=device
.get('image name')
638 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
639 image_dict
['location']=device
.get('image')
640 #image_dict['new_location']=device.get('image location')
641 image_dict
['checksum']=device
.get('image checksum')
642 image_metadata_dict
= device
.get('image metadata', None)
643 image_metadata_str
= None
644 if image_metadata_dict
!= None:
645 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
646 image_dict
['metadata']=image_metadata_str
647 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
648 image_dict
["uuid"]=image_mano_id
649 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
651 #save disk information (image must be based on and size
652 disk_list
.append({'image_id': image_vim_id
, 'size': device
.get('size', default_volume_size
)})
654 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
657 #check that this vim_id exist in VIM, if not create
658 flavor_vim_id
=flavor_db
[0]["vim_id"]
660 vim
.get_flavor(flavor_vim_id
)
661 continue #flavor exist
662 except vimconn
.vimconnException
:
664 #create flavor at vim
665 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
668 flavor_vim_id
=vim
.get_flavor_id_from_data(flavor_dict
)
669 flavor_create
="false"
670 except vimconn
.vimconnException
as e
:
673 if not flavor_vim_id
:
674 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
675 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
676 flavor_created
="true"
677 except vimconn
.vimconnException
as e
:
679 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
681 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
684 #if reach here the flavor has been create or exist
685 if len(flavor_db
)==0:
686 #add new vim_id at datacenters_flavors
687 extended_devices_yaml
= None
688 if len(disk_list
) > 0:
689 extended_devices
= dict()
690 extended_devices
['disks'] = disk_list
691 extended_devices_yaml
= yaml
.safe_dump(extended_devices
,default_flow_style
=True,width
=256)
692 mydb
.new_row('datacenters_flavors',
693 {'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
, 'vim_id': flavor_vim_id
,
694 'created':flavor_created
,'extended': extended_devices_yaml
})
695 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
696 #modify existing vim_id at datacenters_flavors
697 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
699 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
702 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
705 # Step 1. Check the VNF descriptor
706 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
707 # Step 2. Check tenant exist
709 if tenant_id
!= "any":
710 check_tenant(mydb
, tenant_id
)
711 if "tenant_id" in vnf_descriptor
["vnf"]:
712 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
713 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
716 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
717 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
718 if global_config
["auto_push_VNF_to_VIMs"]:
719 vims
= get_vim(mydb
, tenant_id
)
721 # Step 4. Review the descriptor and add missing fields
722 #print vnf_descriptor
723 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
724 vnf_name
= vnf_descriptor
['vnf']['name']
725 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
726 if "physical" in vnf_descriptor
['vnf']:
727 del vnf_descriptor
['vnf']['physical']
728 #print vnf_descriptor
730 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
731 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
732 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
734 #For each VNFC, we add it to the VNFCDict and we create a flavor.
735 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
736 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
738 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
739 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
741 VNFCitem
["name"] = vnfc
['name']
742 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
744 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
747 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
748 myflavorDict
["description"] = VNFCitem
["description"]
749 myflavorDict
["ram"] = vnfc
.get("ram", 0)
750 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
751 myflavorDict
["disk"] = vnfc
.get("disk", 1)
752 myflavorDict
["extended"] = {}
754 devices
= vnfc
.get("devices")
756 myflavorDict
["extended"]["devices"] = devices
759 # 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
760 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
762 # Previous code has been commented
763 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
764 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
765 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
766 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
768 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
770 # print "Error creating flavor: unknown processor model. Rollback successful."
771 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
773 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
774 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
776 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
777 myflavorDict
['extended']['numas'] = vnfc
['numas']
781 # Step 6.2 New flavors are created in the VIM
782 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
784 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
785 VNFCitem
["flavor_id"] = flavor_id
786 VNFCDict
[vnfc
['name']] = VNFCitem
788 logger
.debug("Creating new images in the VIM for each VNFC")
789 # Step 6.3 New images are created in the VIM
790 #For each VNFC, we must create the appropriate image.
791 #This "for" loop might be integrated with the previous one
792 #In case this integration is made, the VNFCDict might become a VNFClist.
793 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
794 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
796 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
797 image_dict
['universal_name']=vnfc
.get('image name')
798 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
799 image_dict
['location']=vnfc
.get('VNFC image')
800 #image_dict['new_location']=vnfc.get('image location')
801 image_dict
['checksum']=vnfc
.get('image checksum')
802 image_metadata_dict
= vnfc
.get('image metadata', None)
803 image_metadata_str
= None
804 if image_metadata_dict
is not None:
805 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
806 image_dict
['metadata']=image_metadata_str
807 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
808 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
809 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
810 VNFCDict
[vnfc
['name']]["image_id"] = image_id
811 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
812 if vnfc
.get("boot-data"):
813 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
816 # Step 7. Storing the VNF descriptor in the repository
817 if "descriptor" not in vnf_descriptor
["vnf"]:
818 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
820 # Step 8. Adding the VNF to the NFVO DB
821 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
823 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
824 _
, message
= rollback(mydb
, vims
, rollback_list
)
825 if isinstance(e
, db_base_Exception
):
826 error_text
= "Exception at database"
827 elif isinstance(e
, KeyError):
828 error_text
= "KeyError exception "
829 e
.http_code
= HTTP_Internal_Server_Error
831 error_text
= "Exception at VIM"
832 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
833 #logger.error("start_scenario %s", error_text)
834 raise NfvoException(error_text
, e
.http_code
)
837 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
840 # Step 1. Check the VNF descriptor
841 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
842 # Step 2. Check tenant exist
844 if tenant_id
!= "any":
845 check_tenant(mydb
, tenant_id
)
846 if "tenant_id" in vnf_descriptor
["vnf"]:
847 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
848 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
851 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
852 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
853 if global_config
["auto_push_VNF_to_VIMs"]:
854 vims
= get_vim(mydb
, tenant_id
)
856 # Step 4. Review the descriptor and add missing fields
857 #print vnf_descriptor
858 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
859 vnf_name
= vnf_descriptor
['vnf']['name']
860 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
861 if "physical" in vnf_descriptor
['vnf']:
862 del vnf_descriptor
['vnf']['physical']
863 #print vnf_descriptor
865 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
866 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
867 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
869 #For each VNFC, we add it to the VNFCDict and we create a flavor.
870 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
871 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
873 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
874 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
876 VNFCitem
["name"] = vnfc
['name']
877 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
879 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
882 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
883 myflavorDict
["description"] = VNFCitem
["description"]
884 myflavorDict
["ram"] = vnfc
.get("ram", 0)
885 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
886 myflavorDict
["disk"] = vnfc
.get("disk", 1)
887 myflavorDict
["extended"] = {}
889 devices
= vnfc
.get("devices")
891 myflavorDict
["extended"]["devices"] = devices
894 # 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
895 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
897 # Previous code has been commented
898 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
899 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
900 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
901 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
903 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
905 # print "Error creating flavor: unknown processor model. Rollback successful."
906 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
908 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
909 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
911 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
912 myflavorDict
['extended']['numas'] = vnfc
['numas']
916 # Step 6.2 New flavors are created in the VIM
917 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
919 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
920 VNFCitem
["flavor_id"] = flavor_id
921 VNFCDict
[vnfc
['name']] = VNFCitem
923 logger
.debug("Creating new images in the VIM for each VNFC")
924 # Step 6.3 New images are created in the VIM
925 #For each VNFC, we must create the appropriate image.
926 #This "for" loop might be integrated with the previous one
927 #In case this integration is made, the VNFCDict might become a VNFClist.
928 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
929 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
931 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
932 image_dict
['universal_name']=vnfc
.get('image name')
933 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
934 image_dict
['location']=vnfc
.get('VNFC image')
935 #image_dict['new_location']=vnfc.get('image location')
936 image_dict
['checksum']=vnfc
.get('image checksum')
937 image_metadata_dict
= vnfc
.get('image metadata', None)
938 image_metadata_str
= None
939 if image_metadata_dict
is not None:
940 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
941 image_dict
['metadata']=image_metadata_str
942 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
943 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
944 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
945 VNFCDict
[vnfc
['name']]["image_id"] = image_id
946 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
947 if vnfc
.get("boot-data"):
948 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
950 # Step 7. Storing the VNF descriptor in the repository
951 if "descriptor" not in vnf_descriptor
["vnf"]:
952 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
954 # Step 8. Adding the VNF to the NFVO DB
955 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
957 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
958 _
, message
= rollback(mydb
, vims
, rollback_list
)
959 if isinstance(e
, db_base_Exception
):
960 error_text
= "Exception at database"
961 elif isinstance(e
, KeyError):
962 error_text
= "KeyError exception "
963 e
.http_code
= HTTP_Internal_Server_Error
965 error_text
= "Exception at VIM"
966 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
967 #logger.error("start_scenario %s", error_text)
968 raise NfvoException(error_text
, e
.http_code
)
971 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
972 #check valid tenant_id
973 check_tenant(mydb
, tenant_id
)
976 if tenant_id
!= "any":
977 where_or
["tenant_id"] = tenant_id
978 where_or
["public"] = True
979 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
982 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
983 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
984 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
985 data
={'vnf' : filtered_content
}
987 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
988 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description', 'boot_data'),
989 WHERE
={'vnfs.uuid': vnf_id
} )
991 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
992 # change boot_data into boot-data
994 if vm
.get("boot_data"):
995 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
998 data
['vnf']['VNFC'] = content
999 #TODO: GET all the information from a VNFC and include it in the output.
1002 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
1003 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
1004 WHERE
={'vnfs.uuid': vnf_id
} )
1005 data
['vnf']['nets'] = content
1007 #GET ip-profile for each net
1008 for net
in data
['vnf']['nets']:
1009 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1010 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1011 WHERE
={'net_id': net
["uuid"]} )
1012 if len(ipprofiles
)==1:
1013 net
["ip_profile"] = ipprofiles
[0]
1014 elif len(ipprofiles
)>1:
1015 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
1018 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1020 #GET External Interfaces
1021 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1022 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1023 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1024 WHERE
={'vnfs.uuid': vnf_id
},
1025 WHERE_NOT
={'interfaces.external_name': None} )
1027 data
['vnf']['external-connections'] = content
1032 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1033 # Check tenant exist
1034 if tenant_id
!= "any":
1035 check_tenant(mydb
, tenant_id
)
1036 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1037 vims
= get_vim(mydb
, tenant_id
)
1041 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1043 if tenant_id
!= "any":
1044 where_or
["tenant_id"] = tenant_id
1045 where_or
["public"] = True
1046 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1047 vnf_id
= vnf
["uuid"]
1049 # "Getting the list of flavors and tenants of the VNF"
1050 flavorList
= get_flavorlist(mydb
, vnf_id
)
1051 if len(flavorList
)==0:
1052 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1054 imageList
= get_imagelist(mydb
, vnf_id
)
1055 if len(imageList
)==0:
1056 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1058 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1060 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1063 for flavor
in flavorList
:
1064 #check if flavor is used by other vnf
1066 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1068 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1070 #flavor not used, must be deleted
1072 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
1073 for flavor_vim
in c
:
1074 if flavor_vim
["datacenter_id"] not in vims
:
1076 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
1078 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
1080 myvim
.delete_flavor(flavor_vim
["vim_id"])
1081 except vimconn
.vimconnNotFoundException
as e
:
1082 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
1083 except vimconn
.vimconnException
as e
:
1084 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1085 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1086 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
1087 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1088 mydb
.delete_row_by_id('flavors', flavor
)
1089 except db_base_Exception
as e
:
1090 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1091 undeletedItems
.append("flavor %s" % flavor
)
1094 for image
in imageList
:
1096 #check if image is used by other vnf
1097 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
1099 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1101 #image not used, must be deleted
1103 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1105 if image_vim
["datacenter_id"] not in vims
:
1107 if image_vim
['created']=='false': #skip this image because not created by openmano
1109 myvim
=vims
[ image_vim
["datacenter_id"] ]
1111 myvim
.delete_image(image_vim
["vim_id"])
1112 except vimconn
.vimconnNotFoundException
as e
:
1113 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1114 except vimconn
.vimconnException
as e
:
1115 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1116 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1117 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1118 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1119 mydb
.delete_row_by_id('images', image
)
1120 except db_base_Exception
as e
:
1121 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1122 undeletedItems
.append("image %s" % image
)
1124 return vnf_id
+ " " + vnf
["name"]
1126 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1129 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1130 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1134 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
1135 myvim
= vims
.values()[0]
1136 result
,servers
= myvim
.get_hosts_info()
1138 return result
, servers
1139 topology
= {'name':myvim
['name'] , 'servers': servers
}
1140 return result
, topology
1143 def get_hosts(mydb
, nfvo_tenant_id
):
1144 vims
= get_vim(mydb
, nfvo_tenant_id
)
1146 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
1148 #print "nfvo.datacenter_action() error. Several datacenters found"
1149 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1150 myvim
= vims
.values()[0]
1152 hosts
= myvim
.get_hosts()
1153 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1155 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1157 server
={'name':host
['name'], 'vms':[]}
1158 for vm
in host
['instances']:
1159 #get internal name and model
1161 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1162 WHERE
={'vim_vm_id':vm
['id']} )
1164 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1166 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1168 except db_base_Exception
as e
:
1169 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1170 datacenter
['Datacenters'][0]['servers'].append(server
)
1171 #return -400, "en construccion"
1173 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1175 except vimconn
.vimconnException
as e
:
1176 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1179 def new_scenario(mydb
, tenant_id
, topo
):
1181 # result, vims = get_vim(mydb, tenant_id)
1183 # return result, vims
1185 if tenant_id
!= "any":
1186 check_tenant(mydb
, tenant_id
)
1187 if "tenant_id" in topo
:
1188 if topo
["tenant_id"] != tenant_id
:
1189 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1194 #1.1: get VNFs and external_networks (other_nets).
1196 other_nets
={} #external_networks, bridge_networks and data_networkds
1197 nodes
= topo
['topology']['nodes']
1198 for k
in nodes
.keys():
1199 if nodes
[k
]['type'] == 'VNF':
1201 vnfs
[k
]['ifaces'] = {}
1202 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1203 other_nets
[k
] = nodes
[k
]
1204 other_nets
[k
]['external']=True
1205 elif nodes
[k
]['type'] == 'network':
1206 other_nets
[k
] = nodes
[k
]
1207 other_nets
[k
]['external']=False
1210 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1211 for name
,vnf
in vnfs
.items():
1213 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1215 error_pos
= "'topology':'nodes':'" + name
+ "'"
1217 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1218 where
['uuid'] = vnf
['vnf_id']
1219 if 'VNF model' in vnf
:
1220 error_text
+= " 'VNF model' " + vnf
['VNF model']
1221 where
['name'] = vnf
['VNF model']
1223 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
1225 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1231 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1233 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1234 vnf
['uuid']=vnf_db
[0]['uuid']
1235 vnf
['description']=vnf_db
[0]['description']
1236 #get external interfaces
1237 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1238 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1239 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1240 for ext_iface
in ext_ifaces
:
1241 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1243 #1.4 get list of connections
1244 conections
= topo
['topology']['connections']
1245 conections_list
= []
1246 conections_list_name
= []
1247 for k
in conections
.keys():
1248 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1249 ifaces_list
= conections
[k
]['nodes'].items()
1250 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1252 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1253 for k2
in conection_pair_list
:
1256 con_type
= conections
[k
].get("type", "link")
1257 if con_type
!= "link":
1259 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
1260 other_nets
[k
] = {'external': False}
1261 if conections
[k
].get("graph"):
1262 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1263 ifaces_list
.append( (k
, None) )
1266 if con_type
== "external_network":
1267 other_nets
[k
]['external'] = True
1268 if conections
[k
].get("model"):
1269 other_nets
[k
]["model"] = conections
[k
]["model"]
1271 other_nets
[k
]["model"] = k
1272 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1273 other_nets
[k
]["model"] = con_type
1275 conections_list_name
.append(k
)
1276 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)
1277 #print set(ifaces_list)
1278 #check valid VNF and iface names
1279 for iface
in ifaces_list
:
1280 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1281 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1282 str(k
), iface
[0]), HTTP_Not_Found
)
1283 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1284 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1285 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
1287 #1.5 unify connections from the pair list to a consolidated list
1289 while index
< len(conections_list
):
1291 while index2
< len(conections_list
):
1292 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1293 conections_list
[index
] |
= conections_list
[index2
]
1294 del conections_list
[index2
]
1295 del conections_list_name
[index2
]
1298 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1300 #for k in conections_list:
1305 #1.6 Delete non external nets
1306 # for k in other_nets.keys():
1307 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1308 # for con in conections_list:
1310 # for index in range(0,len(con)):
1311 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1312 # for index in delete_indexes:
1315 #1.7: Check external_ports are present at database table datacenter_nets
1316 for k
,net
in other_nets
.items():
1317 error_pos
= "'topology':'nodes':'" + k
+ "'"
1318 if net
['external']==False:
1319 if 'name' not in net
:
1321 if 'model' not in net
:
1322 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1323 if net
['model']=='bridge_net':
1324 net
['type']='bridge';
1325 elif net
['model']=='dataplane_net':
1328 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1330 #IF we do not want to check that external network exist at datacenter
1335 # if 'net_id' in net:
1336 # error_text += " 'net_id' " + net['net_id']
1337 # WHERE_['uuid'] = net['net_id']
1338 # if 'model' in net:
1339 # error_text += " 'model' " + net['model']
1340 # WHERE_['name'] = net['model']
1341 # if len(WHERE_) == 0:
1342 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1343 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1344 # FROM='datacenter_nets', WHERE=WHERE_ )
1346 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1348 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1349 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1351 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1352 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1353 # other_nets[k].update(net_db[0])
1356 net_nb
=0 #Number of nets
1357 for con
in conections_list
:
1358 #check if this is connected to a external net
1362 for index
in range(0,len(con
)):
1363 #check if this is connected to a external net
1364 for net_key
in other_nets
.keys():
1365 if con
[index
][0]==net_key
:
1366 if other_net_index
>=0:
1367 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1368 #print "nfvo.new_scenario " + error_text
1369 raise NfvoException(error_text
, HTTP_Bad_Request
)
1371 other_net_index
= index
1372 net_target
= net_key
1374 #print "other_net_index", other_net_index
1376 if other_net_index
>=0:
1377 del con
[other_net_index
]
1378 #IF we do not want to check that external network exist at datacenter
1379 if other_nets
[net_target
]['external'] :
1380 if "name" not in other_nets
[net_target
]:
1381 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1382 if other_nets
[net_target
]["type"] == "external_network":
1383 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1384 other_nets
[net_target
]["type"] = "data"
1386 other_nets
[net_target
]["type"] = "bridge"
1388 # if other_nets[net_target]['external'] :
1389 # 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
1390 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1391 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1392 # print "nfvo.new_scenario " + error_text
1393 # return -HTTP_Bad_Request, error_text
1396 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1399 net_type_bridge
=False
1401 net_target
= "__-__net"+str(net_nb
)
1402 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
1403 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1406 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1407 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1408 if iface_type
=='mgmt' or iface_type
=='bridge':
1409 net_type_bridge
= True
1411 net_type_data
= True
1412 if net_type_bridge
and net_type_data
:
1413 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1414 #print "nfvo.new_scenario " + error_text
1415 raise NfvoException(error_text
, HTTP_Bad_Request
)
1416 elif net_type_bridge
:
1419 type_
='data' if len(con
)>2 else 'ptp'
1420 net_list
[net_target
]['type'] = type_
1423 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1424 #print "nfvo.new_scenario " + error_text
1426 raise NfvoException(error_text
, HTTP_Bad_Request
)
1428 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1429 #1.8.1 obtain management net
1430 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1431 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1432 #1.8.2 check all interfaces from all vnfs
1434 add_mgmt_net
= False
1435 for vnf
in vnfs
.values():
1436 for iface
in vnf
['ifaces'].values():
1437 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1438 #iface not connected
1439 iface
['net_key'] = 'mgmt'
1441 if add_mgmt_net
and 'mgmt' not in net_list
:
1442 net_list
['mgmt']=mgmt_net
[0]
1443 net_list
['mgmt']['external']=True
1444 net_list
['mgmt']['graph']={'visible':False}
1446 net_list
.update(other_nets
)
1448 #print 'net_list', net_list
1453 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1454 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1455 'tenant_id':tenant_id
, 'name':topo
['name'],
1456 'description':topo
.get('description',topo
['name']),
1457 'public': topo
.get('public', False)
1463 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
1464 """ This creates a new scenario for version 0.2 and 0.3"""
1465 scenario
= scenario_dict
["scenario"]
1466 if tenant_id
!= "any":
1467 check_tenant(mydb
, tenant_id
)
1468 if "tenant_id" in scenario
:
1469 if scenario
["tenant_id"] != tenant_id
:
1470 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1471 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1472 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1476 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
1477 for name
,vnf
in scenario
["vnfs"].iteritems():
1479 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1481 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1483 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1484 where
['uuid'] = vnf
['vnf_id']
1485 if 'vnf_name' in vnf
:
1486 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1487 where
['name'] = vnf
['vnf_name']
1489 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1490 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
1495 if len(vnf_db
) == 0:
1496 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1497 elif len(vnf_db
) > 1:
1498 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1499 vnf
['uuid'] = vnf_db
[0]['uuid']
1500 vnf
['description'] = vnf_db
[0]['description']
1502 # get external interfaces
1503 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
1504 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1505 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name': None} )
1506 for ext_iface
in ext_ifaces
:
1507 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
1508 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1510 # 2: Insert net_key and ip_address at every vnf interface
1511 for net_name
, net
in scenario
["networks"].items():
1512 net_type_bridge
= False
1513 net_type_data
= False
1514 for iface_dict
in net
["interfaces"]:
1515 if version
== "0.2":
1516 temp_dict
= iface_dict
1518 elif version
== "0.3":
1519 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
1520 ip_address
= iface_dict
.get('ip_address', None)
1521 for vnf
, iface
in temp_dict
.items():
1522 if vnf
not in scenario
["vnfs"]:
1523 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
1525 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1526 raise NfvoException(error_text
, HTTP_Not_Found
)
1527 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1528 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
1529 .format(net_name
, iface
)
1530 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1531 raise NfvoException(error_text
, HTTP_Bad_Request
)
1532 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1533 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
1534 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1535 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1536 raise NfvoException(error_text
, HTTP_Bad_Request
)
1537 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1538 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
1539 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1540 if iface_type
== 'mgmt' or iface_type
== 'bridge':
1541 net_type_bridge
= True
1543 net_type_data
= True
1545 if net_type_bridge
and net_type_data
:
1546 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
1548 # logger.debug("nfvo.new_scenario " + error_text)
1549 raise NfvoException(error_text
, HTTP_Bad_Request
)
1550 elif net_type_bridge
:
1553 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
1555 if net
.get("implementation"): # for v0.3
1556 if type_
== "bridge" and net
["implementation"] == "underlay":
1557 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
1558 "'network':'{}'".format(net_name
)
1559 # logger.debug(error_text)
1560 raise NfvoException(error_text
, HTTP_Bad_Request
)
1561 elif type_
!= "bridge" and net
["implementation"] == "overlay":
1562 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
1563 "'network':'{}'".format(net_name
)
1564 # logger.debug(error_text)
1565 raise NfvoException(error_text
, HTTP_Bad_Request
)
1566 net
.pop("implementation")
1567 if "type" in net
and version
== "0.3": # for v0.3
1568 if type_
== "data" and net
["type"] == "e-line":
1569 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
1570 "'e-line' at 'network':'{}'".format(net_name
)
1571 # logger.debug(error_text)
1572 raise NfvoException(error_text
, HTTP_Bad_Request
)
1573 elif type_
== "ptp" and net
["type"] == "e-lan":
1577 net
['name'] = net_name
1578 net
['external'] = net
.get('external', False)
1580 # 3: insert at database
1581 scenario
["nets"] = scenario
["networks"]
1582 scenario
['tenant_id'] = tenant_id
1583 scenario_id
= mydb
.new_scenario(scenario
)
1587 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1588 data
["uuid"] = scenario_id
1589 data
["tenant_id"] = tenant_id
1590 c
= mydb
.edit_scenario( data
)
1594 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1595 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1596 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
1597 vims
= {datacenter_id
: myvim
}
1598 myvim_tenant
= myvim
['tenant_id']
1599 datacenter_name
= myvim
['name']
1603 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1604 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1605 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
1606 scenarioDict
['datacenter_id'] = datacenter_id
1607 #print '================scenarioDict======================='
1608 #print json.dumps(scenarioDict, indent=4)
1609 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1611 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
1612 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1614 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1615 auxNetDict
['scenario'] = {}
1617 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1618 for sce_net
in scenarioDict
['nets']:
1619 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1621 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1622 myNetName
= myNetName
[0:255] #limit length
1623 myNetType
= sce_net
['type']
1625 myNetDict
["name"] = myNetName
1626 myNetDict
["type"] = myNetType
1627 myNetDict
["tenant_id"] = myvim_tenant
1628 myNetIPProfile
= sce_net
.get('ip_profile', None)
1630 #We should use the dictionary as input parameter for new_network
1632 if not sce_net
["external"]:
1633 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1634 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1635 sce_net
['vim_id'] = network_id
1636 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1637 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1638 sce_net
["created"] = True
1640 if sce_net
['vim_id'] == None:
1641 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1642 _
, message
= rollback(mydb
, vims
, rollbackList
)
1643 logger
.error("nfvo.start_scenario: %s", error_text
)
1644 raise NfvoException(error_text
, HTTP_Bad_Request
)
1645 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1646 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1648 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1649 #For each vnf net, we create it and we add it to instanceNetlist.
1650 for sce_vnf
in scenarioDict
['vnfs']:
1651 for net
in sce_vnf
['nets']:
1652 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1654 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1655 myNetName
= myNetName
[0:255] #limit length
1656 myNetType
= net
['type']
1658 myNetDict
["name"] = myNetName
1659 myNetDict
["type"] = myNetType
1660 myNetDict
["tenant_id"] = myvim_tenant
1661 myNetIPProfile
= net
.get('ip_profile', None)
1664 #We should use the dictionary as input parameter for new_network
1665 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1666 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1667 net
['vim_id'] = network_id
1668 if sce_vnf
['uuid'] not in auxNetDict
:
1669 auxNetDict
[sce_vnf
['uuid']] = {}
1670 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1671 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1672 net
["created"] = True
1674 #print "auxNetDict:"
1675 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1677 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1678 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1680 for sce_vnf
in scenarioDict
['vnfs']:
1681 for vm
in sce_vnf
['vms']:
1684 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1685 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
1686 #myVMDict['description'] = vm['description']
1687 myVMDict
['description'] = myVMDict
['name'][0:99]
1689 myVMDict
['start'] = "no"
1690 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1691 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1693 #create image at vim in case it not exist
1694 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1695 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1696 vm
['vim_image_id'] = image_id
1698 #create flavor at vim in case it not exist
1699 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1700 if flavor_dict
['extended']!=None:
1701 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1702 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1703 vm
['vim_flavor_id'] = flavor_id
1706 myVMDict
['imageRef'] = vm
['vim_image_id']
1707 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1708 myVMDict
['networks'] = []
1709 for iface
in vm
['interfaces']:
1711 if iface
['type']=="data":
1712 netDict
['type'] = iface
['model']
1713 elif "model" in iface
and iface
["model"]!=None:
1714 netDict
['model']=iface
['model']
1715 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1716 #discover type of interface looking at flavor
1717 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1718 for flavor_iface
in numa
.get('interfaces',[]):
1719 if flavor_iface
.get('name') == iface
['internal_name']:
1720 if flavor_iface
['dedicated'] == 'yes':
1721 netDict
['type']="PF" #passthrough
1722 elif flavor_iface
['dedicated'] == 'no':
1723 netDict
['type']="VF" #siov
1724 elif flavor_iface
['dedicated'] == 'yes:sriov':
1725 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1726 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1728 netDict
["use"]=iface
['type']
1729 if netDict
["use"]=="data" and not netDict
.get("type"):
1730 #print "netDict", netDict
1731 #print "iface", iface
1732 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'])
1733 if flavor_dict
.get('extended')==None:
1734 raise NfvoException(e_text
+ "After database migration some information is not available. \
1735 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1737 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1738 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1739 netDict
["type"]="virtual"
1740 if "vpci" in iface
and iface
["vpci"] is not None:
1741 netDict
['vpci'] = iface
['vpci']
1742 if "mac" in iface
and iface
["mac"] is not None:
1743 netDict
['mac_address'] = iface
['mac']
1744 if "port-security" in iface
and iface
["port-security"] is not None:
1745 netDict
['port_security'] = iface
['port-security']
1746 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
1747 netDict
['floating_ip'] = iface
['floating-ip']
1748 netDict
['name'] = iface
['internal_name']
1749 if iface
['net_id'] is None:
1750 for vnf_iface
in sce_vnf
["interfaces"]:
1753 if vnf_iface
['interface_id']==iface
['uuid']:
1754 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1757 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1758 #skip bridge ifaces not connected to any net
1759 #if 'net_id' not in netDict or netDict['net_id']==None:
1761 myVMDict
['networks'].append(netDict
)
1762 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1763 #print myVMDict['name']
1764 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1765 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1766 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1767 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1768 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1769 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1770 vm
['vim_id'] = vm_id
1771 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1772 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1773 for net
in myVMDict
['networks']:
1775 for iface
in vm
['interfaces']:
1776 if net
["name"]==iface
["internal_name"]:
1777 iface
["vim_id"]=net
["vim_id"]
1780 logger
.debug("start scenario Deployment done")
1781 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1782 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1783 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1784 return mydb
.get_instance_scenario(instance_id
)
1786 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1787 _
, message
= rollback(mydb
, vims
, rollbackList
)
1788 if isinstance(e
, db_base_Exception
):
1789 error_text
= "Exception at database"
1791 error_text
= "Exception at VIM"
1792 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1793 #logger.error("start_scenario %s", error_text)
1794 raise NfvoException(error_text
, e
.http_code
)
1797 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
1798 ''' join the cloud config information into cloud_config_preserve.
1799 In case of conflict cloud_config_preserve preserves
1802 if not cloud_config_preserve
and not cloud_config
:
1805 new_cloud_config
= {"key-pairs":[], "users":[]}
1807 if cloud_config_preserve
:
1808 for key
in cloud_config_preserve
.get("key-pairs", () ):
1809 if key
not in new_cloud_config
["key-pairs"]:
1810 new_cloud_config
["key-pairs"].append(key
)
1812 for key
in cloud_config
.get("key-pairs", () ):
1813 if key
not in new_cloud_config
["key-pairs"]:
1814 new_cloud_config
["key-pairs"].append(key
)
1815 if not new_cloud_config
["key-pairs"]:
1816 del new_cloud_config
["key-pairs"]
1820 new_cloud_config
["users"] += cloud_config
.get("users", () )
1821 if cloud_config_preserve
:
1822 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
1823 index_to_delete
= []
1824 users
= new_cloud_config
.get("users", [])
1825 for index0
in range(0,len(users
)):
1826 if index0
in index_to_delete
:
1828 for index1
in range(index0
+1,len(users
)):
1829 if index1
in index_to_delete
:
1831 if users
[index0
]["name"] == users
[index1
]["name"]:
1832 index_to_delete
.append(index1
)
1833 for key
in users
[index1
].get("key-pairs",()):
1834 if "key-pairs" not in users
[index0
]:
1835 users
[index0
]["key-pairs"] = [key
]
1836 elif key
not in users
[index0
]["key-pairs"]:
1837 users
[index0
]["key-pairs"].append(key
)
1838 index_to_delete
.sort(reverse
=True)
1839 for index
in index_to_delete
:
1841 if not new_cloud_config
["users"]:
1842 del new_cloud_config
["users"]
1845 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
1846 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
1847 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
1848 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
1851 if cloud_config
and cloud_config
.get("user-data") != None:
1852 new_cloud_config
["user-data"] = cloud_config
["user-data"]
1853 if cloud_config_preserve
and cloud_config_preserve
.get("user-data") != None:
1854 new_cloud_config
["user-data"] = cloud_config_preserve
["user-data"]
1857 new_cloud_config
["config-files"] = []
1858 if cloud_config
and cloud_config
.get("config-files") != None:
1859 new_cloud_config
["config-files"] += cloud_config
["config-files"]
1860 if cloud_config_preserve
:
1861 for file in cloud_config_preserve
.get("config-files", ()):
1862 for index
in range(0, len(new_cloud_config
["config-files"])):
1863 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
1864 new_cloud_config
["config-files"][index
] = file
1867 new_cloud_config
["config-files"].append(file)
1868 if not new_cloud_config
["config-files"]:
1869 del new_cloud_config
["config-files"]
1870 return new_cloud_config
1873 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
1874 datacenter_id
= None
1875 datacenter_name
= None
1878 if datacenter_tenant_id
:
1879 thread_id
= datacenter_tenant_id
1880 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
1882 where_
={"td.nfvo_tenant_id": tenant_id
}
1883 if datacenter_id_name
:
1884 if utils
.check_valid_uuid(datacenter_id_name
):
1885 datacenter_id
= datacenter_id_name
1886 where_
["dt.datacenter_id"] = datacenter_id
1888 datacenter_name
= datacenter_id_name
1889 where_
["d.name"] = datacenter_name
1890 if datacenter_tenant_id
:
1891 where_
["dt.uuid"] = datacenter_tenant_id
1892 datacenters
= mydb
.get_rows(
1893 SELECT
=("dt.uuid as datacenter_tenant_id",),
1894 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
1895 "join datacenters as d on d.uuid=dt.datacenter_id",
1897 if len(datacenters
) > 1:
1898 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1900 thread_id
= datacenters
[0]["datacenter_tenant_id"]
1901 thread
= vim_threads
["running"].get(thread_id
)
1903 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1904 return thread_id
, thread
1905 except db_base_Exception
as e
:
1906 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
1908 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
1909 datacenter_id
= None
1910 datacenter_name
= None
1911 if datacenter_id_name
:
1912 if utils
.check_valid_uuid(datacenter_id_name
):
1913 datacenter_id
= datacenter_id_name
1915 datacenter_name
= datacenter_id_name
1916 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
1918 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1920 #print "nfvo.datacenter_action() error. Several datacenters found"
1921 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1922 return vims
.keys()[0], vims
.values()[0]
1926 '''Takes dict d and updates it with the values in dict u.'''
1927 '''It merges all depth levels'''
1928 for k
, v
in u
.iteritems():
1929 if isinstance(v
, collections
.Mapping
):
1930 r
= update(d
.get(k
, {}), v
)
1937 def create_instance(mydb
, tenant_id
, instance_dict
):
1938 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1939 # logger.debug("Creating instance...")
1940 scenario
= instance_dict
["scenario"]
1942 #find main datacenter
1944 myvim_threads_id
= {}
1947 datacenter
= instance_dict
.get("datacenter")
1948 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
1949 myvims
[default_datacenter_id
] = vim
1950 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
1951 tasks_to_launch
[myvim_threads_id
[default_datacenter_id
]] = []
1952 #myvim_tenant = myvim['tenant_id']
1953 # default_datacenter_name = vim['name']
1956 #print "Checking that the scenario exists and getting the scenario dictionary"
1957 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, default_datacenter_id
)
1959 #logger.debug(">>>>>>> Dictionaries before merging")
1960 #logger.debug(">>>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
1961 #logger.debug(">>>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
1963 scenarioDict
['datacenter_id'] = default_datacenter_id
1965 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1966 auxNetDict
['scenario'] = {}
1968 logger
.debug("Creating instance from scenario-dict:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)) #TODO remove
1969 instance_name
= instance_dict
["name"]
1970 instance_description
= instance_dict
.get("description")
1972 # 0 check correct parameters
1973 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1975 for scenario_net
in scenarioDict
['nets']:
1976 if net_name
== scenario_net
["name"]:
1980 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
), HTTP_Bad_Request
)
1981 if "sites" not in net_instance_desc
:
1982 net_instance_desc
["sites"] = [ {} ]
1983 site_without_datacenter_field
= False
1984 for site
in net_instance_desc
["sites"]:
1985 if site
.get("datacenter"):
1986 if site
["datacenter"] not in myvims
:
1987 #Add this datacenter to myvims
1988 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
1990 myvim_threads_id
[d
],_
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
1991 tasks_to_launch
[myvim_threads_id
[d
]] = []
1992 site
["datacenter"] = d
#change name to id
1994 if site_without_datacenter_field
:
1995 raise NfvoException("Found more than one entries without datacenter field at instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
1996 site_without_datacenter_field
= True
1997 site
["datacenter"] = default_datacenter_id
#change name to id
1999 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
2001 for scenario_vnf
in scenarioDict
['vnfs']:
2002 if vnf_name
== scenario_vnf
['name']:
2006 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
2007 if "datacenter" in vnf_instance_desc
:
2008 # Add this datacenter to myvims
2009 if vnf_instance_desc
["datacenter"] not in myvims
:
2010 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2012 myvim_threads_id
[d
],_
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2013 tasks_to_launch
[myvim_threads_id
[d
]] = []
2014 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
2016 #0.1 parse cloud-config parameters
2017 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
2019 #0.2 merge instance information into scenario
2020 #Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
2021 #However, this is not possible yet.
2022 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
2023 for scenario_net
in scenarioDict
['nets']:
2024 if net_name
== scenario_net
["name"]:
2025 if 'ip-profile' in net_instance_desc
:
2026 ipprofile
= net_instance_desc
['ip-profile']
2027 ipprofile
['subnet_address'] = ipprofile
.pop('subnet-address',None)
2028 ipprofile
['ip_version'] = ipprofile
.pop('ip-version','IPv4')
2029 ipprofile
['gateway_address'] = ipprofile
.pop('gateway-address',None)
2030 ipprofile
['dns_address'] = ipprofile
.pop('dns-address',None)
2031 if 'dhcp' in ipprofile
:
2032 ipprofile
['dhcp_start_address'] = ipprofile
['dhcp'].get('start-address',None)
2033 ipprofile
['dhcp_enabled'] = ipprofile
['dhcp'].get('enabled',True)
2034 ipprofile
['dhcp_count'] = ipprofile
['dhcp'].get('count',None)
2035 del ipprofile
['dhcp']
2036 if 'ip_profile' not in scenario_net
:
2037 scenario_net
['ip_profile'] = ipprofile
2039 update(scenario_net
['ip_profile'],ipprofile
)
2040 for interface
in net_instance_desc
.get('interfaces', () ):
2041 if 'ip_address' in interface
:
2042 for vnf
in scenarioDict
['vnfs']:
2043 if interface
['vnf'] == vnf
['name']:
2044 for vnf_interface
in vnf
['interfaces']:
2045 if interface
['vnf_interface'] == vnf_interface
['external_name']:
2046 vnf_interface
['ip_address']=interface
['ip_address']
2048 #logger.debug(">>>>>>>> Merged dictionary")
2049 logger
.debug("Creating instance scenario-dict MERGED:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False))
2052 # 1. Creating new nets (sce_nets) in the VIM"
2053 for sce_net
in scenarioDict
['nets']:
2054 sce_net
["vim_id_sites"]={}
2055 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
2056 net_name
= descriptor_net
.get("vim-network-name")
2057 auxNetDict
['scenario'][sce_net
['uuid']] = {}
2059 sites
= descriptor_net
.get("sites", [ {} ])
2061 if site
.get("datacenter"):
2062 vim
= myvims
[ site
["datacenter"] ]
2063 datacenter_id
= site
["datacenter"]
2064 myvim_thread_id
= myvim_threads_id
[ site
["datacenter"] ]
2066 vim
= myvims
[ default_datacenter_id
]
2067 datacenter_id
= default_datacenter_id
2068 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2069 net_type
= sce_net
['type']
2070 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
2071 if sce_net
["external"]:
2073 net_name
= sce_net
["name"]
2074 if "netmap-use" in site
or "netmap-create" in site
:
2075 create_network
= False
2076 lookfor_network
= False
2077 if "netmap-use" in site
:
2078 lookfor_network
= True
2079 if utils
.check_valid_uuid(site
["netmap-use"]):
2080 filter_text
= "scenario id '%s'" % site
["netmap-use"]
2081 lookfor_filter
["id"] = site
["netmap-use"]
2083 filter_text
= "scenario name '%s'" % site
["netmap-use"]
2084 lookfor_filter
["name"] = site
["netmap-use"]
2085 if "netmap-create" in site
:
2086 create_network
= True
2087 net_vim_name
= net_name
2088 if site
["netmap-create"]:
2089 net_vim_name
= site
["netmap-create"]
2091 elif sce_net
['vim_id'] != None:
2092 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
2093 create_network
= False
2094 lookfor_network
= True
2095 lookfor_filter
["id"] = sce_net
['vim_id']
2096 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
2097 #look for network at datacenter and return error
2099 #There is not a netmap, look at datacenter for a net with this name and create if not found
2100 create_network
= True
2101 lookfor_network
= True
2102 lookfor_filter
["name"] = sce_net
["name"]
2103 net_vim_name
= sce_net
["name"]
2104 filter_text
= "scenario name '%s'" % sce_net
["name"]
2107 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
2108 net_name
= net_name
[:255] #limit length
2109 net_vim_name
= net_name
2110 create_network
= True
2111 lookfor_network
= False
2114 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
2115 if len(vim_nets
) > 1:
2116 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2117 elif len(vim_nets
) == 0:
2118 if not create_network
:
2119 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2121 sce_net
["vim_id_sites"][datacenter_id
] = vim_nets
[0]['id']
2122 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
2123 create_network
= False
2125 #if network is not external
2126 task
= new_task("new-net", (net_vim_name
, net_type
, sce_net
.get('ip_profile',None)))
2127 task_id
= task
["id"]
2128 instance_tasks
[task_id
] = task
2129 tasks_to_launch
[myvim_thread_id
].append(task
)
2130 #network_id = vim.new_network(net_vim_name, net_type, sce_net.get('ip_profile',None))
2131 sce_net
["vim_id_sites"][datacenter_id
] = task_id
2132 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = task_id
2133 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':task_id
})
2134 sce_net
["created"] = True
2136 # 2. Creating new nets (vnf internal nets) in the VIM"
2137 #For each vnf net, we create it and we add it to instanceNetlist.
2138 for sce_vnf
in scenarioDict
['vnfs']:
2139 for net
in sce_vnf
['nets']:
2140 if sce_vnf
.get("datacenter"):
2141 vim
= myvims
[ sce_vnf
["datacenter"] ]
2142 datacenter_id
= sce_vnf
["datacenter"]
2143 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"]]
2145 vim
= myvims
[ default_datacenter_id
]
2146 datacenter_id
= default_datacenter_id
2147 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2148 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
2149 net_name
= descriptor_net
.get("name")
2151 net_name
= "%s.%s" %(instance_name
, net
["name"])
2152 net_name
= net_name
[:255] #limit length
2153 net_type
= net
['type']
2154 task
= new_task("new-net", (net_name
, net_type
, net
.get('ip_profile',None)))
2155 task_id
= task
["id"]
2156 instance_tasks
[task_id
] = task
2157 tasks_to_launch
[myvim_thread_id
].append(task
)
2158 # network_id = vim.new_network(net_name, net_type, net.get('ip_profile',None))
2159 net
['vim_id'] = task_id
2160 if sce_vnf
['uuid'] not in auxNetDict
:
2161 auxNetDict
[sce_vnf
['uuid']] = {}
2162 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = task_id
2163 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':task_id
})
2164 net
["created"] = True
2167 #print "auxNetDict:"
2168 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2170 # 3. Creating new vm instances in the VIM
2171 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2172 for sce_vnf
in scenarioDict
['vnfs']:
2173 if sce_vnf
.get("datacenter"):
2174 vim
= myvims
[ sce_vnf
["datacenter"] ]
2175 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"] ]
2176 datacenter_id
= sce_vnf
["datacenter"]
2178 vim
= myvims
[ default_datacenter_id
]
2179 myvim_thread_id
= myvim_threads_id
[ default_datacenter_id
]
2180 datacenter_id
= default_datacenter_id
2181 sce_vnf
["datacenter_id"] = datacenter_id
2183 for vm
in sce_vnf
['vms']:
2186 myVMDict
['name'] = "{}.{}.{}".format(instance_name
,sce_vnf
['name'],chr(96+i
))
2187 myVMDict
['description'] = myVMDict
['name'][0:99]
2189 # myVMDict['start'] = "no"
2190 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2191 #create image at vim in case it not exist
2192 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2193 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
2194 vm
['vim_image_id'] = image_id
2196 #create flavor at vim in case it not exist
2197 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2198 if flavor_dict
['extended']!=None:
2199 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2200 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
2202 #Obtain information for additional disks
2203 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',), WHERE
={'vim_id': flavor_id
})
2204 if not extended_flavor_dict
:
2205 raise NfvoException("flavor '{}' not found".format(flavor_id
), HTTP_Not_Found
)
2208 #extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
2209 myVMDict
['disks'] = None
2210 extended_info
= extended_flavor_dict
[0]['extended']
2211 if extended_info
!= None:
2212 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
2213 if 'disks' in extended_flavor_dict_yaml
:
2214 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
2216 vm
['vim_flavor_id'] = flavor_id
2217 myVMDict
['imageRef'] = vm
['vim_image_id']
2218 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2219 myVMDict
['networks'] = []
2221 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
2222 for iface
in vm
['interfaces']:
2224 if iface
['type']=="data":
2225 netDict
['type'] = iface
['model']
2226 elif "model" in iface
and iface
["model"]!=None:
2227 netDict
['model']=iface
['model']
2228 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2229 #discover type of interface looking at flavor
2230 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2231 for flavor_iface
in numa
.get('interfaces',[]):
2232 if flavor_iface
.get('name') == iface
['internal_name']:
2233 if flavor_iface
['dedicated'] == 'yes':
2234 netDict
['type']="PF" #passthrough
2235 elif flavor_iface
['dedicated'] == 'no':
2236 netDict
['type']="VF" #siov
2237 elif flavor_iface
['dedicated'] == 'yes:sriov':
2238 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2239 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2241 netDict
["use"]=iface
['type']
2242 if netDict
["use"]=="data" and not netDict
.get("type"):
2243 #print "netDict", netDict
2244 #print "iface", iface
2245 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'])
2246 if flavor_dict
.get('extended')==None:
2247 raise NfvoException(e_text
+ "After database migration some information is not available. \
2248 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
2250 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
2251 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2252 netDict
["type"]="virtual"
2253 if "vpci" in iface
and iface
["vpci"] is not None:
2254 netDict
['vpci'] = iface
['vpci']
2255 if "mac" in iface
and iface
["mac"] is not None:
2256 netDict
['mac_address'] = iface
['mac']
2257 if "port-security" in iface
and iface
["port-security"] is not None:
2258 netDict
['port_security'] = iface
['port-security']
2259 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2260 netDict
['floating_ip'] = iface
['floating-ip']
2261 netDict
['name'] = iface
['internal_name']
2262 if iface
['net_id'] is None:
2263 for vnf_iface
in sce_vnf
["interfaces"]:
2266 if vnf_iface
['interface_id']==iface
['uuid']:
2267 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
2270 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2271 if netDict
.get('net_id') and is_task_id(netDict
['net_id']):
2272 task_depends
[netDict
['net_id']] = instance_tasks
[netDict
['net_id']]
2273 #skip bridge ifaces not connected to any net
2274 #if 'net_id' not in netDict or netDict['net_id']==None:
2276 myVMDict
['networks'].append(netDict
)
2277 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2278 #print myVMDict['name']
2279 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2280 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2281 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2282 if vm
.get("boot_data"):
2283 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config
)
2285 cloud_config_vm
= cloud_config
2286 task
= new_task("new-vm", (myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2287 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2288 cloud_config_vm
, myVMDict
['disks']), depends
=task_depends
)
2289 instance_tasks
[task
["id"]] = task
2290 tasks_to_launch
[myvim_thread_id
].append(task
)
2292 vm
['vim_id'] = vm_id
2293 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2294 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2295 for net
in myVMDict
['networks']:
2297 for iface
in vm
['interfaces']:
2298 if net
["name"]==iface
["internal_name"]:
2299 iface
["vim_id"]=net
["vim_id"]
2301 scenarioDict
["datacenter2tenant"] = myvim_threads_id
2302 logger
.debug("create_instance Deployment done scenarioDict: %s",
2303 yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False) )
2304 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
2305 for myvim_thread_id
,task_list
in tasks_to_launch
.items():
2306 for task
in task_list
:
2307 vim_threads
["running"][myvim_thread_id
].insert_task(task
)
2309 global_instance_tasks
[instance_id
] = instance_tasks
2310 # Update database with those ended instance_tasks
2311 # for task in instance_tasks.values():
2312 # if task["status"] == "ok":
2313 # if task["name"] == "new-vm":
2314 # mydb.update_rows("instance_vms", UPDATE={"vim_vm_id": task["result"]},
2315 # WHERE={"vim_vm_id": task["id"]})
2316 # elif task["name"] == "new-net":
2317 # mydb.update_rows("instance_nets", UPDATE={"vim_net_id": task["result"]},
2318 # WHERE={"vim_net_id": task["id"]})
2319 return mydb
.get_instance_scenario(instance_id
)
2320 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
2321 message
= rollback(mydb
, myvims
, rollbackList
)
2322 if isinstance(e
, db_base_Exception
):
2323 error_text
= "database Exception"
2324 elif isinstance(e
, vimconn
.vimconnException
):
2325 error_text
= "VIM Exception"
2327 error_text
= "Exception"
2328 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2329 #logger.error("create_instance: %s", error_text)
2330 raise NfvoException(error_text
, e
.http_code
)
2333 def delete_instance(mydb
, tenant_id
, instance_id
):
2334 #print "Checking that the instance_id exists and getting the instance dictionary"
2335 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
2336 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2337 tenant_id
= instanceDict
["tenant_id"]
2338 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2340 #1. Delete from Database
2341 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
2350 for sce_vnf
in instanceDict
['vnfs']:
2351 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2352 if datacenter_key
not in myvims
:
2354 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2355 except NfvoException
as e
:
2356 logger
.error(str(e
))
2358 myvim_threads
[datacenter_key
] = myvim_thread
2359 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
2360 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2362 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
2363 sce_vnf
["datacenter_tenant_id"]))
2364 myvims
[datacenter_key
] = None
2366 myvims
[datacenter_key
] = vims
.values()[0]
2367 myvim
= myvims
[datacenter_key
]
2368 myvim_thread
= myvim_threads
[datacenter_key
]
2369 for vm
in sce_vnf
['vms']:
2371 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2375 if is_task_id(vm
['vim_vm_id']):
2376 task_id
= vm
['vim_vm_id']
2377 old_task
= global_instance_tasks
[instance_id
].get(task_id
)
2379 error_msg
+= "\n VM was scheduled for create, but task {} is not found".format(task_id
)
2382 if old_task
["status"] == "enqueued":
2383 old_task
["status"] = "deleted"
2384 elif old_task
["status"] == "error":
2386 elif old_task
["status"] == "processing":
2387 task
= new_task("del-vm", (task_id
, vm
["interfaces"]), depends
={task_id
: old_task
})
2389 task
= new_task("del-vm", (old_task
["result"], vm
["interfaces"]))
2391 task
= new_task("del-vm", (vm
['vim_vm_id'], vm
["interfaces"]) )
2393 myvim_thread
.insert_task(task
)
2394 except vimconn
.vimconnNotFoundException
as e
:
2395 error_msg
+="\n VM VIM_id={} not found at datacenter={}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2396 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
2397 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
2398 except vimconn
.vimconnException
as e
:
2399 error_msg
+="\n VM VIM_id={} at datacenter={} Error: {} {}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"], e
.http_code
, str(e
))
2400 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s",
2401 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
2405 for net
in instanceDict
['nets']:
2406 if not net
['created']:
2407 continue #skip not created nets
2408 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2409 if datacenter_key
not in myvims
:
2411 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2412 except NfvoException
as e
:
2413 logger
.error(str(e
))
2415 myvim_threads
[datacenter_key
] = myvim_thread
2416 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
2417 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2419 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2420 myvims
[datacenter_key
] = None
2422 myvims
[datacenter_key
] = vims
.values()[0]
2423 myvim
= myvims
[datacenter_key
]
2424 myvim_thread
= myvim_threads
[datacenter_key
]
2427 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
2431 if is_task_id(net
['vim_net_id']):
2432 task_id
= net
['vim_net_id']
2433 old_task
= global_instance_tasks
[instance_id
].get(task_id
)
2435 error_msg
+= "\n NET was scheduled for create, but task {} is not found".format(task_id
)
2438 if old_task
["status"] == "enqueued":
2439 old_task
["status"] = "deleted"
2440 elif old_task
["status"] == "error":
2442 elif old_task
["status"] == "processing":
2443 task
= new_task("del-net", task_id
, depends
={task_id
: old_task
})
2445 task
= new_task("del-net", old_task
["result"])
2447 task
= new_task("del-net", (net
['vim_net_id'], net
['sdn_net_id']))
2449 myvim_thread
.insert_task(task
)
2450 except vimconn
.vimconnNotFoundException
as e
:
2451 error_msg
+= "\n NET VIM_id={} not found at datacenter={}".format(net
['vim_net_id'], net
["datacenter_id"])
2452 logger
.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found",
2453 net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']))
2454 except vimconn
.vimconnException
as e
:
2455 error_msg
+= "\n NET VIM_id={} at datacenter={} Error: {} {}".format(net
['vim_net_id'],
2456 net
["datacenter_id"],
2457 e
.http_code
, str(e
))
2458 logger
.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s",
2459 e
.http_code
, net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']), str(e
))
2460 if len(error_msg
) > 0:
2461 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
2463 return 'instance ' + message
+ ' deleted'
2466 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
2467 '''Refreshes a scenario instance. It modifies instanceDict'''
2469 - 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
2472 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
2473 # #print "nfvo.refresh_instance begins"
2474 # #print json.dumps(instanceDict, indent=4)
2476 # #print "Getting the VIM URL and the VIM tenant_id"
2479 # # 1. Getting VIM vm and net list
2480 # vms_updated = [] #List of VM instance uuids in openmano that were updated
2483 # for sce_vnf in instanceDict['vnfs']:
2484 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
2485 # if datacenter_key not in vm_list:
2486 # vm_list[datacenter_key] = []
2487 # if datacenter_key not in myvims:
2488 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
2489 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
2490 # if len(vims) == 0:
2491 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
2492 # myvims[datacenter_key] = None
2494 # myvims[datacenter_key] = vims.values()[0]
2495 # for vm in sce_vnf['vms']:
2496 # vm_list[datacenter_key].append(vm['vim_vm_id'])
2497 # vms_notupdated.append(vm["uuid"])
2499 # nets_updated = [] #List of VM instance uuids in openmano that were updated
2500 # nets_notupdated=[]
2502 # for net in instanceDict['nets']:
2503 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
2504 # if datacenter_key not in net_list:
2505 # net_list[datacenter_key] = []
2506 # if datacenter_key not in myvims:
2507 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
2508 # datacenter_tenant_id=net["datacenter_tenant_id"])
2509 # if len(vims) == 0:
2510 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
2511 # myvims[datacenter_key] = None
2513 # myvims[datacenter_key] = vims.values()[0]
2515 # net_list[datacenter_key].append(net['vim_net_id'])
2516 # nets_notupdated.append(net["uuid"])
2518 # # 1. Getting the status of all VMs
2520 # for datacenter_key in myvims:
2521 # if not vm_list.get(datacenter_key):
2525 # if not myvims[datacenter_key]:
2526 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
2529 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
2531 # except vimconn.vimconnException as e:
2532 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
2533 # failed_message = str(e)
2535 # for vm in vm_list[datacenter_key]:
2536 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
2538 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
2539 # for sce_vnf in instanceDict['vnfs']:
2540 # for vm in sce_vnf['vms']:
2541 # vm_id = vm['vim_vm_id']
2542 # interfaces = vm_dict[vm_id].pop('interfaces', [])
2543 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
2544 # has_mgmt_iface = False
2545 # for iface in vm["interfaces"]:
2546 # if iface["type"]=="mgmt":
2547 # has_mgmt_iface = True
2548 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
2549 # vm_dict[vm_id]['status'] = "ACTIVE"
2550 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
2551 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
2552 # 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'):
2553 # vm['status'] = vm_dict[vm_id]['status']
2554 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
2555 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
2556 # # 2.1. Update in openmano DB the VMs whose status changed
2558 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
2559 # vms_notupdated.remove(vm["uuid"])
2561 # vms_updated.append(vm["uuid"])
2562 # except db_base_Exception as e:
2563 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
2564 # # 2.2. Update in openmano DB the interface VMs
2565 # for interface in interfaces:
2566 # #translate from vim_net_id to instance_net_id
2567 # network_id_list=[]
2568 # for net in instanceDict['nets']:
2569 # if net["vim_net_id"] == interface["vim_net_id"]:
2570 # network_id_list.append(net["uuid"])
2571 # if not network_id_list:
2573 # del interface["vim_net_id"]
2575 # for network_id in network_id_list:
2576 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
2577 # except db_base_Exception as e:
2578 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
2580 # # 3. Getting the status of all nets
2582 # for datacenter_key in myvims:
2583 # if not net_list.get(datacenter_key):
2586 # failed_message = ""
2587 # if not myvims[datacenter_key]:
2588 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
2591 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
2593 # except vimconn.vimconnException as e:
2594 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
2595 # failed_message = str(e)
2597 # for net in net_list[datacenter_key]:
2598 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
2600 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
2601 # # TODO: update nets inside a vnf
2602 # for net in instanceDict['nets']:
2603 # net_id = net['vim_net_id']
2604 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
2605 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
2606 # 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'):
2607 # net['status'] = net_dict[net_id]['status']
2608 # net['error_msg'] = net_dict[net_id].get('error_msg')
2609 # net['vim_info'] = net_dict[net_id].get('vim_info')
2610 # # 5.1. Update in openmano DB the nets whose status changed
2612 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
2613 # nets_notupdated.remove(net["uuid"])
2615 # nets_updated.append(net["uuid"])
2616 # except db_base_Exception as e:
2617 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
2619 # # Returns appropriate output
2620 # #print "nfvo.refresh_instance finishes"
2621 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
2622 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
2623 instance_id
= instanceDict
['uuid']
2624 # if len(vms_notupdated)+len(nets_notupdated)>0:
2625 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
2626 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
2628 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
2631 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
2632 #print "Checking that the instance_id exists and getting the instance dictionary"
2633 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
2634 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2636 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2637 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2639 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2640 myvim
= vims
.values()[0]
2643 input_vnfs
= action_dict
.pop("vnfs", [])
2644 input_vms
= action_dict
.pop("vms", [])
2645 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
2649 for sce_vnf
in instanceDict
['vnfs']:
2650 for vm
in sce_vnf
['vms']:
2651 if not action_over_all
:
2652 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
2653 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
2656 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
2657 if "console" in action_dict
:
2658 if not global_config
["http_console_proxy"]:
2659 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2660 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2661 protocol
=data
["protocol"],
2662 ip
= data
["server"],
2663 port
= data
["port"],
2664 suffix
= data
["suffix"]),
2668 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
2669 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
2670 "description": "this console is only reachable by local interface",
2675 #print "console data", data
2677 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
2678 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2679 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2680 protocol
=data
["protocol"],
2681 ip
= global_config
["http_console_host"],
2682 port
= console_thread
.port
,
2683 suffix
= data
["suffix"]),
2687 except NfvoException
as e
:
2688 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2692 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
2694 except vimconn
.vimconnException
as e
:
2695 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2698 if vm_ok
==0: #all goes wrong
2704 def create_or_use_console_proxy_thread(console_server
, console_port
):
2705 #look for a non-used port
2706 console_thread_key
= console_server
+ ":" + str(console_port
)
2707 if console_thread_key
in global_config
["console_thread"]:
2708 #global_config["console_thread"][console_thread_key].start_timeout()
2709 return global_config
["console_thread"][console_thread_key
]
2711 for port
in global_config
["console_port_iterator"]():
2712 #print "create_or_use_console_proxy_thread() port:", port
2713 if port
in global_config
["console_ports"]:
2716 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
2718 global_config
["console_thread"][console_thread_key
] = clithread
2719 global_config
["console_ports"][port
] = console_thread_key
2721 except cli
.ConsoleProxyExceptionPortUsed
as e
:
2722 #port used, try with onoher
2724 except cli
.ConsoleProxyException
as e
:
2725 raise NfvoException(str(e
), HTTP_Bad_Request
)
2726 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
2729 def check_tenant(mydb
, tenant_id
):
2730 '''check that tenant exists at database'''
2731 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
2733 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
2737 def new_tenant(mydb
, tenant_dict
):
2738 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
2742 def delete_tenant(mydb
, tenant
):
2743 #get nfvo_tenant info
2745 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
2746 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
2747 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
2750 def new_datacenter(mydb
, datacenter_descriptor
):
2751 if "config" in datacenter_descriptor
:
2752 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2753 #Check that datacenter-type is correct
2754 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
2757 module
= "vimconn_" + datacenter_type
2758 pkg
= __import__("osm_ro." + module
)
2759 vim_conn
= getattr(pkg
, module
)
2760 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
2761 except (IOError, ImportError):
2762 # if module_info and module_info[0]:
2763 # file.close(module_info[0])
2764 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
2766 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
2767 return datacenter_id
2770 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2771 #obtain data, check that only one exist
2772 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2774 datacenter_id
= datacenter
['uuid']
2775 where
={'uuid': datacenter
['uuid']}
2776 if "config" in datacenter_descriptor
:
2777 if datacenter_descriptor
['config']!=None:
2779 new_config_dict
= datacenter_descriptor
["config"]
2782 for k
in new_config_dict
:
2783 if new_config_dict
[k
]==None:
2786 config_text
= datacenter
.get("config")
2789 config_dict
= yaml
.load(config_text
)
2790 config_dict
.update(new_config_dict
)
2794 except Exception as e
:
2795 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
2796 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
2797 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
2798 return datacenter_id
2801 def delete_datacenter(mydb
, datacenter
):
2802 #get nfvo_tenant info
2803 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
2804 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
2805 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
2808 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):
2809 #get datacenter info
2810 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2811 datacenter_name
= myvim
["name"]
2813 create_vim_tenant
= True if not vim_tenant_id
and not vim_tenant_name
else False
2815 # get nfvo_tenant info
2816 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2817 if vim_tenant_name
==None:
2818 vim_tenant_name
=tenant_dict
['name']
2820 #check that this association does not exist before
2821 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2822 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2823 if len(tenants_datacenters
)>0:
2824 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
2826 vim_tenant_id_exist_atdb
=False
2827 if not create_vim_tenant
:
2828 where_
={"datacenter_id": datacenter_id
}
2829 if vim_tenant_id
!=None:
2830 where_
["vim_tenant_id"] = vim_tenant_id
2831 if vim_tenant_name
!=None:
2832 where_
["vim_tenant_name"] = vim_tenant_name
2833 #check if vim_tenant_id is already at database
2834 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
2835 if len(datacenter_tenants_dict
)>=1:
2836 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2837 vim_tenant_id_exist_atdb
=True
2838 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2840 datacenter_tenants_dict
= {}
2841 #insert at table datacenter_tenants
2842 else: #if vim_tenant_id==None:
2843 #create tenant at VIM if not provided
2845 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2846 except vimconn
.vimconnException
as e
:
2847 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
2848 datacenter_tenants_dict
= {}
2849 datacenter_tenants_dict
["created"]="true"
2851 #fill datacenter_tenants table
2852 if not vim_tenant_id_exist_atdb
:
2853 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2854 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2855 datacenter_tenants_dict
["user"] = vim_username
2856 datacenter_tenants_dict
["passwd"] = vim_password
2857 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2859 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
2860 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
2861 datacenter_tenants_dict
["uuid"] = id_
2863 #fill tenants_datacenters table
2864 datacenter_tenant_id
= datacenter_tenants_dict
["uuid"]
2865 tenants_datacenter_dict
["datacenter_tenant_id"] = datacenter_tenant_id
2866 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
2868 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_dict
['uuid'], datacenter_id
) # reload data
2869 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
2870 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, datacenter_name
, datacenter_tenant_id
,
2871 db
=db
, db_lock
=db_lock
, ovim
=ovim
)
2873 thread_id
= datacenter_tenants_dict
["uuid"]
2874 vim_threads
["running"][thread_id
] = new_thread
2875 return datacenter_id
2878 def edit_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=None, vim_tenant_name
=None,
2879 vim_username
=None, vim_password
=None, config
=None):
2880 #Obtain the data of this datacenter_tenant_id
2881 vim_data
= mydb
.get_rows(
2882 SELECT
=("datacenter_tenants.vim_tenant_name", "datacenter_tenants.vim_tenant_id", "datacenter_tenants.user",
2883 "datacenter_tenants.passwd", "datacenter_tenants.config"),
2884 FROM
="datacenter_tenants JOIN tenants_datacenters ON datacenter_tenants.uuid=tenants_datacenters.datacenter_tenant_id",
2885 WHERE
={"tenants_datacenters.nfvo_tenant_id": nfvo_tenant
,
2886 "tenants_datacenters.datacenter_id": datacenter_id
})
2888 logger
.debug(str(vim_data
))
2889 if len(vim_data
) < 1:
2890 raise NfvoException("Datacenter {} is not attached for tenant {}".format(datacenter_id
, nfvo_tenant
), HTTP_Conflict
)
2894 v
['config'] = yaml
.load(v
['config'])
2897 v
['vim_tenant_id'] = vim_tenant_id
2899 v
['vim_tenant_name'] = vim_tenant_name
2901 v
['user'] = vim_username
2903 v
['passwd'] = vim_password
2907 v
['config'].update(config
)
2909 logger
.debug(str(v
))
2910 deassociate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'])
2911 associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'], vim_tenant_name
=v
['vim_tenant_name'],
2912 vim_username
=v
['user'], vim_password
=v
['passwd'], config
=v
['config'])
2914 return datacenter_id
2916 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2917 #get datacenter info
2918 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2920 #get nfvo_tenant info
2921 if not tenant_id
or tenant_id
=="any":
2924 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
2925 tenant_uuid
= tenant_dict
['uuid']
2927 #check that this association exist before
2928 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
2930 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
2931 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2932 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
2933 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
2935 #delete this association
2936 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2938 #get vim_tenant info and deletes
2940 for tenant_datacenter_item
in tenant_datacenter_list
:
2941 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2942 #try to delete vim:tenant
2944 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2945 if vim_tenant_dict
['created']=='true':
2946 #delete tenant at VIM if created by NFVO
2948 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2949 except vimconn
.vimconnException
as e
:
2950 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
2951 logger
.warn(warning
)
2952 except db_base_Exception
as e
:
2953 logger
.error("Cannot delete datacenter_tenants " + str(e
))
2954 pass # the error will be caused because dependencies, vim_tenant can not be deleted
2955 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
2956 thread
= vim_threads
["running"][thread_id
]
2957 thread
.insert_task(new_task("exit", None))
2958 vim_threads
["deleting"][thread_id
] = thread
2959 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
2962 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
2964 #get datacenter info
2965 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2967 if 'net-update' in action_dict
:
2969 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2971 except vimconn
.vimconnException
as e
:
2972 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
2973 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2974 #update nets Change from VIM format to NFVO format
2977 net_nfvo
={'datacenter_id': datacenter_id
}
2978 net_nfvo
['name'] = net
['name']
2979 #net_nfvo['description']= net['name']
2980 net_nfvo
['vim_net_id'] = net
['id']
2981 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2982 net_nfvo
['shared'] = net
['shared']
2983 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2984 net_list
.append(net_nfvo
)
2985 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
2986 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
2988 elif 'net-edit' in action_dict
:
2989 net
= action_dict
['net-edit'].pop('net')
2990 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2991 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
2992 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2994 elif 'net-delete' in action_dict
:
2995 net
= action_dict
['net-deelte'].get('net')
2996 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2997 result
= mydb
.delete_row(FROM
='datacenter_nets',
2998 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
3002 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
3005 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
3006 #get datacenter info
3007 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3009 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
3010 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
3011 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
3015 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
3016 #get datacenter info
3017 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3020 action_dict
= action_dict
["netmap"]
3021 if 'vim_id' in action_dict
:
3022 filter_dict
["id"] = action_dict
['vim_id']
3023 if 'vim_name' in action_dict
:
3024 filter_dict
["name"] = action_dict
['vim_name']
3026 filter_dict
["shared"] = True
3029 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
3030 except vimconn
.vimconnException
as e
:
3031 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
3032 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
3033 if len(vim_nets
)>1 and action_dict
:
3034 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
3035 elif len(vim_nets
)==0: # and action_dict:
3036 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
3038 for net
in vim_nets
:
3039 net_nfvo
={'datacenter_id': datacenter_id
}
3040 if action_dict
and "name" in action_dict
:
3041 net_nfvo
['name'] = action_dict
['name']
3043 net_nfvo
['name'] = net
['name']
3044 #net_nfvo['description']= net['name']
3045 net_nfvo
['vim_net_id'] = net
['id']
3046 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
3047 net_nfvo
['shared'] = net
['shared']
3048 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
3050 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
3051 net_nfvo
["status"] = "OK"
3052 net_nfvo
["uuid"] = net_id
3053 except db_base_Exception
as e
:
3057 net_nfvo
["status"] = "FAIL: " + str(e
)
3058 net_list
.append(net_nfvo
)
3062 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
3063 #get datacenter info
3064 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3067 if utils
.check_valid_uuid(name
):
3068 filter_dict
["id"] = name
3070 filter_dict
["name"] = name
3072 if item
=="networks":
3073 #filter_dict['tenant_id'] = myvim['tenant_id']
3074 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
3075 elif item
=="tenants":
3076 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
3077 elif item
== "images":
3078 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
3080 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3081 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
3082 if name
and len(content
)==1:
3083 return {item
[:-1]: content
[0]}
3084 elif name
and len(content
)==0:
3085 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
3088 return {item
: content
}
3089 except vimconn
.vimconnException
as e
:
3090 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
3091 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
3094 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
3095 #get datacenter info
3096 if tenant_id
== "any":
3099 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3101 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
3102 logger
.debug("vim_action_delete vim response: " + str(content
))
3103 items
= content
.values()[0]
3104 if type(items
)==list and len(items
)==0:
3105 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
3106 elif type(items
)==list and len(items
)>1:
3107 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
3108 else: # it is a dict
3109 item_id
= items
["id"]
3110 item_name
= str(items
.get("name"))
3113 if item
=="networks":
3114 content
= myvim
.delete_network(item_id
)
3115 elif item
=="tenants":
3116 content
= myvim
.delete_tenant(item_id
)
3117 elif item
== "images":
3118 content
= myvim
.delete_image(item_id
)
3120 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3121 except vimconn
.vimconnException
as e
:
3122 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
3123 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
3125 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
3128 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
3129 #get datacenter info
3130 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
3131 if tenant_id
== "any":
3133 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3135 if item
=="networks":
3136 net
= descriptor
["network"]
3137 net_name
= net
.pop("name")
3138 net_type
= net
.pop("type", "bridge")
3139 net_public
= net
.pop("shared", False)
3140 net_ipprofile
= net
.pop("ip_profile", None)
3141 net_vlan
= net
.pop("vlan", None)
3142 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
3143 elif item
=="tenants":
3144 tenant
= descriptor
["tenant"]
3145 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
3147 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3148 except vimconn
.vimconnException
as e
:
3149 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
3151 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
3153 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
3154 data
= ovim
.new_of_controller(sdn_controller
)
3155 logger
.debug('New SDN controller created with uuid {}'.format(data
))
3158 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
3159 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
3160 msg
= 'SDN controller {} updated'.format(data
)
3164 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
3165 if controller_id
== None:
3166 data
= ovim
.get_of_controllers()
3168 data
= ovim
.show_of_controller(controller_id
)
3170 msg
= 'SDN controller list:\n {}'.format(data
)
3174 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
3175 select_
= ('uuid', 'config')
3176 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
3177 for datacenter
in datacenters
:
3178 if datacenter
['config']:
3179 config
= yaml
.load(datacenter
['config'])
3180 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
3181 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), HTTP_Conflict
)
3183 data
= ovim
.delete_of_controller(controller_id
)
3184 msg
= 'SDN controller {} deleted'.format(data
)
3188 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
3189 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
3190 if len(controller
) < 1:
3191 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), HTTP_Not_Found
)
3194 sdn_controller_id
= yaml
.load(controller
[0]["config"])["sdn-controller"]
3196 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), HTTP_Bad_Request
)
3198 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
3199 switch_dpid
= sdn_controller
["dpid"]
3202 for compute_node
in sdn_port_mapping
:
3203 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
3205 element
["compute_node"] = compute_node
["compute_node"]
3206 for port
in compute_node
["ports"]:
3207 element
["pci"] = port
.get("pci")
3208 element
["switch_port"] = port
.get("switch_port")
3209 element
["switch_mac"] = port
.get("switch_mac")
3210 if not element
["pci"] or not (element
["switch_port"] or element
["switch_mac"]):
3211 raise NfvoException ("The mapping must contain the 'pci' and at least one of the elements 'switch_port'"
3212 " or 'switch_mac'", HTTP_Bad_Request
)
3213 maps
.append(dict(element
))
3215 return ovim
.set_of_port_mapping(maps
, ofc_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, region
=datacenter_id
)
3217 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
3218 maps
= ovim
.get_of_port_mappings(db_filter
={"region": datacenter_id
})
3221 "sdn-controller": None,
3222 "datacenter-id": datacenter_id
,
3224 "ports_mapping": list()
3227 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
3228 if datacenter
['config']:
3229 config
= yaml
.load(datacenter
['config'])
3230 if 'sdn-controller' in config
:
3231 controller_id
= config
['sdn-controller']
3232 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
3233 result
["sdn-controller"] = controller_id
3234 result
["dpid"] = sdn_controller
["dpid"]
3236 if result
["sdn-controller"] == None or result
["dpid"] == None:
3237 raise NfvoException("Not all SDN controller information for datacenter {} could be found: {}".format(datacenter_id
, result
),
3238 HTTP_Internal_Server_Error
)
3243 ports_correspondence_dict
= dict()
3245 if result
["sdn-controller"] != link
["ofc_id"]:
3246 raise NfvoException("The sdn-controller specified for different port mappings differ", HTTP_Internal_Server_Error
)
3247 if result
["dpid"] != link
["switch_dpid"]:
3248 raise NfvoException("The dpid specified for different port mappings differ", HTTP_Internal_Server_Error
)
3250 element
["pci"] = link
["pci"]
3251 if link
["switch_port"]:
3252 element
["switch_port"] = link
["switch_port"]
3253 if link
["switch_mac"]:
3254 element
["switch_mac"] = link
["switch_mac"]
3256 if not link
["compute_node"] in ports_correspondence_dict
:
3258 content
["compute_node"] = link
["compute_node"]
3259 content
["ports"] = list()
3260 ports_correspondence_dict
[link
["compute_node"]] = content
3262 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
3264 for key
in sorted(ports_correspondence_dict
):
3265 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
3269 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
3270 return ovim
.clear_of_port_mapping(db_filter
={"region":datacenter_id
})