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
43 from threading
import Lock
47 global vimconn_imported
49 global default_volume_size
50 default_volume_size
= '5' #size in GB
53 vimconn_imported
= {} # dictionary with VIM type as key, loaded module as value
54 vim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-VIMs
55 vim_persistent_info
= {}
56 logger
= logging
.getLogger('openmano.nfvo')
63 class NfvoException(Exception):
64 def __init__(self
, message
, http_code
):
65 self
.http_code
= http_code
66 Exception.__init
__(self
, message
)
72 if task_id
<= last_task_id
:
73 task_id
= last_task_id
+ 0.000001
74 last_task_id
= task_id
75 return "TASK.{:.6f}".format(task_id
)
78 def new_task(name
, params
, store
=True, depends
=None):
79 task_id
= get_task_id()
80 task
= {"status": "enqueued", "id": task_id
, "name": name
, "params": params
}
82 task
["depends"] = depends
84 task_dict
[task_id
] = task
89 return True if id[:5] == "TASK." else False
92 def get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_name
, tenant_id
):
93 name
= datacenter_name
[:16]
94 if name
not in vim_threads
["names"]:
95 vim_threads
["names"].append(name
)
97 name
= datacenter_name
[:16] + "." + tenant_name
[:16]
98 if name
not in vim_threads
["names"]:
99 vim_threads
["names"].append(name
)
101 name
= datacenter_id
+ "-" + tenant_id
102 vim_threads
["names"].append(name
)
106 def start_service(mydb
):
107 global db
, global_config
108 db
= nfvo_db
.nfvo_db()
109 db
.connect(global_config
['db_host'], global_config
['db_user'], global_config
['db_passwd'], global_config
['db_name'])
110 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'
111 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
112 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
113 'user','passwd', 'dt.config as dt_config', 'nfvo_tenant_id')
115 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
)
117 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id')}
119 extra
.update(yaml
.load(vim
["config"]))
120 if vim
.get('dt_config'):
121 extra
.update(yaml
.load(vim
["dt_config"]))
122 if vim
["type"] not in vimconn_imported
:
125 module
= "vimconn_" + vim
["type"]
126 module_info
= imp
.find_module(module
)
127 vim_conn
= imp
.load_module(vim
["type"], *module_info
)
128 vimconn_imported
[vim
["type"]] = vim_conn
129 except (IOError, ImportError) as e
:
130 if module_info
and module_info
[0]:
131 file.close(module_info
[0])
132 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
133 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
135 thread_id
= vim
["datacenter_id"] + "." + vim
['nfvo_tenant_id']
136 vim_persistent_info
[thread_id
] = {}
139 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
140 myvim
= vimconn_imported
[ vim
["type"] ].vimconnector(
141 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
142 tenant_id
=vim
['vim_tenant_id'], tenant_name
=vim
['vim_tenant_name'],
143 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
144 user
=vim
['user'], passwd
=vim
['passwd'],
145 config
=extra
, persistent_info
=vim_persistent_info
[thread_id
]
147 except Exception as e
:
148 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
149 thread_name
= get_non_used_vim_name(vim
['datacenter_name'], vim
['vim_tenant_id'], vim
['vim_tenant_name'], vim
['vim_tenant_id'])
150 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, vim
['datacenter_name'],
151 vim
.get('datacenter_tenant_id'), db
=db
, db_lock
=db_lock
)
153 vim_threads
["running"][thread_id
] = new_thread
154 except db_base_Exception
as e
:
155 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
159 for thread_id
,thread
in vim_threads
["running"].items():
160 thread
.insert_task(new_task("exit", None, store
=False))
161 vim_threads
["deleting"][thread_id
] = thread
162 vim_threads
["running"] = {}
165 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
167 return result, content:
168 <0, error_text upon error
169 nb_records, flavor_list on success
172 WHERE_dict
['vnf_id'] = vnf_id
173 if nfvo_tenant
is not None:
174 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
176 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
177 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
178 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
179 #print "get_flavor_list result:", result
180 #print "get_flavor_list content:", content
182 for flavor
in flavors
:
183 flavorList
.append(flavor
['flavor_id'])
187 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
189 return result, content:
190 <0, error_text upon error
191 nb_records, flavor_list on success
194 WHERE_dict
['vnf_id'] = vnf_id
195 if nfvo_tenant
is not None:
196 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
198 #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
199 images
= mydb
.get_rows(FROM
='vms join images on vms.image_id=images.uuid',SELECT
=('image_id',),WHERE
=WHERE_dict
)
202 imageList
.append(image
['image_id'])
206 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
207 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None):
208 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
209 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
210 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
211 raise exception upon error
214 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
215 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
216 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
217 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
218 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
219 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
220 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
221 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'
222 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
223 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
224 'user','passwd', 'dt.config as dt_config')
226 from_
= 'datacenters as d'
227 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
229 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
232 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id')}
234 extra
.update(yaml
.load(vim
["config"]))
235 if vim
.get('dt_config'):
236 extra
.update(yaml
.load(vim
["dt_config"]))
237 if vim
["type"] not in vimconn_imported
:
240 module
= "vimconn_" + vim
["type"]
241 module_info
= imp
.find_module(module
)
242 vim_conn
= imp
.load_module(vim
["type"], *module_info
)
243 vimconn_imported
[vim
["type"]] = vim_conn
244 except (IOError, ImportError) as e
:
245 if module_info
and module_info
[0]:
246 file.close(module_info
[0])
247 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
248 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
251 if 'nfvo_tenant_id' in vim
:
252 thread_id
= vim
["datacenter_id"] + "." + vim
['nfvo_tenant_id']
253 if thread_id
not in vim_persistent_info
:
254 vim_persistent_info
[thread_id
] = {}
255 persistent_info
= vim_persistent_info
[thread_id
]
259 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
260 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
261 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
262 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
),
263 tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
264 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
265 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
266 config
=extra
, persistent_info
=persistent_info
268 except Exception as e
:
269 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
271 except db_base_Exception
as e
:
272 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
275 def rollback(mydb
, vims
, rollback_list
):
277 #delete things by reverse order
278 for i
in range(len(rollback_list
)-1, -1, -1):
279 item
= rollback_list
[i
]
280 if item
["where"]=="vim":
281 if item
["vim_id"] not in vims
:
283 vim
=vims
[ item
["vim_id"] ]
285 if item
["what"]=="image":
286 vim
.delete_image(item
["uuid"])
287 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
288 elif item
["what"]=="flavor":
289 vim
.delete_flavor(item
["uuid"])
290 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
291 elif item
["what"]=="network":
292 vim
.delete_network(item
["uuid"])
293 elif item
["what"]=="vm":
294 vim
.delete_vminstance(item
["uuid"])
295 except vimconn
.vimconnException
as e
:
296 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
297 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
298 except db_base_Exception
as e
:
299 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
303 if item
["what"]=="image":
304 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
305 elif item
["what"]=="flavor":
306 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
307 except db_base_Exception
as e
:
308 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
309 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
310 if len(undeleted_items
)==0:
311 return True," Rollback successful."
313 return False," Rollback fails to delete: " + str(undeleted_items
)
316 def check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1):
318 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
320 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
322 #dataplane interfaces
323 for numa
in vnfc
.get("numas",() ):
324 for interface
in numa
.get("interfaces",()):
325 if interface
["name"] in name_dict
:
327 "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
328 vnfc
["name"], interface
["name"]),
330 name_dict
[ interface
["name"] ] = "underlay"
332 for interface
in vnfc
.get("bridge-ifaces",() ):
333 if interface
["name"] in name_dict
:
335 "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
336 vnfc
["name"], interface
["name"]),
338 name_dict
[ interface
["name"] ] = "overlay"
339 vnfc_interfaces
[ vnfc
["name"] ] = name_dict
340 # check bood-data info
341 if "boot-data" in vnfc
:
342 # check that user-data is incompatible with users and config-files
343 if (vnfc
["boot-data"].get("users") or vnfc
["boot-data"].get("config-files")) and vnfc
["boot-data"].get("user-data"):
345 "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
348 #check if the info in external_connections matches with the one in the vnfcs
350 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
351 if external_connection
["name"] in name_list
:
353 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
354 external_connection
["name"]),
356 name_list
.append(external_connection
["name"])
357 if external_connection
["VNFC"] not in vnfc_interfaces
:
359 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
360 external_connection
["name"], external_connection
["VNFC"]),
363 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
365 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
366 external_connection
["name"],
367 external_connection
["local_iface_name"]),
370 #check if the info in internal_connections matches with the one in the vnfcs
372 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
373 if internal_connection
["name"] in name_list
:
375 "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection".format(
376 internal_connection
["name"]),
378 name_list
.append(internal_connection
["name"])
379 #We should check that internal-connections of type "ptp" have only 2 elements
381 if len(internal_connection
["elements"])>2 and (internal_connection
.get("type") == "ptp" or internal_connection
.get("type") == "e-line"):
383 "Error at 'vnf:internal-connections[name:'{}']:elements', size must be 2 for a '{}' type. Consider change it to '{}' type".format(
384 internal_connection
["name"],
385 'ptp' if vnf_descriptor_version
==1 else 'e-line',
386 'data' if vnf_descriptor_version
==1 else "e-lan"),
388 for port
in internal_connection
["elements"]:
390 iface
= port
["local_iface_name"]
391 if vnf
not in vnfc_interfaces
:
393 "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
394 internal_connection
["name"], vnf
),
396 if iface
not in vnfc_interfaces
[ vnf
]:
398 "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
399 internal_connection
["name"], iface
),
401 return -HTTP_Bad_Request
,
402 if vnf_descriptor_version
==1 and "type" not in internal_connection
:
403 if vnfc_interfaces
[vnf
][iface
] == "overlay":
404 internal_connection
["type"] = "bridge"
406 internal_connection
["type"] = "data"
407 if vnf_descriptor_version
==2 and "implementation" not in internal_connection
:
408 if vnfc_interfaces
[vnf
][iface
] == "overlay":
409 internal_connection
["implementation"] = "overlay"
411 internal_connection
["implementation"] = "underlay"
412 if (internal_connection
.get("type") == "data" or internal_connection
.get("type") == "ptp" or \
413 internal_connection
.get("implementation") == "underlay") and vnfc_interfaces
[vnf
][iface
] == "overlay":
415 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
416 internal_connection
["name"],
417 iface
, 'bridge' if vnf_descriptor_version
==1 else 'overlay',
418 'data' if vnf_descriptor_version
==1 else 'underlay'),
420 if (internal_connection
.get("type") == "bridge" or internal_connection
.get("implementation") == "overlay") and \
421 vnfc_interfaces
[vnf
][iface
] == "underlay":
423 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
424 internal_connection
["name"], iface
,
425 'data' if vnf_descriptor_version
==1 else 'underlay',
426 'bridge' if vnf_descriptor_version
==1 else 'overlay'),
430 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
432 if only_create_at_vim
:
433 image_mano_id
= image_dict
['uuid']
434 if return_on_error
== None:
435 return_on_error
= True
437 if image_dict
['location']:
438 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
440 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
442 image_mano_id
= images
[0]['uuid']
444 #create image in MANO DB
445 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
446 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
447 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
449 #temp_image_dict['location'] = image_dict.get('new_location') if image_dict['location'] is None
450 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
451 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
452 #create image at every vim
453 for vim_id
,vim
in vims
.iteritems():
454 image_created
="false"
456 image_db
= mydb
.get_rows(FROM
="datacenters_images", WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
457 #look at VIM if this image exist
459 if image_dict
['location'] is not None:
460 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
463 filter_dict
['name'] = image_dict
['universal_name']
464 if image_dict
.get('checksum') != None:
465 filter_dict
['checksum'] = image_dict
['checksum']
466 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
467 vim_images
= vim
.get_image_list(filter_dict
)
468 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
469 if len(vim_images
) > 1:
470 raise vimconn
.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict
)), HTTP_Conflict
)
471 elif len(vim_images
) == 0:
472 raise vimconn
.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict
)))
474 #logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
475 image_vim_id
= vim_images
[0]['id']
477 except vimconn
.vimconnNotFoundException
as e
:
478 #Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
480 #image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
481 if image_dict
['location']:
482 image_vim_id
= vim
.new_image(image_dict
)
483 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
486 #If we reach this point, then the image has image name, and optionally checksum, and could not be found
487 raise vimconn
.vimconnException(str(e
))
488 except vimconn
.vimconnException
as e
:
490 logger
.error("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
493 logger
.warn("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
495 except vimconn
.vimconnException
as e
:
497 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
499 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
502 #if we reach here, the image has been created or existed
504 #add new vim_id at datacenters_images
505 mydb
.new_row('datacenters_images', {'datacenter_id':vim_id
, 'image_id':image_mano_id
, 'vim_id': image_vim_id
, 'created':image_created
})
506 elif image_db
[0]["vim_id"]!=image_vim_id
:
507 #modify existing vim_id at datacenters_images
508 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
510 return image_vim_id
if only_create_at_vim
else image_mano_id
513 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
514 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
515 'ram':flavor_dict
.get('ram'),
516 'vcpus':flavor_dict
.get('vcpus'),
518 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
519 del flavor_dict
['extended']
520 if 'extended' in flavor_dict
:
521 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
523 #look if flavor exist
524 if only_create_at_vim
:
525 flavor_mano_id
= flavor_dict
['uuid']
526 if return_on_error
== None:
527 return_on_error
= True
529 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
531 flavor_mano_id
= flavors
[0]['uuid']
534 #create one by one the images of aditional disks
535 dev_image_list
=[] #list of images
536 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
538 for device
in flavor_dict
['extended'].get('devices',[]):
539 if "image" not in device
and "image name" not in device
:
542 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
543 image_dict
['universal_name']=device
.get('image name')
544 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
545 image_dict
['location']=device
.get('image')
546 #image_dict['new_location']=vnfc.get('image location')
547 image_dict
['checksum']=device
.get('image checksum')
548 image_metadata_dict
= device
.get('image metadata', None)
549 image_metadata_str
= None
550 if image_metadata_dict
!= None:
551 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
552 image_dict
['metadata']=image_metadata_str
553 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
554 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
555 dev_image_list
.append(image_id
)
557 temp_flavor_dict
['name'] = flavor_dict
['name']
558 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
559 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
560 flavor_mano_id
= content
561 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
562 #create flavor at every vim
563 if 'uuid' in flavor_dict
:
564 del flavor_dict
['uuid']
566 for vim_id
,vim
in vims
.items():
567 flavor_created
="false"
569 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors", WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
570 #look at VIM if this flavor exist SKIPPED
571 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
573 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
577 #Create the flavor in VIM
578 #Translate images at devices from MANO id to VIM id
580 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
581 #make a copy of original devices
584 for device
in flavor_dict
["extended"].get("devices",[]):
587 devices_original
.append(dev
)
588 if 'image' in device
:
590 if 'image metadata' in device
:
591 del device
['image metadata']
593 for index
in range(0,len(devices_original
)) :
594 device
=devices_original
[index
]
595 if "image" not in device
and "image name" not in device
:
597 disk_list
.append({'size': device
.get('size', default_volume_size
)})
600 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
601 image_dict
['universal_name']=device
.get('image name')
602 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
603 image_dict
['location']=device
.get('image')
604 #image_dict['new_location']=device.get('image location')
605 image_dict
['checksum']=device
.get('image checksum')
606 image_metadata_dict
= device
.get('image metadata', None)
607 image_metadata_str
= None
608 if image_metadata_dict
!= None:
609 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
610 image_dict
['metadata']=image_metadata_str
611 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
612 image_dict
["uuid"]=image_mano_id
613 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
615 #save disk information (image must be based on and size
616 disk_list
.append({'image_id': image_vim_id
, 'size': device
.get('size', default_volume_size
)})
618 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
621 #check that this vim_id exist in VIM, if not create
622 flavor_vim_id
=flavor_db
[0]["vim_id"]
624 vim
.get_flavor(flavor_vim_id
)
625 continue #flavor exist
626 except vimconn
.vimconnException
:
628 #create flavor at vim
629 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
632 flavor_vim_id
=vim
.get_flavor_id_from_data(flavor_dict
)
633 flavor_create
="false"
634 except vimconn
.vimconnException
as e
:
637 if not flavor_vim_id
:
638 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
639 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
640 flavor_created
="true"
641 except vimconn
.vimconnException
as e
:
643 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
645 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
648 #if reach here the flavor has been create or exist
649 if len(flavor_db
)==0:
650 #add new vim_id at datacenters_flavors
651 extended_devices_yaml
= None
652 if len(disk_list
) > 0:
653 extended_devices
= dict()
654 extended_devices
['disks'] = disk_list
655 extended_devices_yaml
= yaml
.safe_dump(extended_devices
,default_flow_style
=True,width
=256)
656 mydb
.new_row('datacenters_flavors',
657 {'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
, 'vim_id': flavor_vim_id
,
658 'created':flavor_created
,'extended': extended_devices_yaml
})
659 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
660 #modify existing vim_id at datacenters_flavors
661 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
663 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
666 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
669 # Step 1. Check the VNF descriptor
670 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
671 # Step 2. Check tenant exist
673 if tenant_id
!= "any":
674 check_tenant(mydb
, tenant_id
)
675 if "tenant_id" in vnf_descriptor
["vnf"]:
676 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
677 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
680 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
681 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
682 if global_config
["auto_push_VNF_to_VIMs"]:
683 vims
= get_vim(mydb
, tenant_id
)
685 # Step 4. Review the descriptor and add missing fields
686 #print vnf_descriptor
687 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
688 vnf_name
= vnf_descriptor
['vnf']['name']
689 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
690 if "physical" in vnf_descriptor
['vnf']:
691 del vnf_descriptor
['vnf']['physical']
692 #print vnf_descriptor
694 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
695 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
696 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
698 #For each VNFC, we add it to the VNFCDict and we create a flavor.
699 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
700 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
702 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
703 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
705 VNFCitem
["name"] = vnfc
['name']
706 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
708 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
711 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
712 myflavorDict
["description"] = VNFCitem
["description"]
713 myflavorDict
["ram"] = vnfc
.get("ram", 0)
714 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
715 myflavorDict
["disk"] = vnfc
.get("disk", 1)
716 myflavorDict
["extended"] = {}
718 devices
= vnfc
.get("devices")
720 myflavorDict
["extended"]["devices"] = devices
723 # 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
724 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
726 # Previous code has been commented
727 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
728 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
729 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
730 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
732 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
734 # print "Error creating flavor: unknown processor model. Rollback successful."
735 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
737 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
738 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
740 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
741 myflavorDict
['extended']['numas'] = vnfc
['numas']
745 # Step 6.2 New flavors are created in the VIM
746 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
748 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
749 VNFCitem
["flavor_id"] = flavor_id
750 VNFCDict
[vnfc
['name']] = VNFCitem
752 logger
.debug("Creating new images in the VIM for each VNFC")
753 # Step 6.3 New images are created in the VIM
754 #For each VNFC, we must create the appropriate image.
755 #This "for" loop might be integrated with the previous one
756 #In case this integration is made, the VNFCDict might become a VNFClist.
757 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
758 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
760 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
761 image_dict
['universal_name']=vnfc
.get('image name')
762 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
763 image_dict
['location']=vnfc
.get('VNFC image')
764 #image_dict['new_location']=vnfc.get('image location')
765 image_dict
['checksum']=vnfc
.get('image checksum')
766 image_metadata_dict
= vnfc
.get('image metadata', None)
767 image_metadata_str
= None
768 if image_metadata_dict
is not None:
769 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
770 image_dict
['metadata']=image_metadata_str
771 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
772 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
773 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
774 VNFCDict
[vnfc
['name']]["image_id"] = image_id
775 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
776 if vnfc
.get("boot-data"):
777 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
780 # Step 7. Storing the VNF descriptor in the repository
781 if "descriptor" not in vnf_descriptor
["vnf"]:
782 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
784 # Step 8. Adding the VNF to the NFVO DB
785 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
787 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
788 _
, message
= rollback(mydb
, vims
, rollback_list
)
789 if isinstance(e
, db_base_Exception
):
790 error_text
= "Exception at database"
791 elif isinstance(e
, KeyError):
792 error_text
= "KeyError exception "
793 e
.http_code
= HTTP_Internal_Server_Error
795 error_text
= "Exception at VIM"
796 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
797 #logger.error("start_scenario %s", error_text)
798 raise NfvoException(error_text
, e
.http_code
)
801 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
804 # Step 1. Check the VNF descriptor
805 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
806 # Step 2. Check tenant exist
808 if tenant_id
!= "any":
809 check_tenant(mydb
, tenant_id
)
810 if "tenant_id" in vnf_descriptor
["vnf"]:
811 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
812 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
815 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
816 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
817 if global_config
["auto_push_VNF_to_VIMs"]:
818 vims
= get_vim(mydb
, tenant_id
)
820 # Step 4. Review the descriptor and add missing fields
821 #print vnf_descriptor
822 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
823 vnf_name
= vnf_descriptor
['vnf']['name']
824 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
825 if "physical" in vnf_descriptor
['vnf']:
826 del vnf_descriptor
['vnf']['physical']
827 #print vnf_descriptor
829 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
830 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
831 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
833 #For each VNFC, we add it to the VNFCDict and we create a flavor.
834 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
835 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
837 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
838 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
840 VNFCitem
["name"] = vnfc
['name']
841 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
843 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
846 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
847 myflavorDict
["description"] = VNFCitem
["description"]
848 myflavorDict
["ram"] = vnfc
.get("ram", 0)
849 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
850 myflavorDict
["disk"] = vnfc
.get("disk", 1)
851 myflavorDict
["extended"] = {}
853 devices
= vnfc
.get("devices")
855 myflavorDict
["extended"]["devices"] = devices
858 # 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
859 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
861 # Previous code has been commented
862 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
863 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
864 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
865 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
867 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
869 # print "Error creating flavor: unknown processor model. Rollback successful."
870 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
872 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
873 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
875 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
876 myflavorDict
['extended']['numas'] = vnfc
['numas']
880 # Step 6.2 New flavors are created in the VIM
881 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
883 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
884 VNFCitem
["flavor_id"] = flavor_id
885 VNFCDict
[vnfc
['name']] = VNFCitem
887 logger
.debug("Creating new images in the VIM for each VNFC")
888 # Step 6.3 New images are created in the VIM
889 #For each VNFC, we must create the appropriate image.
890 #This "for" loop might be integrated with the previous one
891 #In case this integration is made, the VNFCDict might become a VNFClist.
892 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
893 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
895 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
896 image_dict
['universal_name']=vnfc
.get('image name')
897 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
898 image_dict
['location']=vnfc
.get('VNFC image')
899 #image_dict['new_location']=vnfc.get('image location')
900 image_dict
['checksum']=vnfc
.get('image checksum')
901 image_metadata_dict
= vnfc
.get('image metadata', None)
902 image_metadata_str
= None
903 if image_metadata_dict
is not None:
904 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
905 image_dict
['metadata']=image_metadata_str
906 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
907 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
908 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
909 VNFCDict
[vnfc
['name']]["image_id"] = image_id
910 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
911 if vnfc
.get("boot-data"):
912 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
914 # Step 7. Storing the VNF descriptor in the repository
915 if "descriptor" not in vnf_descriptor
["vnf"]:
916 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
918 # Step 8. Adding the VNF to the NFVO DB
919 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
921 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
922 _
, message
= rollback(mydb
, vims
, rollback_list
)
923 if isinstance(e
, db_base_Exception
):
924 error_text
= "Exception at database"
925 elif isinstance(e
, KeyError):
926 error_text
= "KeyError exception "
927 e
.http_code
= HTTP_Internal_Server_Error
929 error_text
= "Exception at VIM"
930 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
931 #logger.error("start_scenario %s", error_text)
932 raise NfvoException(error_text
, e
.http_code
)
935 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
936 #check valid tenant_id
937 check_tenant(mydb
, tenant_id
)
940 if tenant_id
!= "any":
941 where_or
["tenant_id"] = tenant_id
942 where_or
["public"] = True
943 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
946 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
947 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
948 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
949 data
={'vnf' : filtered_content
}
951 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
952 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description', 'boot_data'),
953 WHERE
={'vnfs.uuid': vnf_id
} )
955 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
956 # change boot_data into boot-data
958 if vm
.get("boot_data"):
959 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
962 data
['vnf']['VNFC'] = content
963 #TODO: GET all the information from a VNFC and include it in the output.
966 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
967 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
968 WHERE
={'vnfs.uuid': vnf_id
} )
969 data
['vnf']['nets'] = content
971 #GET ip-profile for each net
972 for net
in data
['vnf']['nets']:
973 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
974 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
975 WHERE
={'net_id': net
["uuid"]} )
976 if len(ipprofiles
)==1:
977 net
["ip_profile"] = ipprofiles
[0]
978 elif len(ipprofiles
)>1:
979 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
982 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
984 #GET External Interfaces
985 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
986 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
987 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
988 WHERE
={'vnfs.uuid': vnf_id
},
989 WHERE_NOT
={'interfaces.external_name': None} )
991 data
['vnf']['external-connections'] = content
996 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
998 if tenant_id
!= "any":
999 check_tenant(mydb
, tenant_id
)
1000 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1001 vims
= get_vim(mydb
, tenant_id
)
1005 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1007 if tenant_id
!= "any":
1008 where_or
["tenant_id"] = tenant_id
1009 where_or
["public"] = True
1010 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1011 vnf_id
= vnf
["uuid"]
1013 # "Getting the list of flavors and tenants of the VNF"
1014 flavorList
= get_flavorlist(mydb
, vnf_id
)
1015 if len(flavorList
)==0:
1016 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1018 imageList
= get_imagelist(mydb
, vnf_id
)
1019 if len(imageList
)==0:
1020 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1022 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1024 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1027 for flavor
in flavorList
:
1028 #check if flavor is used by other vnf
1030 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1032 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1034 #flavor not used, must be deleted
1036 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
1037 for flavor_vim
in c
:
1038 if flavor_vim
["datacenter_id"] not in vims
:
1040 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
1042 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
1044 myvim
.delete_flavor(flavor_vim
["vim_id"])
1045 except vimconn
.vimconnNotFoundException
as e
:
1046 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
1047 except vimconn
.vimconnException
as e
:
1048 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1049 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1050 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
1051 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1052 mydb
.delete_row_by_id('flavors', flavor
)
1053 except db_base_Exception
as e
:
1054 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1055 undeletedItems
.append("flavor %s" % flavor
)
1058 for image
in imageList
:
1060 #check if image is used by other vnf
1061 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
1063 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1065 #image not used, must be deleted
1067 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1069 if image_vim
["datacenter_id"] not in vims
:
1071 if image_vim
['created']=='false': #skip this image because not created by openmano
1073 myvim
=vims
[ image_vim
["datacenter_id"] ]
1075 myvim
.delete_image(image_vim
["vim_id"])
1076 except vimconn
.vimconnNotFoundException
as e
:
1077 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1078 except vimconn
.vimconnException
as e
:
1079 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1080 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1081 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1082 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1083 mydb
.delete_row_by_id('images', image
)
1084 except db_base_Exception
as e
:
1085 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1086 undeletedItems
.append("image %s" % image
)
1088 return vnf_id
+ " " + vnf
["name"]
1090 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1093 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1094 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1098 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
1099 myvim
= vims
.values()[0]
1100 result
,servers
= myvim
.get_hosts_info()
1102 return result
, servers
1103 topology
= {'name':myvim
['name'] , 'servers': servers
}
1104 return result
, topology
1107 def get_hosts(mydb
, nfvo_tenant_id
):
1108 vims
= get_vim(mydb
, nfvo_tenant_id
)
1110 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
1112 #print "nfvo.datacenter_action() error. Several datacenters found"
1113 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1114 myvim
= vims
.values()[0]
1116 hosts
= myvim
.get_hosts()
1117 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1119 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1121 server
={'name':host
['name'], 'vms':[]}
1122 for vm
in host
['instances']:
1123 #get internal name and model
1125 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1126 WHERE
={'vim_vm_id':vm
['id']} )
1128 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1130 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1132 except db_base_Exception
as e
:
1133 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1134 datacenter
['Datacenters'][0]['servers'].append(server
)
1135 #return -400, "en construccion"
1137 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1139 except vimconn
.vimconnException
as e
:
1140 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1143 def new_scenario(mydb
, tenant_id
, topo
):
1145 # result, vims = get_vim(mydb, tenant_id)
1147 # return result, vims
1149 if tenant_id
!= "any":
1150 check_tenant(mydb
, tenant_id
)
1151 if "tenant_id" in topo
:
1152 if topo
["tenant_id"] != tenant_id
:
1153 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1158 #1.1: get VNFs and external_networks (other_nets).
1160 other_nets
={} #external_networks, bridge_networks and data_networkds
1161 nodes
= topo
['topology']['nodes']
1162 for k
in nodes
.keys():
1163 if nodes
[k
]['type'] == 'VNF':
1165 vnfs
[k
]['ifaces'] = {}
1166 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1167 other_nets
[k
] = nodes
[k
]
1168 other_nets
[k
]['external']=True
1169 elif nodes
[k
]['type'] == 'network':
1170 other_nets
[k
] = nodes
[k
]
1171 other_nets
[k
]['external']=False
1174 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1175 for name
,vnf
in vnfs
.items():
1177 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1179 error_pos
= "'topology':'nodes':'" + name
+ "'"
1181 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1182 where
['uuid'] = vnf
['vnf_id']
1183 if 'VNF model' in vnf
:
1184 error_text
+= " 'VNF model' " + vnf
['VNF model']
1185 where
['name'] = vnf
['VNF model']
1187 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
1189 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1195 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1197 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1198 vnf
['uuid']=vnf_db
[0]['uuid']
1199 vnf
['description']=vnf_db
[0]['description']
1200 #get external interfaces
1201 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1202 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1203 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1204 for ext_iface
in ext_ifaces
:
1205 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1207 #1.4 get list of connections
1208 conections
= topo
['topology']['connections']
1209 conections_list
= []
1210 conections_list_name
= []
1211 for k
in conections
.keys():
1212 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1213 ifaces_list
= conections
[k
]['nodes'].items()
1214 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1216 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1217 for k2
in conection_pair_list
:
1220 con_type
= conections
[k
].get("type", "link")
1221 if con_type
!= "link":
1223 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
1224 other_nets
[k
] = {'external': False}
1225 if conections
[k
].get("graph"):
1226 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1227 ifaces_list
.append( (k
, None) )
1230 if con_type
== "external_network":
1231 other_nets
[k
]['external'] = True
1232 if conections
[k
].get("model"):
1233 other_nets
[k
]["model"] = conections
[k
]["model"]
1235 other_nets
[k
]["model"] = k
1236 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1237 other_nets
[k
]["model"] = con_type
1239 conections_list_name
.append(k
)
1240 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)
1241 #print set(ifaces_list)
1242 #check valid VNF and iface names
1243 for iface
in ifaces_list
:
1244 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1245 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1246 str(k
), iface
[0]), HTTP_Not_Found
)
1247 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1248 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1249 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
1251 #1.5 unify connections from the pair list to a consolidated list
1253 while index
< len(conections_list
):
1255 while index2
< len(conections_list
):
1256 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1257 conections_list
[index
] |
= conections_list
[index2
]
1258 del conections_list
[index2
]
1259 del conections_list_name
[index2
]
1262 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1264 #for k in conections_list:
1269 #1.6 Delete non external nets
1270 # for k in other_nets.keys():
1271 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1272 # for con in conections_list:
1274 # for index in range(0,len(con)):
1275 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1276 # for index in delete_indexes:
1279 #1.7: Check external_ports are present at database table datacenter_nets
1280 for k
,net
in other_nets
.items():
1281 error_pos
= "'topology':'nodes':'" + k
+ "'"
1282 if net
['external']==False:
1283 if 'name' not in net
:
1285 if 'model' not in net
:
1286 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1287 if net
['model']=='bridge_net':
1288 net
['type']='bridge';
1289 elif net
['model']=='dataplane_net':
1292 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1294 #IF we do not want to check that external network exist at datacenter
1299 # if 'net_id' in net:
1300 # error_text += " 'net_id' " + net['net_id']
1301 # WHERE_['uuid'] = net['net_id']
1302 # if 'model' in net:
1303 # error_text += " 'model' " + net['model']
1304 # WHERE_['name'] = net['model']
1305 # if len(WHERE_) == 0:
1306 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1307 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1308 # FROM='datacenter_nets', WHERE=WHERE_ )
1310 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1312 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1313 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1315 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1316 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1317 # other_nets[k].update(net_db[0])
1320 net_nb
=0 #Number of nets
1321 for con
in conections_list
:
1322 #check if this is connected to a external net
1326 for index
in range(0,len(con
)):
1327 #check if this is connected to a external net
1328 for net_key
in other_nets
.keys():
1329 if con
[index
][0]==net_key
:
1330 if other_net_index
>=0:
1331 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1332 #print "nfvo.new_scenario " + error_text
1333 raise NfvoException(error_text
, HTTP_Bad_Request
)
1335 other_net_index
= index
1336 net_target
= net_key
1338 #print "other_net_index", other_net_index
1340 if other_net_index
>=0:
1341 del con
[other_net_index
]
1342 #IF we do not want to check that external network exist at datacenter
1343 if other_nets
[net_target
]['external'] :
1344 if "name" not in other_nets
[net_target
]:
1345 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1346 if other_nets
[net_target
]["type"] == "external_network":
1347 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1348 other_nets
[net_target
]["type"] = "data"
1350 other_nets
[net_target
]["type"] = "bridge"
1352 # if other_nets[net_target]['external'] :
1353 # 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
1354 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1355 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1356 # print "nfvo.new_scenario " + error_text
1357 # return -HTTP_Bad_Request, error_text
1360 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1363 net_type_bridge
=False
1365 net_target
= "__-__net"+str(net_nb
)
1366 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
1367 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1370 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1371 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1372 if iface_type
=='mgmt' or iface_type
=='bridge':
1373 net_type_bridge
= True
1375 net_type_data
= True
1376 if net_type_bridge
and net_type_data
:
1377 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1378 #print "nfvo.new_scenario " + error_text
1379 raise NfvoException(error_text
, HTTP_Bad_Request
)
1380 elif net_type_bridge
:
1383 type_
='data' if len(con
)>2 else 'ptp'
1384 net_list
[net_target
]['type'] = type_
1387 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1388 #print "nfvo.new_scenario " + error_text
1390 raise NfvoException(error_text
, HTTP_Bad_Request
)
1392 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1393 #1.8.1 obtain management net
1394 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1395 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1396 #1.8.2 check all interfaces from all vnfs
1398 add_mgmt_net
= False
1399 for vnf
in vnfs
.values():
1400 for iface
in vnf
['ifaces'].values():
1401 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1402 #iface not connected
1403 iface
['net_key'] = 'mgmt'
1405 if add_mgmt_net
and 'mgmt' not in net_list
:
1406 net_list
['mgmt']=mgmt_net
[0]
1407 net_list
['mgmt']['external']=True
1408 net_list
['mgmt']['graph']={'visible':False}
1410 net_list
.update(other_nets
)
1412 #print 'net_list', net_list
1417 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1418 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1419 'tenant_id':tenant_id
, 'name':topo
['name'],
1420 'description':topo
.get('description',topo
['name']),
1421 'public': topo
.get('public', False)
1427 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
1428 """ This creates a new scenario for version 0.2 and 0.3"""
1429 scenario
= scenario_dict
["scenario"]
1430 if tenant_id
!= "any":
1431 check_tenant(mydb
, tenant_id
)
1432 if "tenant_id" in scenario
:
1433 if scenario
["tenant_id"] != tenant_id
:
1434 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1435 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1436 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1440 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
1441 for name
,vnf
in scenario
["vnfs"].iteritems():
1443 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1445 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1447 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1448 where
['uuid'] = vnf
['vnf_id']
1449 if 'vnf_name' in vnf
:
1450 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1451 where
['name'] = vnf
['vnf_name']
1453 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1454 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
1459 if len(vnf_db
) == 0:
1460 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1461 elif len(vnf_db
) > 1:
1462 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1463 vnf
['uuid'] = vnf_db
[0]['uuid']
1464 vnf
['description'] = vnf_db
[0]['description']
1466 # get external interfaces
1467 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
1468 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1469 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name': None} )
1470 for ext_iface
in ext_ifaces
:
1471 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
1472 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1474 # 2: Insert net_key and ip_address at every vnf interface
1475 for net_name
, net
in scenario
["networks"].items():
1476 net_type_bridge
= False
1477 net_type_data
= False
1478 for iface_dict
in net
["interfaces"]:
1479 if version
== "0.2":
1480 temp_dict
= iface_dict
1482 elif version
== "0.3":
1483 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
1484 ip_address
= iface_dict
.get('ip_address', None)
1485 for vnf
, iface
in temp_dict
.items():
1486 if vnf
not in scenario
["vnfs"]:
1487 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
1489 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1490 raise NfvoException(error_text
, HTTP_Not_Found
)
1491 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1492 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
1493 .format(net_name
, iface
)
1494 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1495 raise NfvoException(error_text
, HTTP_Bad_Request
)
1496 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1497 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
1498 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1499 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1500 raise NfvoException(error_text
, HTTP_Bad_Request
)
1501 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1502 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
1503 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1504 if iface_type
== 'mgmt' or iface_type
== 'bridge':
1505 net_type_bridge
= True
1507 net_type_data
= True
1509 if net_type_bridge
and net_type_data
:
1510 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
1512 # logger.debug("nfvo.new_scenario " + error_text)
1513 raise NfvoException(error_text
, HTTP_Bad_Request
)
1514 elif net_type_bridge
:
1517 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
1519 if net
.get("implementation"): # for v0.3
1520 if type_
== "bridge" and net
["implementation"] == "underlay":
1521 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
1522 "'network':'{}'".format(net_name
)
1523 # logger.debug(error_text)
1524 raise NfvoException(error_text
, HTTP_Bad_Request
)
1525 elif type_
!= "bridge" and net
["implementation"] == "overlay":
1526 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
1527 "'network':'{}'".format(net_name
)
1528 # logger.debug(error_text)
1529 raise NfvoException(error_text
, HTTP_Bad_Request
)
1530 net
.pop("implementation")
1531 if "type" in net
and version
== "0.3": # for v0.3
1532 if type_
== "data" and net
["type"] == "e-line":
1533 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
1534 "'e-line' at 'network':'{}'".format(net_name
)
1535 # logger.debug(error_text)
1536 raise NfvoException(error_text
, HTTP_Bad_Request
)
1537 elif type_
== "ptp" and net
["type"] == "e-lan":
1541 net
['name'] = net_name
1542 net
['external'] = net
.get('external', False)
1544 # 3: insert at database
1545 scenario
["nets"] = scenario
["networks"]
1546 scenario
['tenant_id'] = tenant_id
1547 scenario_id
= mydb
.new_scenario(scenario
)
1551 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1552 data
["uuid"] = scenario_id
1553 data
["tenant_id"] = tenant_id
1554 c
= mydb
.edit_scenario( data
)
1558 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1559 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1560 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
1561 vims
= {datacenter_id
: myvim
}
1562 myvim_tenant
= myvim
['tenant_id']
1563 datacenter_name
= myvim
['name']
1567 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1568 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1569 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
1570 scenarioDict
['datacenter_id'] = datacenter_id
1571 #print '================scenarioDict======================='
1572 #print json.dumps(scenarioDict, indent=4)
1573 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1575 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
1576 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1578 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1579 auxNetDict
['scenario'] = {}
1581 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1582 for sce_net
in scenarioDict
['nets']:
1583 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1585 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1586 myNetName
= myNetName
[0:255] #limit length
1587 myNetType
= sce_net
['type']
1589 myNetDict
["name"] = myNetName
1590 myNetDict
["type"] = myNetType
1591 myNetDict
["tenant_id"] = myvim_tenant
1592 myNetIPProfile
= sce_net
.get('ip_profile', None)
1594 #We should use the dictionary as input parameter for new_network
1596 if not sce_net
["external"]:
1597 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1598 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1599 sce_net
['vim_id'] = network_id
1600 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1601 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1602 sce_net
["created"] = True
1604 if sce_net
['vim_id'] == None:
1605 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1606 _
, message
= rollback(mydb
, vims
, rollbackList
)
1607 logger
.error("nfvo.start_scenario: %s", error_text
)
1608 raise NfvoException(error_text
, HTTP_Bad_Request
)
1609 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1610 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1612 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1613 #For each vnf net, we create it and we add it to instanceNetlist.
1614 for sce_vnf
in scenarioDict
['vnfs']:
1615 for net
in sce_vnf
['nets']:
1616 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1618 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1619 myNetName
= myNetName
[0:255] #limit length
1620 myNetType
= net
['type']
1622 myNetDict
["name"] = myNetName
1623 myNetDict
["type"] = myNetType
1624 myNetDict
["tenant_id"] = myvim_tenant
1625 myNetIPProfile
= net
.get('ip_profile', None)
1628 #We should use the dictionary as input parameter for new_network
1629 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1630 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1631 net
['vim_id'] = network_id
1632 if sce_vnf
['uuid'] not in auxNetDict
:
1633 auxNetDict
[sce_vnf
['uuid']] = {}
1634 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1635 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1636 net
["created"] = True
1638 #print "auxNetDict:"
1639 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1641 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1642 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1644 for sce_vnf
in scenarioDict
['vnfs']:
1645 for vm
in sce_vnf
['vms']:
1648 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1649 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
1650 #myVMDict['description'] = vm['description']
1651 myVMDict
['description'] = myVMDict
['name'][0:99]
1653 myVMDict
['start'] = "no"
1654 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1655 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1657 #create image at vim in case it not exist
1658 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1659 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1660 vm
['vim_image_id'] = image_id
1662 #create flavor at vim in case it not exist
1663 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1664 if flavor_dict
['extended']!=None:
1665 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1666 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1667 vm
['vim_flavor_id'] = flavor_id
1670 myVMDict
['imageRef'] = vm
['vim_image_id']
1671 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1672 myVMDict
['networks'] = []
1673 for iface
in vm
['interfaces']:
1675 if iface
['type']=="data":
1676 netDict
['type'] = iface
['model']
1677 elif "model" in iface
and iface
["model"]!=None:
1678 netDict
['model']=iface
['model']
1679 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1680 #discover type of interface looking at flavor
1681 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1682 for flavor_iface
in numa
.get('interfaces',[]):
1683 if flavor_iface
.get('name') == iface
['internal_name']:
1684 if flavor_iface
['dedicated'] == 'yes':
1685 netDict
['type']="PF" #passthrough
1686 elif flavor_iface
['dedicated'] == 'no':
1687 netDict
['type']="VF" #siov
1688 elif flavor_iface
['dedicated'] == 'yes:sriov':
1689 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1690 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1692 netDict
["use"]=iface
['type']
1693 if netDict
["use"]=="data" and not netDict
.get("type"):
1694 #print "netDict", netDict
1695 #print "iface", iface
1696 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'])
1697 if flavor_dict
.get('extended')==None:
1698 raise NfvoException(e_text
+ "After database migration some information is not available. \
1699 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1701 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1702 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1703 netDict
["type"]="virtual"
1704 if "vpci" in iface
and iface
["vpci"] is not None:
1705 netDict
['vpci'] = iface
['vpci']
1706 if "mac" in iface
and iface
["mac"] is not None:
1707 netDict
['mac_address'] = iface
['mac']
1708 if "port-security" in iface
and iface
["port-security"] is not None:
1709 netDict
['port_security'] = iface
['port-security']
1710 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
1711 netDict
['floating_ip'] = iface
['floating-ip']
1712 netDict
['name'] = iface
['internal_name']
1713 if iface
['net_id'] is None:
1714 for vnf_iface
in sce_vnf
["interfaces"]:
1717 if vnf_iface
['interface_id']==iface
['uuid']:
1718 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1721 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1722 #skip bridge ifaces not connected to any net
1723 #if 'net_id' not in netDict or netDict['net_id']==None:
1725 myVMDict
['networks'].append(netDict
)
1726 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1727 #print myVMDict['name']
1728 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1729 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1730 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1731 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1732 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1733 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1734 vm
['vim_id'] = vm_id
1735 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1736 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1737 for net
in myVMDict
['networks']:
1739 for iface
in vm
['interfaces']:
1740 if net
["name"]==iface
["internal_name"]:
1741 iface
["vim_id"]=net
["vim_id"]
1744 logger
.debug("start scenario Deployment done")
1745 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1746 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1747 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1748 return mydb
.get_instance_scenario(instance_id
)
1750 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1751 _
, message
= rollback(mydb
, vims
, rollbackList
)
1752 if isinstance(e
, db_base_Exception
):
1753 error_text
= "Exception at database"
1755 error_text
= "Exception at VIM"
1756 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1757 #logger.error("start_scenario %s", error_text)
1758 raise NfvoException(error_text
, e
.http_code
)
1761 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
1762 ''' join the cloud config information into cloud_config_preserve.
1763 In case of conflict cloud_config_preserve preserves
1766 if not cloud_config_preserve
and not cloud_config
:
1769 new_cloud_config
= {"key-pairs":[], "users":[]}
1771 if cloud_config_preserve
:
1772 for key
in cloud_config_preserve
.get("key-pairs", () ):
1773 if key
not in new_cloud_config
["key-pairs"]:
1774 new_cloud_config
["key-pairs"].append(key
)
1776 for key
in cloud_config
.get("key-pairs", () ):
1777 if key
not in new_cloud_config
["key-pairs"]:
1778 new_cloud_config
["key-pairs"].append(key
)
1779 if not new_cloud_config
["key-pairs"]:
1780 del new_cloud_config
["key-pairs"]
1784 new_cloud_config
["users"] += cloud_config
.get("users", () )
1785 if cloud_config_preserve
:
1786 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
1787 index_to_delete
= []
1788 users
= new_cloud_config
.get("users", [])
1789 for index0
in range(0,len(users
)):
1790 if index0
in index_to_delete
:
1792 for index1
in range(index0
+1,len(users
)):
1793 if index1
in index_to_delete
:
1795 if users
[index0
]["name"] == users
[index1
]["name"]:
1796 index_to_delete
.append(index1
)
1797 for key
in users
[index1
].get("key-pairs",()):
1798 if "key-pairs" not in users
[index0
]:
1799 users
[index0
]["key-pairs"] = [key
]
1800 elif key
not in users
[index0
]["key-pairs"]:
1801 users
[index0
]["key-pairs"].append(key
)
1802 index_to_delete
.sort(reverse
=True)
1803 for index
in index_to_delete
:
1805 if not new_cloud_config
["users"]:
1806 del new_cloud_config
["users"]
1809 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
1810 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
1811 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
1812 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
1815 if cloud_config
and cloud_config
.get("user-data") != None:
1816 new_cloud_config
["user-data"] = cloud_config
["user-data"]
1817 if cloud_config_preserve
and cloud_config_preserve
.get("user-data") != None:
1818 new_cloud_config
["user-data"] = cloud_config_preserve
["user-data"]
1821 new_cloud_config
["config-files"] = []
1822 if cloud_config
and cloud_config
.get("config-files") != None:
1823 new_cloud_config
["config-files"] += cloud_config
["config-files"]
1824 if cloud_config_preserve
:
1825 for file in cloud_config_preserve
.get("config-files", ()):
1826 for index
in range(0, len(new_cloud_config
["config-files"])):
1827 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
1828 new_cloud_config
["config-files"][index
] = file
1831 new_cloud_config
["config-files"].append(file)
1832 if not new_cloud_config
["config-files"]:
1833 del new_cloud_config
["config-files"]
1834 return new_cloud_config
1837 def get_vim_thread(tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
1838 datacenter_id
= None
1839 datacenter_name
= None
1841 if datacenter_id_name
:
1842 if utils
.check_valid_uuid(datacenter_id_name
):
1843 datacenter_id
= datacenter_id_name
1845 datacenter_name
= datacenter_id_name
1847 thread
= vim_threads
["running"].get(datacenter_id
+ "." + tenant_id
)
1849 for k
, v
in vim_threads
["running"].items():
1850 datacenter_tenant
= k
.split(".")
1851 if datacenter_tenant
[0] == datacenter_id
and datacenter_tenant
[1] == tenant_id
:
1853 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1855 elif not datacenter_id
and datacenter_tenant
[1] == tenant_id
:
1856 if thread
.datacenter_name
== datacenter_name
:
1858 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1861 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1865 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
1866 datacenter_id
= None
1867 datacenter_name
= None
1868 if datacenter_id_name
:
1869 if utils
.check_valid_uuid(datacenter_id_name
):
1870 datacenter_id
= datacenter_id_name
1872 datacenter_name
= datacenter_id_name
1873 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
1875 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1877 #print "nfvo.datacenter_action() error. Several datacenters found"
1878 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1879 return vims
.keys()[0], vims
.values()[0]
1883 '''Takes dict d and updates it with the values in dict u.'''
1884 '''It merges all depth levels'''
1885 for k
, v
in u
.iteritems():
1886 if isinstance(v
, collections
.Mapping
):
1887 r
= update(d
.get(k
, {}), v
)
1894 def create_instance(mydb
, tenant_id
, instance_dict
):
1895 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1896 # logger.debug("Creating instance...")
1897 scenario
= instance_dict
["scenario"]
1899 #find main datacenter
1902 datacenter2tenant
= {}
1903 datacenter
= instance_dict
.get("datacenter")
1904 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
1905 myvims
[default_datacenter_id
] = vim
1906 myvim_threads
[default_datacenter_id
] = get_vim_thread(tenant_id
, default_datacenter_id
)
1907 datacenter2tenant
[default_datacenter_id
] = vim
['config']['datacenter_tenant_id']
1908 #myvim_tenant = myvim['tenant_id']
1909 # default_datacenter_name = vim['name']
1912 #print "Checking that the scenario exists and getting the scenario dictionary"
1913 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, default_datacenter_id
)
1915 #logger.debug(">>>>>>> Dictionaries before merging")
1916 #logger.debug(">>>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
1917 #logger.debug(">>>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
1919 scenarioDict
['datacenter_id'] = default_datacenter_id
1921 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1922 auxNetDict
['scenario'] = {}
1924 logger
.debug("Creating instance from scenario-dict:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)) #TODO remove
1925 instance_name
= instance_dict
["name"]
1926 instance_description
= instance_dict
.get("description")
1929 # 0 check correct parameters
1930 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1932 for scenario_net
in scenarioDict
['nets']:
1933 if net_name
== scenario_net
["name"]:
1937 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
), HTTP_Bad_Request
)
1938 if "sites" not in net_instance_desc
:
1939 net_instance_desc
["sites"] = [ {} ]
1940 site_without_datacenter_field
= False
1941 for site
in net_instance_desc
["sites"]:
1942 if site
.get("datacenter"):
1943 if site
["datacenter"] not in myvims
:
1944 #Add this datacenter to myvims
1945 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
1947 myvim_threads
[d
] = get_vim_thread(tenant_id
, site
["datacenter"])
1948 datacenter2tenant
[d
] = v
['config']['datacenter_tenant_id']
1949 site
["datacenter"] = d
#change name to id
1951 if site_without_datacenter_field
:
1952 raise NfvoException("Found more than one entries without datacenter field at instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
1953 site_without_datacenter_field
= True
1954 site
["datacenter"] = default_datacenter_id
#change name to id
1956 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
1958 for scenario_vnf
in scenarioDict
['vnfs']:
1959 if vnf_name
== scenario_vnf
['name']:
1963 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
1964 if "datacenter" in vnf_instance_desc
:
1965 # Add this datacenter to myvims
1966 if vnf_instance_desc
["datacenter"] not in myvims
:
1967 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
1969 myvim_threads
[d
] = get_vim_thread(tenant_id
, vnf_instance_desc
["datacenter"])
1970 datacenter2tenant
[d
] = v
['config']['datacenter_tenant_id']
1971 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
1973 #0.1 parse cloud-config parameters
1974 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
1976 #0.2 merge instance information into scenario
1977 #Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
1978 #However, this is not possible yet.
1979 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1980 for scenario_net
in scenarioDict
['nets']:
1981 if net_name
== scenario_net
["name"]:
1982 if 'ip-profile' in net_instance_desc
:
1983 ipprofile
= net_instance_desc
['ip-profile']
1984 ipprofile
['subnet_address'] = ipprofile
.pop('subnet-address',None)
1985 ipprofile
['ip_version'] = ipprofile
.pop('ip-version','IPv4')
1986 ipprofile
['gateway_address'] = ipprofile
.pop('gateway-address',None)
1987 ipprofile
['dns_address'] = ipprofile
.pop('dns-address',None)
1988 if 'dhcp' in ipprofile
:
1989 ipprofile
['dhcp_start_address'] = ipprofile
['dhcp'].get('start-address',None)
1990 ipprofile
['dhcp_enabled'] = ipprofile
['dhcp'].get('enabled',True)
1991 ipprofile
['dhcp_count'] = ipprofile
['dhcp'].get('count',None)
1992 del ipprofile
['dhcp']
1993 if 'ip_profile' not in scenario_net
:
1994 scenario_net
['ip_profile'] = ipprofile
1996 update(scenario_net
['ip_profile'],ipprofile
)
1997 for interface
in net_instance_desc
.get('interfaces', () ):
1998 if 'ip_address' in interface
:
1999 for vnf
in scenarioDict
['vnfs']:
2000 if interface
['vnf'] == vnf
['name']:
2001 for vnf_interface
in vnf
['interfaces']:
2002 if interface
['vnf_interface'] == vnf_interface
['external_name']:
2003 vnf_interface
['ip_address']=interface
['ip_address']
2005 #logger.debug(">>>>>>>> Merged dictionary")
2006 logger
.debug("Creating instance scenario-dict MERGED:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False))
2009 # 1. Creating new nets (sce_nets) in the VIM"
2010 for sce_net
in scenarioDict
['nets']:
2011 sce_net
["vim_id_sites"]={}
2012 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
2013 net_name
= descriptor_net
.get("vim-network-name")
2014 auxNetDict
['scenario'][sce_net
['uuid']] = {}
2016 sites
= descriptor_net
.get("sites", [ {} ])
2018 if site
.get("datacenter"):
2019 vim
= myvims
[ site
["datacenter"] ]
2020 datacenter_id
= site
["datacenter"]
2021 myvim_thread
= myvim_threads
[ site
["datacenter"] ]
2023 vim
= myvims
[ default_datacenter_id
]
2024 datacenter_id
= default_datacenter_id
2025 myvim_thread
= myvim_threads
[default_datacenter_id
]
2026 net_type
= sce_net
['type']
2027 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
2028 if sce_net
["external"]:
2030 net_name
= sce_net
["name"]
2031 if "netmap-use" in site
or "netmap-create" in site
:
2032 create_network
= False
2033 lookfor_network
= False
2034 if "netmap-use" in site
:
2035 lookfor_network
= True
2036 if utils
.check_valid_uuid(site
["netmap-use"]):
2037 filter_text
= "scenario id '%s'" % site
["netmap-use"]
2038 lookfor_filter
["id"] = site
["netmap-use"]
2040 filter_text
= "scenario name '%s'" % site
["netmap-use"]
2041 lookfor_filter
["name"] = site
["netmap-use"]
2042 if "netmap-create" in site
:
2043 create_network
= True
2044 net_vim_name
= net_name
2045 if site
["netmap-create"]:
2046 net_vim_name
= site
["netmap-create"]
2048 elif sce_net
['vim_id'] != None:
2049 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
2050 create_network
= False
2051 lookfor_network
= True
2052 lookfor_filter
["id"] = sce_net
['vim_id']
2053 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
2054 #look for network at datacenter and return error
2056 #There is not a netmap, look at datacenter for a net with this name and create if not found
2057 create_network
= True
2058 lookfor_network
= True
2059 lookfor_filter
["name"] = sce_net
["name"]
2060 net_vim_name
= sce_net
["name"]
2061 filter_text
= "scenario name '%s'" % sce_net
["name"]
2064 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
2065 net_name
= net_name
[:255] #limit length
2066 net_vim_name
= net_name
2067 create_network
= True
2068 lookfor_network
= False
2071 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
2072 if len(vim_nets
) > 1:
2073 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2074 elif len(vim_nets
) == 0:
2075 if not create_network
:
2076 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2078 sce_net
["vim_id_sites"][datacenter_id
] = vim_nets
[0]['id']
2079 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
2080 create_network
= False
2082 #if network is not external
2083 task
= new_task("new-net", (net_vim_name
, net_type
, sce_net
.get('ip_profile',None)))
2084 task_id
= myvim_thread
.insert_task(task
)
2085 instance_tasks
[task_id
] = task
2086 #network_id = vim.new_network(net_vim_name, net_type, sce_net.get('ip_profile',None))
2087 sce_net
["vim_id_sites"][datacenter_id
] = task_id
2088 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = task_id
2089 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':task_id
})
2090 sce_net
["created"] = True
2092 # 2. Creating new nets (vnf internal nets) in the VIM"
2093 #For each vnf net, we create it and we add it to instanceNetlist.
2094 for sce_vnf
in scenarioDict
['vnfs']:
2095 for net
in sce_vnf
['nets']:
2096 if sce_vnf
.get("datacenter"):
2097 vim
= myvims
[ sce_vnf
["datacenter"] ]
2098 datacenter_id
= sce_vnf
["datacenter"]
2099 myvim_thread
= myvim_threads
[ sce_vnf
["datacenter"]]
2101 vim
= myvims
[ default_datacenter_id
]
2102 datacenter_id
= default_datacenter_id
2103 myvim_thread
= myvim_threads
[default_datacenter_id
]
2104 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
2105 net_name
= descriptor_net
.get("name")
2107 net_name
= "%s.%s" %(instance_name
, net
["name"])
2108 net_name
= net_name
[:255] #limit length
2109 net_type
= net
['type']
2110 task
= new_task("new-net", (net_name
, net_type
, net
.get('ip_profile',None)))
2111 task_id
= myvim_thread
.insert_task(task
)
2112 instance_tasks
[task_id
] = task
2113 # network_id = vim.new_network(net_name, net_type, net.get('ip_profile',None))
2114 net
['vim_id'] = task_id
2115 if sce_vnf
['uuid'] not in auxNetDict
:
2116 auxNetDict
[sce_vnf
['uuid']] = {}
2117 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = task_id
2118 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':task_id
})
2119 net
["created"] = True
2122 #print "auxNetDict:"
2123 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2125 # 3. Creating new vm instances in the VIM
2126 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2127 for sce_vnf
in scenarioDict
['vnfs']:
2128 if sce_vnf
.get("datacenter"):
2129 vim
= myvims
[ sce_vnf
["datacenter"] ]
2130 myvim_thread
= myvim_threads
[ sce_vnf
["datacenter"] ]
2131 datacenter_id
= sce_vnf
["datacenter"]
2133 vim
= myvims
[ default_datacenter_id
]
2134 myvim_thread
= myvim_threads
[ default_datacenter_id
]
2135 datacenter_id
= default_datacenter_id
2136 sce_vnf
["datacenter_id"] = datacenter_id
2138 for vm
in sce_vnf
['vms']:
2141 myVMDict
['name'] = "{}.{}.{}".format(instance_name
,sce_vnf
['name'],chr(96+i
))
2142 myVMDict
['description'] = myVMDict
['name'][0:99]
2144 # myVMDict['start'] = "no"
2145 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2146 #create image at vim in case it not exist
2147 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2148 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
2149 vm
['vim_image_id'] = image_id
2151 #create flavor at vim in case it not exist
2152 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2153 if flavor_dict
['extended']!=None:
2154 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2155 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
2157 #Obtain information for additional disks
2158 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',), WHERE
={'vim_id': flavor_id
})
2159 if not extended_flavor_dict
:
2160 raise NfvoException("flavor '{}' not found".format(flavor_id
), HTTP_Not_Found
)
2163 #extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
2164 myVMDict
['disks'] = None
2165 extended_info
= extended_flavor_dict
[0]['extended']
2166 if extended_info
!= None:
2167 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
2168 if 'disks' in extended_flavor_dict_yaml
:
2169 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
2171 vm
['vim_flavor_id'] = flavor_id
2172 myVMDict
['imageRef'] = vm
['vim_image_id']
2173 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2174 myVMDict
['networks'] = []
2176 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
2177 for iface
in vm
['interfaces']:
2179 if iface
['type']=="data":
2180 netDict
['type'] = iface
['model']
2181 elif "model" in iface
and iface
["model"]!=None:
2182 netDict
['model']=iface
['model']
2183 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2184 #discover type of interface looking at flavor
2185 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2186 for flavor_iface
in numa
.get('interfaces',[]):
2187 if flavor_iface
.get('name') == iface
['internal_name']:
2188 if flavor_iface
['dedicated'] == 'yes':
2189 netDict
['type']="PF" #passthrough
2190 elif flavor_iface
['dedicated'] == 'no':
2191 netDict
['type']="VF" #siov
2192 elif flavor_iface
['dedicated'] == 'yes:sriov':
2193 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2194 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2196 netDict
["use"]=iface
['type']
2197 if netDict
["use"]=="data" and not netDict
.get("type"):
2198 #print "netDict", netDict
2199 #print "iface", iface
2200 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'])
2201 if flavor_dict
.get('extended')==None:
2202 raise NfvoException(e_text
+ "After database migration some information is not available. \
2203 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
2205 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
2206 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2207 netDict
["type"]="virtual"
2208 if "vpci" in iface
and iface
["vpci"] is not None:
2209 netDict
['vpci'] = iface
['vpci']
2210 if "mac" in iface
and iface
["mac"] is not None:
2211 netDict
['mac_address'] = iface
['mac']
2212 if "port-security" in iface
and iface
["port-security"] is not None:
2213 netDict
['port_security'] = iface
['port-security']
2214 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2215 netDict
['floating_ip'] = iface
['floating-ip']
2216 netDict
['name'] = iface
['internal_name']
2217 if iface
['net_id'] is None:
2218 for vnf_iface
in sce_vnf
["interfaces"]:
2221 if vnf_iface
['interface_id']==iface
['uuid']:
2222 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
2225 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2226 if is_task_id(netDict
['net_id']):
2227 task_depends
[netDict
['net_id']] = instance_tasks
[netDict
['net_id']]
2228 #skip bridge ifaces not connected to any net
2229 #if 'net_id' not in netDict or netDict['net_id']==None:
2231 myVMDict
['networks'].append(netDict
)
2232 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2233 #print myVMDict['name']
2234 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2235 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2236 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2237 if vm
.get("boot_data"):
2238 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config
)
2240 cloud_config_vm
= cloud_config
2241 task
= new_task("new-vm", (myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2242 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2243 cloud_config_vm
, myVMDict
['disks']), depends
=task_depends
)
2244 vm_id
= myvim_thread
.insert_task(task
)
2245 instance_tasks
[vm_id
] = task
2247 vm
['vim_id'] = vm_id
2248 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2249 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2250 for net
in myVMDict
['networks']:
2252 for iface
in vm
['interfaces']:
2253 if net
["name"]==iface
["internal_name"]:
2254 iface
["vim_id"]=net
["vim_id"]
2256 scenarioDict
["datacenter2tenant"] = datacenter2tenant
2257 logger
.debug("create_instance Deployment done scenarioDict: %s",
2258 yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False) )
2259 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
2260 # Update database with those ended tasks
2261 for task
in instance_tasks
.values():
2262 if task
["status"] == "ok":
2263 if task
["name"] == "new-vm":
2264 mydb
.update_rows("instance_vms", UPDATE
={"vim_vm_id": task
["result"]},
2265 WHERE
={"vim_vm_id": task
["id"]})
2266 elif task
["name"] == "new-net":
2267 mydb
.update_rows("instance_nets", UPDATE
={"vim_net_id": task
["result"]},
2268 WHERE
={"vim_net_id": task
["id"]})
2269 return mydb
.get_instance_scenario(instance_id
)
2270 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
2271 message
= rollback(mydb
, myvims
, rollbackList
)
2272 if isinstance(e
, db_base_Exception
):
2273 error_text
= "database Exception"
2274 elif isinstance(e
, vimconn
.vimconnException
):
2275 error_text
= "VIM Exception"
2277 error_text
= "Exception"
2278 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2279 #logger.error("create_instance: %s", error_text)
2280 raise NfvoException(error_text
, e
.http_code
)
2283 def delete_instance(mydb
, tenant_id
, instance_id
):
2284 #print "Checking that the instance_id exists and getting the instance dictionary"
2285 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
2286 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2287 tenant_id
= instanceDict
["tenant_id"]
2288 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2290 #1. Delete from Database
2291 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
2300 for sce_vnf
in instanceDict
['vnfs']:
2301 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2302 if datacenter_key
not in myvims
:
2304 myvim_thread
= get_vim_thread(tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2305 except NfvoException
as e
:
2306 logger
.error(str(e
))
2308 myvim_threads
[datacenter_key
] = myvim_thread
2309 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
2310 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2312 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
2313 sce_vnf
["datacenter_tenant_id"]))
2314 myvims
[datacenter_key
] = None
2316 myvims
[datacenter_key
] = vims
.values()[0]
2317 myvim
= myvims
[datacenter_key
]
2318 myvim_thread
= myvim_threads
[datacenter_key
]
2319 for vm
in sce_vnf
['vms']:
2321 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2325 if is_task_id(vm
['vim_vm_id']):
2326 task_id
= vm
['vim_vm_id']
2327 old_task
= task_dict
.get(task_id
)
2329 error_msg
+= "\n VM was scheduled for create, but task {} is not found".format(task_id
)
2332 if old_task
["status"] == "enqueued":
2333 old_task
["status"] = "deleted"
2334 elif old_task
["status"] == "error":
2336 elif old_task
["status"] == "processing":
2337 task
= new_task("del-vm", task_id
, depends
={task_id
: old_task
})
2339 task
= new_task("del-vm", old_task
["result"])
2341 task
= new_task("del-vm", vm
['vim_vm_id'], store
=False)
2343 myvim_thread
.insert_task(task
)
2344 except vimconn
.vimconnNotFoundException
as e
:
2345 error_msg
+="\n VM VIM_id={} not found at datacenter={}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2346 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
2347 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
2348 except vimconn
.vimconnException
as e
:
2349 error_msg
+="\n VM VIM_id={} at datacenter={} Error: {} {}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"], e
.http_code
, str(e
))
2350 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s",
2351 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
2355 for net
in instanceDict
['nets']:
2356 if not net
['created']:
2357 continue #skip not created nets
2358 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2359 if datacenter_key
not in myvims
:
2361 myvim_thread
= get_vim_thread(tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2362 except NfvoException
as e
:
2363 logger
.error(str(e
))
2365 myvim_threads
[datacenter_key
] = myvim_thread
2366 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
2367 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2369 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2370 myvims
[datacenter_key
] = None
2372 myvims
[datacenter_key
] = vims
.values()[0]
2373 myvim
= myvims
[datacenter_key
]
2374 myvim_thread
= myvim_threads
[datacenter_key
]
2377 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
2381 if is_task_id(net
['vim_net_id']):
2382 task_id
= net
['vim_net_id']
2383 old_task
= task_dict
.get(task_id
)
2385 error_msg
+= "\n NET was scheduled for create, but task {} is not found".format(task_id
)
2388 if old_task
["status"] == "enqueued":
2389 old_task
["status"] = "deleted"
2390 elif old_task
["status"] == "error":
2392 elif old_task
["status"] == "processing":
2393 task
= new_task("del-net", task_id
, depends
={task_id
: old_task
})
2395 task
= new_task("del-net", old_task
["result"])
2397 task
= new_task("del-net", net
['vim_net_id'], store
=False)
2399 myvim_thread
.insert_task(task
)
2400 except vimconn
.vimconnNotFoundException
as e
:
2401 error_msg
+= "\n NET VIM_id={} not found at datacenter={}".format(net
['vim_net_id'], net
["datacenter_id"])
2402 logger
.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found",
2403 net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']))
2404 except vimconn
.vimconnException
as e
:
2405 error_msg
+= "\n NET VIM_id={} at datacenter={} Error: {} {}".format(net
['vim_net_id'],
2406 net
["datacenter_id"],
2407 e
.http_code
, str(e
))
2408 logger
.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s",
2409 e
.http_code
, net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']), str(e
))
2410 if len(error_msg
) > 0:
2411 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
2413 return 'instance ' + message
+ ' deleted'
2416 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
2417 '''Refreshes a scenario instance. It modifies instanceDict'''
2419 - 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
2422 # Assumption: nfvo_tenant and instance_id were checked before entering into this function
2423 #print "nfvo.refresh_instance begins"
2424 #print json.dumps(instanceDict, indent=4)
2426 #print "Getting the VIM URL and the VIM tenant_id"
2429 # 1. Getting VIM vm and net list
2430 vms_updated
= [] #List of VM instance uuids in openmano that were updated
2433 for sce_vnf
in instanceDict
['vnfs']:
2434 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2435 if datacenter_key
not in vm_list
:
2436 vm_list
[datacenter_key
] = []
2437 if datacenter_key
not in myvims
:
2438 vims
= get_vim(mydb
, nfvo_tenant
, datacenter_id
=sce_vnf
["datacenter_id"],
2439 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2441 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"]))
2442 myvims
[datacenter_key
] = None
2444 myvims
[datacenter_key
] = vims
.values()[0]
2445 for vm
in sce_vnf
['vms']:
2446 vm_list
[datacenter_key
].append(vm
['vim_vm_id'])
2447 vms_notupdated
.append(vm
["uuid"])
2449 nets_updated
= [] #List of VM instance uuids in openmano that were updated
2452 for net
in instanceDict
['nets']:
2453 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2454 if datacenter_key
not in net_list
:
2455 net_list
[datacenter_key
] = []
2456 if datacenter_key
not in myvims
:
2457 vims
= get_vim(mydb
, nfvo_tenant
, datacenter_id
=net
["datacenter_id"],
2458 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2460 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2461 myvims
[datacenter_key
] = None
2463 myvims
[datacenter_key
] = vims
.values()[0]
2465 net_list
[datacenter_key
].append(net
['vim_net_id'])
2466 nets_notupdated
.append(net
["uuid"])
2468 # 1. Getting the status of all VMs
2470 for datacenter_key
in myvims
:
2471 if not vm_list
.get(datacenter_key
):
2475 if not myvims
[datacenter_key
]:
2476 failed_message
= "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"])
2479 vm_dict
.update(myvims
[datacenter_key
].refresh_vms_status(vm_list
[datacenter_key
]) )
2481 except vimconn
.vimconnException
as e
:
2482 logger
.error("VIM exception %s %s", type(e
).__name
__, str(e
))
2483 failed_message
= str(e
)
2485 for vm
in vm_list
[datacenter_key
]:
2486 vm_dict
[vm
] = {'status': "VIM_ERROR", 'error_msg': failed_message
}
2488 # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
2489 for sce_vnf
in instanceDict
['vnfs']:
2490 for vm
in sce_vnf
['vms']:
2491 vm_id
= vm
['vim_vm_id']
2492 interfaces
= vm_dict
[vm_id
].pop('interfaces', [])
2493 #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
2494 has_mgmt_iface
= False
2495 for iface
in vm
["interfaces"]:
2496 if iface
["type"]=="mgmt":
2497 has_mgmt_iface
= True
2498 if vm_dict
[vm_id
]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface
:
2499 vm_dict
[vm_id
]['status'] = "ACTIVE"
2500 if vm_dict
[vm_id
].get('error_msg') and len(vm_dict
[vm_id
]['error_msg']) >= 1024:
2501 vm_dict
[vm_id
]['error_msg'] = vm_dict
[vm_id
]['error_msg'][:516] + " ... " + vm_dict
[vm_id
]['error_msg'][-500:]
2502 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'):
2503 vm
['status'] = vm_dict
[vm_id
]['status']
2504 vm
['error_msg'] = vm_dict
[vm_id
].get('error_msg')
2505 vm
['vim_info'] = vm_dict
[vm_id
].get('vim_info')
2506 # 2.1. Update in openmano DB the VMs whose status changed
2508 updates
= mydb
.update_rows('instance_vms', UPDATE
=vm_dict
[vm_id
], WHERE
={'uuid':vm
["uuid"]})
2509 vms_notupdated
.remove(vm
["uuid"])
2511 vms_updated
.append(vm
["uuid"])
2512 except db_base_Exception
as e
:
2513 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2514 # 2.2. Update in openmano DB the interface VMs
2515 for interface
in interfaces
:
2516 #translate from vim_net_id to instance_net_id
2518 for net
in instanceDict
['nets']:
2519 if net
["vim_net_id"] == interface
["vim_net_id"]:
2520 network_id_list
.append(net
["uuid"])
2521 if not network_id_list
:
2523 del interface
["vim_net_id"]
2525 for network_id
in network_id_list
:
2526 mydb
.update_rows('instance_interfaces', UPDATE
=interface
, WHERE
={'instance_vm_id':vm
["uuid"], "instance_net_id":network_id
})
2527 except db_base_Exception
as e
:
2528 logger
.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm
["uuid"], network_id
)
2530 # 3. Getting the status of all nets
2532 for datacenter_key
in myvims
:
2533 if not net_list
.get(datacenter_key
):
2537 if not myvims
[datacenter_key
]:
2538 failed_message
= "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"])
2541 net_dict
.update(myvims
[datacenter_key
].refresh_nets_status(net_list
[datacenter_key
]) )
2543 except vimconn
.vimconnException
as e
:
2544 logger
.error("VIM exception %s %s", type(e
).__name
__, str(e
))
2545 failed_message
= str(e
)
2547 for net
in net_list
[datacenter_key
]:
2548 net_dict
[net
] = {'status': "VIM_ERROR", 'error_msg': failed_message
}
2550 # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
2551 # TODO: update nets inside a vnf
2552 for net
in instanceDict
['nets']:
2553 net_id
= net
['vim_net_id']
2554 if net_dict
[net_id
].get('error_msg') and len(net_dict
[net_id
]['error_msg']) >= 1024:
2555 net_dict
[net_id
]['error_msg'] = net_dict
[net_id
]['error_msg'][:516] + " ... " + net_dict
[vm_id
]['error_msg'][-500:]
2556 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'):
2557 net
['status'] = net_dict
[net_id
]['status']
2558 net
['error_msg'] = net_dict
[net_id
].get('error_msg')
2559 net
['vim_info'] = net_dict
[net_id
].get('vim_info')
2560 # 5.1. Update in openmano DB the nets whose status changed
2562 updated
= mydb
.update_rows('instance_nets', UPDATE
=net_dict
[net_id
], WHERE
={'uuid':net
["uuid"]})
2563 nets_notupdated
.remove(net
["uuid"])
2565 nets_updated
.append(net
["uuid"])
2566 except db_base_Exception
as e
:
2567 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2569 # Returns appropriate output
2570 #print "nfvo.refresh_instance finishes"
2571 logger
.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
2572 str(vms_updated
), str(nets_updated
), str(vms_notupdated
), str(nets_notupdated
))
2573 instance_id
= instanceDict
['uuid']
2574 if len(vms_notupdated
)+len(nets_notupdated
)>0:
2575 error_msg
= "VMs not updated: " + str(vms_notupdated
) + "; nets not updated: " + str(nets_notupdated
)
2576 return len(vms_notupdated
)+len(nets_notupdated
), 'Scenario instance ' + instance_id
+ ' refreshed but some elements could not be updated in the database: ' + error_msg
2578 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
2581 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
2582 #print "Checking that the instance_id exists and getting the instance dictionary"
2583 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
2584 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2586 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2587 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2589 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2590 myvim
= vims
.values()[0]
2593 input_vnfs
= action_dict
.pop("vnfs", [])
2594 input_vms
= action_dict
.pop("vms", [])
2595 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
2599 for sce_vnf
in instanceDict
['vnfs']:
2600 for vm
in sce_vnf
['vms']:
2601 if not action_over_all
:
2602 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
2603 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
2606 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
2607 if "console" in action_dict
:
2608 if not global_config
["http_console_proxy"]:
2609 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2610 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2611 protocol
=data
["protocol"],
2612 ip
= data
["server"],
2613 port
= data
["port"],
2614 suffix
= data
["suffix"]),
2618 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
2619 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
2620 "description": "this console is only reachable by local interface",
2625 #print "console data", data
2627 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
2628 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2629 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2630 protocol
=data
["protocol"],
2631 ip
= global_config
["http_console_host"],
2632 port
= console_thread
.port
,
2633 suffix
= data
["suffix"]),
2637 except NfvoException
as e
:
2638 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2642 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
2644 except vimconn
.vimconnException
as e
:
2645 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2648 if vm_ok
==0: #all goes wrong
2654 def create_or_use_console_proxy_thread(console_server
, console_port
):
2655 #look for a non-used port
2656 console_thread_key
= console_server
+ ":" + str(console_port
)
2657 if console_thread_key
in global_config
["console_thread"]:
2658 #global_config["console_thread"][console_thread_key].start_timeout()
2659 return global_config
["console_thread"][console_thread_key
]
2661 for port
in global_config
["console_port_iterator"]():
2662 #print "create_or_use_console_proxy_thread() port:", port
2663 if port
in global_config
["console_ports"]:
2666 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
2668 global_config
["console_thread"][console_thread_key
] = clithread
2669 global_config
["console_ports"][port
] = console_thread_key
2671 except cli
.ConsoleProxyExceptionPortUsed
as e
:
2672 #port used, try with onoher
2674 except cli
.ConsoleProxyException
as e
:
2675 raise NfvoException(str(e
), HTTP_Bad_Request
)
2676 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
2679 def check_tenant(mydb
, tenant_id
):
2680 '''check that tenant exists at database'''
2681 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
2683 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
2687 def new_tenant(mydb
, tenant_dict
):
2688 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
2692 def delete_tenant(mydb
, tenant
):
2693 #get nfvo_tenant info
2695 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
2696 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
2697 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
2700 def new_datacenter(mydb
, datacenter_descriptor
):
2701 if "config" in datacenter_descriptor
:
2702 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2703 #Check that datacenter-type is correct
2704 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
2707 module
= "vimconn_" + datacenter_type
2708 module_info
= imp
.find_module(module
)
2709 except (IOError, ImportError):
2710 if module_info
and module_info
[0]:
2711 file.close(module_info
[0])
2712 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
2714 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
2715 return datacenter_id
2718 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2719 #obtain data, check that only one exist
2720 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2722 datacenter_id
= datacenter
['uuid']
2723 where
={'uuid': datacenter
['uuid']}
2724 if "config" in datacenter_descriptor
:
2725 if datacenter_descriptor
['config']!=None:
2727 new_config_dict
= datacenter_descriptor
["config"]
2730 for k
in new_config_dict
:
2731 if new_config_dict
[k
]==None:
2734 config_dict
= yaml
.load(datacenter
["config"])
2735 config_dict
.update(new_config_dict
)
2739 except Exception as e
:
2740 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
2741 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
2742 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
2743 return datacenter_id
2746 def delete_datacenter(mydb
, datacenter
):
2747 #get nfvo_tenant info
2748 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
2749 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
2750 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
2753 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):
2754 #get datacenter info
2755 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2756 datacenter_name
= myvim
["name"]
2758 create_vim_tenant
= True if not vim_tenant_id
and not vim_tenant_name
else False
2760 # get nfvo_tenant info
2761 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2762 if vim_tenant_name
==None:
2763 vim_tenant_name
=tenant_dict
['name']
2765 #check that this association does not exist before
2766 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2767 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2768 if len(tenants_datacenters
)>0:
2769 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
2771 vim_tenant_id_exist_atdb
=False
2772 if not create_vim_tenant
:
2773 where_
={"datacenter_id": datacenter_id
}
2774 if vim_tenant_id
!=None:
2775 where_
["vim_tenant_id"] = vim_tenant_id
2776 if vim_tenant_name
!=None:
2777 where_
["vim_tenant_name"] = vim_tenant_name
2778 #check if vim_tenant_id is already at database
2779 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
2780 if len(datacenter_tenants_dict
)>=1:
2781 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2782 vim_tenant_id_exist_atdb
=True
2783 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2785 datacenter_tenants_dict
= {}
2786 #insert at table datacenter_tenants
2787 else: #if vim_tenant_id==None:
2788 #create tenant at VIM if not provided
2790 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2791 except vimconn
.vimconnException
as e
:
2792 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
2793 datacenter_tenants_dict
= {}
2794 datacenter_tenants_dict
["created"]="true"
2796 #fill datacenter_tenants table
2797 if not vim_tenant_id_exist_atdb
:
2798 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2799 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2800 datacenter_tenants_dict
["user"] = vim_username
2801 datacenter_tenants_dict
["passwd"] = vim_password
2802 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2804 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
2805 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
2806 datacenter_tenants_dict
["uuid"] = id_
2808 #fill tenants_datacenters table
2809 tenants_datacenter_dict
["datacenter_tenant_id"]=datacenter_tenants_dict
["uuid"]
2810 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
2812 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_dict
['uuid'], datacenter_id
) # reload data
2813 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
2814 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, datacenter_name
, db
=db
, db_lock
=db_lock
)
2816 thread_id
= datacenter_id
+ "." + tenant_dict
['uuid']
2817 vim_threads
["running"][thread_id
] = new_thread
2818 return datacenter_id
2821 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2822 #get datacenter info
2823 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2825 #get nfvo_tenant info
2826 if not tenant_id
or tenant_id
=="any":
2829 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
2830 tenant_uuid
= tenant_dict
['uuid']
2832 #check that this association exist before
2833 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
2835 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
2836 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2837 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
2838 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
2840 #delete this association
2841 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2843 #get vim_tenant info and deletes
2845 for tenant_datacenter_item
in tenant_datacenter_list
:
2846 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2847 #try to delete vim:tenant
2849 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2850 if vim_tenant_dict
['created']=='true':
2851 #delete tenant at VIM if created by NFVO
2853 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2854 except vimconn
.vimconnException
as e
:
2855 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
2856 logger
.warn(warning
)
2857 except db_base_Exception
as e
:
2858 logger
.error("Cannot delete datacenter_tenants " + str(e
))
2859 pass # the error will be caused because dependencies, vim_tenant can not be deleted
2860 thread_id
= datacenter_id
+ "." + tenant_datacenter_item
["nfvo_tenant_id"]
2861 thread
= vim_threads
["running"][thread_id
]
2862 thread
.insert_task(new_task("exit", None, store
=False))
2863 vim_threads
["deleting"][thread_id
] = thread
2864 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
2867 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
2869 #get datacenter info
2870 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2872 if 'net-update' in action_dict
:
2874 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2876 except vimconn
.vimconnException
as e
:
2877 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
2878 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2879 #update nets Change from VIM format to NFVO format
2882 net_nfvo
={'datacenter_id': datacenter_id
}
2883 net_nfvo
['name'] = net
['name']
2884 #net_nfvo['description']= net['name']
2885 net_nfvo
['vim_net_id'] = net
['id']
2886 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2887 net_nfvo
['shared'] = net
['shared']
2888 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2889 net_list
.append(net_nfvo
)
2890 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
2891 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
2893 elif 'net-edit' in action_dict
:
2894 net
= action_dict
['net-edit'].pop('net')
2895 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2896 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
2897 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2899 elif 'net-delete' in action_dict
:
2900 net
= action_dict
['net-deelte'].get('net')
2901 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2902 result
= mydb
.delete_row(FROM
='datacenter_nets',
2903 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2907 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
2910 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
2911 #get datacenter info
2912 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2914 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
2915 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
2916 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
2920 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
2921 #get datacenter info
2922 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2925 action_dict
= action_dict
["netmap"]
2926 if 'vim_id' in action_dict
:
2927 filter_dict
["id"] = action_dict
['vim_id']
2928 if 'vim_name' in action_dict
:
2929 filter_dict
["name"] = action_dict
['vim_name']
2931 filter_dict
["shared"] = True
2934 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
2935 except vimconn
.vimconnException
as e
:
2936 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
2937 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2938 if len(vim_nets
)>1 and action_dict
:
2939 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
2940 elif len(vim_nets
)==0: # and action_dict:
2941 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
2943 for net
in vim_nets
:
2944 net_nfvo
={'datacenter_id': datacenter_id
}
2945 if action_dict
and "name" in action_dict
:
2946 net_nfvo
['name'] = action_dict
['name']
2948 net_nfvo
['name'] = net
['name']
2949 #net_nfvo['description']= net['name']
2950 net_nfvo
['vim_net_id'] = net
['id']
2951 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2952 net_nfvo
['shared'] = net
['shared']
2953 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2955 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
2956 net_nfvo
["status"] = "OK"
2957 net_nfvo
["uuid"] = net_id
2958 except db_base_Exception
as e
:
2962 net_nfvo
["status"] = "FAIL: " + str(e
)
2963 net_list
.append(net_nfvo
)
2967 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
2968 #get datacenter info
2969 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2972 if utils
.check_valid_uuid(name
):
2973 filter_dict
["id"] = name
2975 filter_dict
["name"] = name
2977 if item
=="networks":
2978 #filter_dict['tenant_id'] = myvim['tenant_id']
2979 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
2980 elif item
=="tenants":
2981 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
2982 elif item
== "images":
2983 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
2985 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2986 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
2987 if name
and len(content
)==1:
2988 return {item
[:-1]: content
[0]}
2989 elif name
and len(content
)==0:
2990 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
2993 return {item
: content
}
2994 except vimconn
.vimconnException
as e
:
2995 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
2996 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
2999 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
3000 #get datacenter info
3001 if tenant_id
== "any":
3004 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3006 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
3007 logger
.debug("vim_action_delete vim response: " + str(content
))
3008 items
= content
.values()[0]
3009 if type(items
)==list and len(items
)==0:
3010 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
3011 elif type(items
)==list and len(items
)>1:
3012 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
3013 else: # it is a dict
3014 item_id
= items
["id"]
3015 item_name
= str(items
.get("name"))
3018 if item
=="networks":
3019 content
= myvim
.delete_network(item_id
)
3020 elif item
=="tenants":
3021 content
= myvim
.delete_tenant(item_id
)
3022 elif item
== "images":
3023 content
= myvim
.delete_image(item_id
)
3025 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3026 except vimconn
.vimconnException
as e
:
3027 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
3028 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
3030 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
3033 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
3034 #get datacenter info
3035 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
3036 if tenant_id
== "any":
3038 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3040 if item
=="networks":
3041 net
= descriptor
["network"]
3042 net_name
= net
.pop("name")
3043 net_type
= net
.pop("type", "bridge")
3044 net_public
= net
.pop("shared", False)
3045 net_ipprofile
= net
.pop("ip_profile", None)
3046 net_vlan
= net
.pop("vlan", None)
3047 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
3048 elif item
=="tenants":
3049 tenant
= descriptor
["tenant"]
3050 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
3052 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3053 except vimconn
.vimconnException
as e
:
3054 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
3056 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)