openmano v0.4.39: logging at vimconnector. Exception generation upon error instead...
[osm/RO.git] / nfvo.py
1 # -*- coding: utf-8 -*-
2
3 ##
4 # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
5 # This file is part of openmano
6 # All Rights Reserved.
7 #
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
11 #
12 # http://www.apache.org/licenses/LICENSE-2.0
13 #
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
18 # under the License.
19 #
20 # For those usages not covered by the Apache License, Version 2.0 please
21 # contact with: nfvlabs@tid.es
22 ##
23
24 '''
25 NFVO engine, implementing all the methods for the creation, deletion and management of vnfs, scenarios and instances
26 '''
27 __author__="Alfonso Tierno, Gerardo Garcia, Pablo Montes"
28 __date__ ="$16-sep-2014 22:05:01$"
29
30 import imp
31 #import json
32 import yaml
33 import utils
34 from nfvo_db import HTTP_Unauthorized, HTTP_Bad_Request, HTTP_Internal_Server_Error, HTTP_Not_Found,\
35 HTTP_Conflict, HTTP_Method_Not_Allowed
36 import console_proxy_thread as cli
37 import vimconn
38 import logging
39
40 global global_config
41 global vimconn_imported
42
43
44 vimconn_imported={} #dictionary with VIM type as key, loaded module as value
45 logger = logging.getLogger('mano.nfvo')
46
47 class NfvoException(Exception):
48 def __init__(self, message, http_code):
49 self.http_code = http_code
50 Exception.__init__(self, message)
51
52
53 def get_flavorlist(mydb, vnf_id, nfvo_tenant=None):
54 '''Obtain flavorList
55 return result, content:
56 <0, error_text upon error
57 nb_records, flavor_list on success
58 '''
59 WHERE_dict={}
60 WHERE_dict['vnf_id'] = vnf_id
61 if nfvo_tenant is not None:
62 WHERE_dict['nfvo_tenant_id'] = nfvo_tenant
63
64 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
65 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
66 result, content = mydb.get_table(FROM='vms join flavors on vms.flavor_id=flavors.uuid',SELECT=('flavor_id',),WHERE=WHERE_dict )
67 if result < 0:
68 print "nfvo.get_flavorlist error %d %s" % (result, content)
69 return -result, content
70 print "get_flavor_list result:", result
71 print "get_flavor_list content:", content
72 flavorList=[]
73 for flavor in content:
74 flavorList.append(flavor['flavor_id'])
75 return result, flavorList
76
77 def get_imagelist(mydb, vnf_id, nfvo_tenant=None):
78 '''Obtain imageList
79 return result, content:
80 <0, error_text upon error
81 nb_records, flavor_list on success
82 '''
83 WHERE_dict={}
84 WHERE_dict['vnf_id'] = vnf_id
85 if nfvo_tenant is not None:
86 WHERE_dict['nfvo_tenant_id'] = nfvo_tenant
87
88 #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
89 result, content = mydb.get_table(FROM='vms join images on vms.image_id=images.uuid',SELECT=('image_id',),WHERE=WHERE_dict )
90 if result < 0:
91 print "nfvo.get_imagelist error %d %s" % (result, content)
92 return -result, content
93 print "get_image_list result:", result
94 print "get_image_list content:", content
95 imageList=[]
96 for image in content:
97 imageList.append(image['image_id'])
98 return result, imageList
99
100 def get_vim(mydb, nfvo_tenant=None, datacenter_id=None, datacenter_name=None, vim_tenant=None):
101 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
102 return result, content:
103 <0, error_text upon error
104 NUMBER, dictionary with datacenter_id: vim_class with these keys:
105 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
106 '''
107 WHERE_dict={}
108 if nfvo_tenant is not None: WHERE_dict['nfvo_tenant_id'] = nfvo_tenant
109 if datacenter_id is not None: WHERE_dict['d.uuid'] = datacenter_id
110 if datacenter_name is not None: WHERE_dict['d.name'] = datacenter_name
111 if vim_tenant is not None: WHERE_dict['dt.vim_tenant_id'] = vim_tenant
112 if nfvo_tenant or vim_tenant:
113 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'
114 select_ = ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
115 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
116 'user','passwd')
117 else:
118 from_ = 'datacenters as d'
119 select_ = ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
120 result, content = mydb.get_table(FROM=from_, SELECT=select_, WHERE=WHERE_dict )
121 if result < 0:
122 print "nfvo.get_vim error %d %s" % (result, content)
123 return result, content
124 #elif result==0:
125 # print "nfvo.get_vim not found a valid VIM with the input params " + str(WHERE_dict)
126 # return -HTTP_Not_Found, "datacenter not found for " + str(WHERE_dict)
127 #print content
128 vim_dict={}
129 for vim in content:
130 extra={'datacenter_tenant_id': vim.get('datacenter_tenant_id')}
131 if vim["config"] != None:
132 extra.update(yaml.load(vim["config"]))
133 if vim["type"] not in vimconn_imported:
134 module_info=None
135 try:
136 module = "vimconn_" + vim["type"]
137 module_info = imp.find_module(module)
138 vim_conn = imp.load_module(vim["type"], *module_info)
139 vimconn_imported[vim["type"]] = vim_conn
140 except (IOError, ImportError) as e:
141 if module_info and module_info[0]:
142 file.close(module_info[0])
143 print "Cannot open VIM module '%s.py'; %s: %s" % ( module, type(e).__name__, str(e))
144 return -HTTP_Bad_Request, "Unknown vim type %s" % vim["type"]
145
146 try:
147 #if not tenant:
148 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
149 vim_dict[ vim['datacenter_id'] ] = vimconn_imported[ vim["type"] ].vimconnector(
150 uuid=vim['datacenter_id'], name=vim['datacenter_name'],
151 tenant_id=vim.get('vim_tenant_id'), tenant_name=vim.get('vim_tenant_name'),
152 url=vim['vim_url'], url_admin=vim['vim_url_admin'],
153 user=vim.get('user'), passwd=vim.get('passwd'),
154 config=extra
155 )
156 except Exception as e:
157 return -HTTP_Internal_Server_Error, "Error at VIM %s; %s: %s" % ( vim["type"], type(e).__name__, str(e))
158 return len(vim_dict), vim_dict
159
160 def rollback(mydb, vims, rollback_list):
161 undeleted_items=[]
162 #delete things by reverse order
163 for i in range(len(rollback_list)-1, -1, -1):
164 item = rollback_list[i]
165 if item["where"]=="vim":
166 if item["vim_id"] not in vims:
167 continue
168 vim=vims[ item["vim_id"] ]
169 try:
170 if item["what"]=="image":
171 vim.delete_image(item["uuid"])
172 result, message = mydb.delete_row_by_dict(FROM="datacenters_images", WEHRE={"datacenter_id": vim["id"], "vim_id":item["uuid"]})
173 if result < 0:
174 logger.error("Error in rollback. Not possible to delete image '%s' from DB.dacenters_images. Message: %s", item["uuid"],message)
175 elif item["what"]=="flavor":
176 vim.delete_flavor(item["uuid"])
177 result, message = mydb.delete_row_by_dict(FROM="datacenters_flavos", WEHRE={"datacenter_id": vim["id"], "vim_id":item["uuid"]})
178 if result < 0:
179 logger.error("Error in rollback. Not possible to delete flavor '%s' from DB.dacenters_flavors. Message: %s", item["uuid"],message)
180 elif item["what"]=="network":
181 vim.delete_network(item["uuid"])
182 elif item["what"]=="vm":
183 vim.delete_vminstance(item["uuid"])
184 except vimconn.vimconnException as e:
185 logger.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item['what'], item["uuid"], str(e))
186 undeleted_items.append("{} {} from VIM {}".format(item['what'], item["uuid"], vim["name"]))
187
188 else: # where==mano
189 if item["what"]=="image":
190 result, message = mydb.delete_row_by_dict(FROM="images", WEHRE={"uuid": item["uuid"]})
191 if result < 0:
192 logger.error("Error in rollback. Not possible to delete image '%s' from DB.images. Message: %s", item["uuid"], message)
193 undeleted_items.append("image %s" % (item["uuid"]))
194 elif item["what"]=="flavor":
195 result, message = mydb.delete_row_by_dict(FROM="flavors", WEHRE={"uuid": item["uuid"]})
196 if result < 0:
197 logger.error("Error in rollback. Not possible to delete flavor '%s' from DB.flavors. Message: %s", item["uuid"], message)
198 undeleted_items.append("flavor %s" % (item["uuid"]))
199 if len(undeleted_items)==0:
200 return True," Rollback successful."
201 else:
202 return False," Rollback fails to delete: " + str(undeleted_items)
203
204 def check_vnf_descriptor(vnf_descriptor):
205 global global_config
206 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
207 vnfc_interfaces={}
208 for vnfc in vnf_descriptor["vnf"]["VNFC"]:
209 name_list = []
210 #dataplane interfaces
211 for numa in vnfc.get("numas",() ):
212 for interface in numa.get("interfaces",()):
213 if interface["name"] in name_list:
214 return -HTTP_Bad_Request, "Error at vnf:VNFC[name:'%s']:numas:interfaces:name, interface name '%s' already used in this VNFC" %(vnfc["name"], interface["name"])
215 name_list.append( interface["name"] )
216 #bridge interfaces
217 for interface in vnfc.get("bridge-ifaces",() ):
218 if interface["name"] in name_list:
219 return -HTTP_Bad_Request, "Error at vnf:VNFC[name:'%s']:bridge-ifaces:name, interface name '%s' already used in this VNFC" %(vnfc["name"], interface["name"])
220 name_list.append( interface["name"] )
221 vnfc_interfaces[ vnfc["name"] ] = name_list
222
223 #check if the info in external_connections matches with the one in the vnfcs
224 name_list=[]
225 for external_connection in vnf_descriptor["vnf"].get("external-connections",() ):
226 if external_connection["name"] in name_list:
227 return -HTTP_Bad_Request, "Error at vnf:external-connections:name, value '%s' already used as an external-connection" %(external_connection["name"])
228 name_list.append(external_connection["name"])
229 if external_connection["VNFC"] not in vnfc_interfaces:
230 return -HTTP_Bad_Request, "Error at vnf:external-connections[name:'%s']:VNFC, value '%s' does not match any VNFC" %(external_connection["name"], external_connection["VNFC"])
231 if external_connection["local_iface_name"] not in vnfc_interfaces[ external_connection["VNFC"] ]:
232 return -HTTP_Bad_Request, "Error at vnf:external-connections[name:'%s']:local_iface_name, value '%s' does not match any interface of this VNFC" %(external_connection["name"], external_connection["local_iface_name"])
233
234 #check if the info in internal_connections matches with the one in the vnfcs
235 name_list=[]
236 for internal_connection in vnf_descriptor["vnf"].get("internal-connections",() ):
237 if internal_connection["name"] in name_list:
238 return -HTTP_Bad_Request, "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection" %(internal_connection["name"])
239 name_list.append(internal_connection["name"])
240 #We should check that internal-connections of type "ptp" have only 2 elements
241 if len(internal_connection["elements"])>2 and internal_connection["type"] == "ptp":
242 return -HTTP_Bad_Request, "Error at vnf:internal-connections[name:'%s']:elements, size must be 2 for a type:'ptp'" %(internal_connection["name"])
243 for port in internal_connection["elements"]:
244 if port["VNFC"] not in vnfc_interfaces:
245 return -HTTP_Bad_Request, "Error at vnf:internal-connections[name:'%s']:elements[]:VNFC, value '%s' does not match any VNFC" %(internal_connection["name"], port["VNFC"])
246 if port["local_iface_name"] not in vnfc_interfaces[ port["VNFC"] ]:
247 return -HTTP_Bad_Request, "Error at vnf:internal-connections[name:'%s']:elements[]:local_iface_name, value '%s' does not match any interface of this VNFC" %(internal_connection["name"], port["local_iface_name"])
248
249
250 return 200, None
251
252 def create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vim=False, return_on_error = False):
253 #look if image exist
254 if only_create_at_vim:
255 image_mano_id = image_dict['uuid']
256 else:
257 res,content = mydb.get_table(FROM="images", WHERE={'location':image_dict['location'], 'metadata':image_dict['metadata']})
258 if res>=1:
259 image_mano_id = content[0]['uuid']
260 elif res<0:
261 return res, content
262 else:
263 #create image
264 temp_image_dict={'name':image_dict['name'], 'description':image_dict.get('description',None),
265 'location':image_dict['location'], 'metadata':image_dict.get('metadata',None)
266 }
267 res,content = mydb.new_row('images', temp_image_dict, tenant_id=None, add_uuid=True)
268 if res>0:
269 image_mano_id= content
270 rollback_list.append({"where":"mano", "what":"image","uuid":image_mano_id})
271 else:
272 return res if res<0 else -1, content
273 #create image at every vim
274 for vim_id,vim in vims.iteritems():
275 image_created="false"
276 #look at database
277 res_db,image_db = mydb.get_table(FROM="datacenters_images", WHERE={'datacenter_id':vim_id, 'image_id':image_mano_id})
278 if res_db<0:
279 return res_db, image_db
280 #look at VIM if this image exist
281 try:
282 image_vim_id = vim.get_image_id_from_path(image_dict['location'])
283 except vimconn.vimconnNotFoundException as e:
284 #Create the image in VIM
285 try:
286 image_vim_id = vim.new_image(image_dict)
287 rollback_list.append({"where":"vim", "vim_id": vim_id, "what":"image","uuid":image_vim_id})
288 image_created="true"
289 except vimconn.vimconnException as e:
290 if return_on_error:
291 logger.error("Error creating image at VIM: %s", str(e))
292 return -e.http_code, str(e)
293 image_vim_id = str(e)
294 logger.warn("Error creating image at VIM: %s", str(e))
295 continue
296 except vimconn.vimconnException as e:
297 logger.warn("Error contacting VIM to know if the image exist at VIM: %s", str(e))
298 image_vim_id = str(e)
299 continue
300 #if reach here the image has been create or exist
301 if res_db==0:
302 #add new vim_id at datacenters_images
303 mydb.new_row('datacenters_images', {'datacenter_id':vim_id, 'image_id':image_mano_id, 'vim_id': image_vim_id, 'created':image_created})
304 elif image_db[0]["vim_id"]!=image_vim_id:
305 #modify existing vim_id at datacenters_images
306 mydb.update_rows('datacenters_images', UPDATE={'vim_id':image_vim_id}, WHERE={'datacenter_id':vim_id, 'image_id':image_mano_id})
307
308 return 1, image_vim_id if only_create_at_vim else image_mano_id
309
310 def create_or_use_flavor(mydb, vims, flavor_dict, rollback_list, only_create_at_vim=False, return_on_error = False):
311 temp_flavor_dict= {'disk':flavor_dict.get('disk',1),
312 'ram':flavor_dict.get('ram'),
313 'vcpus':flavor_dict.get('vcpus'),
314 }
315 if 'extended' in flavor_dict and flavor_dict['extended']==None:
316 del flavor_dict['extended']
317 if 'extended' in flavor_dict:
318 temp_flavor_dict['extended']=yaml.safe_dump(flavor_dict['extended'],default_flow_style=True,width=256)
319
320 #look if flavor exist
321 if only_create_at_vim:
322 flavor_mano_id = flavor_dict['uuid']
323 else:
324 res,content = mydb.get_table(FROM="flavors", WHERE=temp_flavor_dict)
325 if res>=1:
326 flavor_mano_id = content[0]['uuid']
327 elif res<0:
328 return res, content
329 else:
330 #create flavor
331 #create one by one the images of aditional disks
332 dev_image_list=[] #list of images
333 if 'extended' in flavor_dict and flavor_dict['extended']!=None:
334 dev_nb=0
335 for device in flavor_dict['extended'].get('devices',[]):
336 if "image" not in device:
337 continue
338 image_dict={'location':device['image'], 'name':flavor_dict['name']+str(dev_nb)+"-img", 'description':flavor_dict.get('description')}
339 image_metadata_dict = device.get('image metadata', None)
340 image_metadata_str = None
341 if image_metadata_dict != None:
342 image_metadata_str = yaml.safe_dump(image_metadata_dict,default_flow_style=True,width=256)
343 image_dict['metadata']=image_metadata_str
344 res, image_id = create_or_use_image(mydb, vims, image_dict, rollback_list)
345 if res < 0:
346 return res, image_id + rollback(mydb, vims, rollback_list)[1]
347 print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
348 dev_image_list.append(image_id)
349 dev_nb += 1
350 temp_flavor_dict['name'] = flavor_dict['name']
351 temp_flavor_dict['description'] = flavor_dict.get('description',None)
352 res,content = mydb.new_row('flavors', temp_flavor_dict, tenant_id=None, add_uuid=True)
353 if res>0:
354 flavor_mano_id= content
355 rollback_list.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id})
356 else:
357 return res if res<0 else -1, content
358 #create flavor at every vim
359 if 'uuid' in flavor_dict:
360 del flavor_dict['uuid']
361 flavor_vim_id=None
362 for vim_id,vim in vims.items():
363 flavor_created="false"
364 #look at database
365 res_db,flavor_db = mydb.get_table(FROM="datacenters_flavors", WHERE={'datacenter_id':vim_id, 'flavor_id':flavor_mano_id})
366 if res_db<0:
367 return res_db, flavor_db
368 #look at VIM if this flavor exist SKIPPED
369 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
370 #if res_vim < 0:
371 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
372 # continue
373 #elif res_vim==0:
374
375 #Create the flavor in VIM
376 #Translate images at devices from MANO id to VIM id
377 error=False
378 if 'extended' in flavor_dict and flavor_dict['extended']!=None and "devices" in flavor_dict['extended']:
379 #make a copy of original devices
380 devices_original=[]
381 for device in flavor_dict["extended"].get("devices",[]):
382 dev={}
383 dev.update(device)
384 devices_original.append(dev)
385 if 'image' in device:
386 del device['image']
387 if 'image metadata' in device:
388 del device['image metadata']
389 dev_nb=0
390 for index in range(0,len(devices_original)) :
391 device=devices_original[index]
392 if "image" not in device:
393 continue
394 image_dict={'location':device['image'], 'name':flavor_dict['name']+str(dev_nb)+"-img", 'description':flavor_dict.get('description')}
395 image_metadata_dict = device.get('image metadata', None)
396 image_metadata_str = None
397 if image_metadata_dict != None:
398 image_metadata_str = yaml.safe_dump(image_metadata_dict,default_flow_style=True,width=256)
399 image_dict['metadata']=image_metadata_str
400 r,image_mano_id=create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vim=False)
401 if r<0:
402 print "Error creating device image for flavor: %s." %image_mano_id
403 error_text = image_mano_id
404 error=True
405 break
406 image_dict["uuid"]=image_mano_id
407 r,image_vim_id=create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vim=True)
408 if r<0:
409 print "Error creating device image for flavor at VIM: %s." %image_vim_id
410 error_text = image_vim_id
411 error=True
412 break
413 flavor_dict["extended"]["devices"][index]['imageRef']=image_vim_id
414 dev_nb += 1
415 if error:
416 if return_on_error:
417 return r, error_text
418 continue
419 if res_db>0:
420 #check that this vim_id exist in VIM, if not create
421 flavor_vim_id=flavor_db[0]["vim_id"]
422 try:
423 vim.get_flavor(flavor_vim_id)
424 continue #flavor exist
425 except vimconn.vimconnException:
426 pass
427 #create flavor at vim
428 logger.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim["name"])
429 try:
430 flavor_vim_id = vim.new_flavor(flavor_dict)
431 rollback_list.append({"where":"vim", "vim_id": vim_id, "what":"flavor","uuid":flavor_vim_id})
432 flavor_created="true"
433 except vimconn.vimconnException as e:
434 if return_on_error:
435 logger.error("Error creating flavor at VIM %s: %s.", vim["name"], str(e))
436 return -e.http_code, str(e)
437 logger.warn("Error creating flavor at VIM %s: %s.", vim["name"], str(e))
438 continue
439 #if reach here the flavor has been create or exist
440 if res_db==0:
441 #add new vim_id at datacenters_flavors
442 mydb.new_row('datacenters_flavors', {'datacenter_id':vim_id, 'flavor_id':flavor_mano_id, 'vim_id': flavor_vim_id, 'created':flavor_created})
443 elif flavor_db[0]["vim_id"]!=flavor_vim_id:
444 #modify existing vim_id at datacenters_flavors
445 mydb.update_rows('datacenters_flavors', UPDATE={'vim_id':flavor_vim_id}, WHERE={'datacenter_id':vim_id, 'flavor_id':flavor_mano_id})
446
447 return 1, flavor_vim_id if only_create_at_vim else flavor_mano_id
448
449 def new_vnf(mydb, tenant_id, vnf_descriptor):
450 global global_config
451
452 # Step 1. Check the VNF descriptor
453 result, message = check_vnf_descriptor(vnf_descriptor)
454 if result < 0:
455 print "new_vnf error: %s" %message
456 return result, message
457
458 # Step 2. Check tenant exist
459 if tenant_id != "any":
460 if not check_tenant(mydb, tenant_id):
461 print 'nfvo.new_vnf() tenant %s not found' % tenant_id
462 return -HTTP_Not_Found, 'Tenant %s not found' % tenant_id
463 if "tenant_id" in vnf_descriptor["vnf"]:
464 if vnf_descriptor["vnf"]["tenant_id"] != tenant_id:
465 print "nfvo.new_vnf() tenant '%s' not found" % tenant_id
466 return -HTTP_Unauthorized, "VNF can not have a different tenant owner '%s', must be '%s'" %(vnf_descriptor["vnf"]["tenant_id"], tenant_id)
467 else:
468 vnf_descriptor['vnf']['tenant_id'] = tenant_id
469 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
470 result, vims = get_vim(mydb, tenant_id)
471 if result < 0:
472 print "nfvo.new_vnf() error. Datacenter not found"
473 return result, vims
474 else:
475 vims={}
476
477 # Step 4. Review the descriptor and add missing fields
478 #print vnf_descriptor
479 print "Refactoring VNF descriptor with fields: description, public (default: true)"
480 vnf_name = vnf_descriptor['vnf']['name']
481 vnf_descriptor['vnf']['description'] = vnf_descriptor['vnf'].get("description", vnf_name)
482 if "physical" in vnf_descriptor['vnf']:
483 del vnf_descriptor['vnf']['physical']
484 #print vnf_descriptor
485 # Step 5. Check internal connections
486 # TODO: to be moved to step 1????
487 internal_connections=vnf_descriptor['vnf'].get('internal_connections',[])
488 for ic in internal_connections:
489 if len(ic['elements'])>2 and ic['type']=='ptp':
490 return -HTTP_Bad_Request, "Mismatch 'type':'ptp' with %d elements at 'vnf':'internal-conections'['name':'%s']. Change 'type' to 'data'" %(len(ic), ic['name'])
491 elif len(ic['elements'])==2 and ic['type']=='data':
492 return -HTTP_Bad_Request, "Mismatch 'type':'data' with 2 elements at 'vnf':'internal-conections'['name':'%s']. Change 'type' to 'ptp'" %(ic['name'])
493
494 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
495 print 'BEGIN creation of VNF "%s"' % vnf_name
496 print "VNF %s: consisting of %d VNFC(s)" % (vnf_name,len(vnf_descriptor['vnf']['VNFC']))
497
498 #For each VNFC, we add it to the VNFCDict and we create a flavor.
499 VNFCDict = {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
500 rollback_list = [] # It will contain the new images created in mano. It is used for rollback
501
502 try:
503 print "Creating additional disk images and new flavors in the VIM for each VNFC"
504 for vnfc in vnf_descriptor['vnf']['VNFC']:
505 VNFCitem={}
506 VNFCitem["name"] = vnfc['name']
507 VNFCitem["description"] = vnfc.get("description", 'VM %s of the VNF %s' %(vnfc['name'],vnf_name))
508
509 print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
510
511 myflavorDict = {}
512 myflavorDict["name"] = vnfc['name']+"-flv"
513 myflavorDict["description"] = VNFCitem["description"]
514 myflavorDict["ram"] = vnfc.get("ram", 0)
515 myflavorDict["vcpus"] = vnfc.get("vcpus", 0)
516 myflavorDict["disk"] = vnfc.get("disk", 1)
517 myflavorDict["extended"] = {}
518
519 devices = vnfc.get("devices")
520 if devices != None:
521 myflavorDict["extended"]["devices"] = devices
522
523 # TODO:
524 # 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
525 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
526
527 # Previous code has been commented
528 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
529 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
530 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
531 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
532 #else:
533 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
534 # if result2:
535 # print "Error creating flavor: unknown processor model. Rollback successful."
536 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
537 # else:
538 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
539 myflavorDict['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
540
541 if 'numas' in vnfc and len(vnfc['numas'])>0:
542 myflavorDict['extended']['numas'] = vnfc['numas']
543
544 #print myflavorDict
545
546 # Step 6.2 New flavors are created in the VIM
547 res, flavor_id = create_or_use_flavor(mydb, vims, myflavorDict, rollback_list)
548 if res < 0:
549 return res, flavor_id + rollback(mydb, vims, rollback_list)[1]
550
551 print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
552 VNFCitem["flavor_id"] = flavor_id
553 VNFCDict[vnfc['name']] = VNFCitem
554
555 print "Creating new images in the VIM for each VNFC"
556 # Step 6.3 New images are created in the VIM
557 #For each VNFC, we must create the appropriate image.
558 #This "for" loop might be integrated with the previous one
559 #In case this integration is made, the VNFCDict might become a VNFClist.
560 for vnfc in vnf_descriptor['vnf']['VNFC']:
561 print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
562 image_dict={'location':vnfc['VNFC image'], 'name':vnfc['name']+"-img", 'description':VNFCDict[vnfc['name']]['description']}
563 image_metadata_dict = vnfc.get('image metadata', None)
564 image_metadata_str = None
565 if image_metadata_dict is not None:
566 image_metadata_str = yaml.safe_dump(image_metadata_dict,default_flow_style=True,width=256)
567 image_dict['metadata']=image_metadata_str
568 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
569 res, image_id = create_or_use_image(mydb, vims, image_dict, rollback_list)
570 if res < 0:
571 return res, image_id + rollback(mydb, vims, rollback_list)[1]
572 print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
573 VNFCDict[vnfc['name']]["image_id"] = image_id
574 VNFCDict[vnfc['name']]["image_path"] = vnfc['VNFC image']
575
576 except KeyError as e:
577 print "Error while creating a VNF. KeyError: " + str(e)
578 _, message = rollback(mydb, vims, rollback_list)
579 return -HTTP_Internal_Server_Error, "Error while creating a VNF. KeyError " + str(e) + "." + message
580
581 # Step 7. Storing the VNF descriptor in the repository
582 if "descriptor" not in vnf_descriptor["vnf"]:
583 vnf_descriptor["vnf"]["descriptor"] = yaml.safe_dump(vnf_descriptor, indent=4, explicit_start=True, default_flow_style=False)
584
585 # Step 8. Adding the VNF to the NFVO DB
586 try:
587 result, vnf_id = mydb.new_vnf_as_a_whole(tenant_id,vnf_name,vnf_descriptor,VNFCDict)
588 except KeyError as e:
589 print "Error while creating a VNF. KeyError: " + str(e)
590 _, message = rollback(mydb, vims, rollback_list)
591 return -HTTP_Internal_Server_Error, "Error while creating a VNF. KeyError " + str(e) + "." + message
592
593 if result < 0:
594 _, message = rollback(mydb, vims, rollback_list)
595 return result, vnf_id + "." + message
596
597 return 200,vnf_id
598
599 def get_vnf_id(mydb, tenant_id, vnf_id):
600 #check valid tenant_id
601 if tenant_id != "any" and not check_tenant(mydb, tenant_id):
602 print 'nfvo.get_vnf_id() tenant %s not found' % tenant_id
603 return -HTTP_Not_Found, "Tenant '%s' not found" % tenant_id
604 #obtain data
605 where_or = {}
606 if tenant_id != "any":
607 where_or["tenant_id"] = tenant_id
608 where_or["public"] = True
609 result, content = mydb.get_table_by_uuid_name('vnfs', vnf_id, "VNF", WHERE_OR=where_or, WHERE_AND_OR="AND")
610 if result < 0:
611 print "nfvo.get_vnf_id() error %d %s" % (result, content)
612 return (result, content)
613
614
615 vnf_id=content["uuid"]
616 filter_keys = ('uuid','name','description','public', "tenant_id", "created_at")
617 filtered_content = dict( (k,v) for k,v in content.iteritems() if k in filter_keys )
618 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
619 data={'vnf' : filtered_content}
620 #GET VM
621 result,content = mydb.get_table(FROM='vnfs join vms on vnfs.uuid=vms.vnf_id',
622 SELECT=('vms.uuid as uuid','vms.name as name', 'vms.description as description'),
623 WHERE={'vnfs.uuid': vnf_id} )
624 if result < 0:
625 print "nfvo.get_vnf_id error %d %s" % (result, content)
626 return (result, content)
627 elif result==0:
628 print "nfvo.get_vnf_id vnf '%s' not found" % vnf_id
629 return (-HTTP_Not_Found, "vnf %s not found" % vnf_id)
630
631 data['vnf']['VNFC'] = content
632 #GET NET
633 result,content = mydb.get_table(FROM='vnfs join nets on vnfs.uuid=nets.vnf_id',
634 SELECT=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
635 WHERE={'vnfs.uuid': vnf_id} )
636 if result < 0:
637 print "nfvo.get_vnf_id error %d %s" % (result, content)
638 return (result, content)
639 else:
640 if result==0:
641 data['vnf']['nets'] = []
642 else:
643 data['vnf']['nets'] = content
644 #GET Interfaces
645 result,content = mydb.get_table(FROM='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
646 SELECT=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
647 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
648 WHERE={'vnfs.uuid': vnf_id},
649 WHERE_NOT={'interfaces.external_name': None} )
650 #print content
651 if result < 0:
652 print "nfvo.get_vnf_id error %d %s" % (result, content)
653 return (result, content)
654 else:
655 if result==0:
656 data['vnf']['external-connections'] = []
657 else:
658 data['vnf']['external-connections'] = content
659 return 0, data
660
661
662 def delete_vnf(mydb,tenant_id,vnf_id,datacenter=None,vim_tenant=None):
663 # Check tenant exist
664 if tenant_id != "any":
665 if not check_tenant(mydb, tenant_id):
666 print 'nfvo.delete_vnf() tenant %s not found' % tenant_id
667 return -HTTP_Not_Found, 'Tenant %s not found' % tenant_id
668 # Get the URL of the VIM from the nfvo_tenant and the datacenter
669 result, vims = get_vim(mydb, tenant_id)
670 if result < 0:
671 print "nfvo.delete_vnf() error. Datacenter not found"
672 return result, vims
673 else:
674 vims={}
675
676 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
677 where_or = {}
678 if tenant_id != "any":
679 where_or["tenant_id"] = tenant_id
680 where_or["public"] = True
681 result, content = mydb.get_table_by_uuid_name('vnfs', vnf_id, "VNF", WHERE_OR=where_or, WHERE_AND_OR="AND")
682 if result < 0:
683 return result, content
684 vnf_id = content["uuid"]
685
686 # "Getting the list of flavors and tenants of the VNF"
687 result,flavorList = get_flavorlist(mydb, vnf_id)
688 if result < 0:
689 print flavorList
690 elif result==0:
691 print "delete_vnf error. No flavors found for the VNF id '%s'" % vnf_id
692
693 result,imageList = get_imagelist(mydb, vnf_id)
694 print "imageList", imageList
695 if result < 0:
696 print imageList
697 elif result==0:
698 print "delete_vnf error. No images found for the VNF id '%s'" % vnf_id
699
700 result, content = mydb.delete_row('vnfs', vnf_id, tenant_id)
701 if result == 0:
702 return -HTTP_Not_Found, content
703 elif result >0:
704 print content
705 else:
706 print "delete_vnf error",result, content
707 return result, content
708
709 undeletedItems = []
710 for flavor in flavorList:
711 #check if flavor is used by other vnf
712 r,c = mydb.get_table(FROM='vms', WHERE={'flavor_id':flavor} )
713 if r < 0:
714 print 'delete_vnf_error. Not possible to delete VIM flavor "%s". %s' % (flavor,c)
715 undeletedItems.append("flavor "+ flavor["flavor_id"])
716 elif r > 0:
717 print 'Flavor %s not deleted because it is being used by another VNF %s' %(flavor,str(c))
718 continue
719 #flavor not used, must be deleted
720 #delelte at VIM
721 r,c = mydb.get_table(FROM='datacenters_flavors', WHERE={'flavor_id':flavor})
722 if r>0:
723 for flavor_vim in c:
724 if flavor_vim["datacenter_id"] not in vims:
725 continue
726 if flavor_vim['created']=='false': #skip this flavor because not created by openmano
727 continue
728 myvim=vims[ flavor_vim["datacenter_id"] ]
729 try:
730 myvim.delete_flavor(flavor_vim["vim_id"])
731 except vimconn.vimconnNotFoundException as e:
732 logger.warn("VIM flavor %s not exist at datacenter %s", flavor_vim["vim_id"], flavor_vim["datacenter_id"] )
733 except vimconn.vimconnException as e:
734 logger.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
735 flavor_vim["vim_id"], flavor_vim["datacenter_id"], type(e).__name__, str(e))
736 undeletedItems.append("flavor {} from VIM {}".format(flavor_vim["vim_id"], flavor_vim["datacenter_id"] ))
737 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
738 result, content = mydb.delete_row('flavors', flavor)
739 if result <0:
740 undeletedItems.append("flavor %s" % flavor)
741
742 for image in imageList:
743 #check if image is used by other vnf
744 r,c = mydb.get_table(FROM='vms', WHERE={'image_id':image} )
745 if r < 0:
746 print 'delete_vnf_error. Not possible to delete VIM image "%s". %s' % (image,c)
747 undeletedItems.append("image "+ image["image_id"])
748 elif r > 0:
749 print 'Image %s not deleted because it is being used by another VNF %s' %(image,str(c))
750 continue
751 #image not used, must be deleted
752 #delelte at VIM
753 r,c = mydb.get_table(FROM='datacenters_images', WHERE={'image_id':image})
754 if r>0:
755 for image_vim in c:
756 if image_vim["datacenter_id"] not in vims:
757 continue
758 if image_vim['created']=='false': #skip this image because not created by openmano
759 continue
760 myvim=vims[ image_vim["datacenter_id"] ]
761 try:
762 myvim.delete_image(image_vim["vim_id"])
763 except vimconn.vimconnNotFoundException as e:
764 logger.warn("VIM image %s not exist at datacenter %s", image_vim["vim_id"], image_vim["datacenter_id"] )
765 except vimconn.vimconnException as e:
766 logger.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
767 image_vim["vim_id"], image_vim["datacenter_id"], type(e).__name__, str(e))
768 undeletedItems.append("image {} from VIM {}".format(image_vim["vim_id"], image_vim["datacenter_id"] ))
769 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
770 result, content = mydb.delete_row('images', image)
771 if result <0:
772 undeletedItems.append("image %s" % image)
773
774 if undeletedItems:
775 return 200, "delete_vnf error. Undeleted: %s" %(undeletedItems)
776
777 return 200,vnf_id
778
779 def get_hosts_info(mydb, nfvo_tenant_id, datacenter_name=None):
780 result, vims = get_vim(mydb, nfvo_tenant_id, None, datacenter_name)
781 if result < 0:
782 return result, vims
783 elif result == 0:
784 return -HTTP_Not_Found, "datacenter '%s' not found" % datacenter_name
785 myvim = vims.values()[0]
786 result,servers = myvim.get_hosts_info()
787 if result < 0:
788 return result, servers
789 topology = {'name':myvim['name'] , 'servers': servers}
790 return result, topology
791
792 def get_hosts(mydb, nfvo_tenant_id):
793 result, vims = get_vim(mydb, nfvo_tenant_id)
794 if result < 0:
795 return result, vims
796 elif result == 0:
797 return -HTTP_Not_Found, "No datacenter found"
798 myvim = vims.values()[0]
799 result,hosts = myvim.get_hosts()
800 if result < 0:
801 return result, hosts
802 print '==================='
803 print 'hosts '+ yaml.safe_dump(hosts, indent=4, default_flow_style=False)
804
805 datacenter = {'Datacenters': [ {'name':myvim['name'],'servers':[]} ] }
806 for host in hosts:
807 server={'name':host['name'], 'vms':[]}
808 for vm in host['instances']:
809 #get internal name and model
810 r,c = mydb.get_table(SELECT=('name',), FROM='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
811 WHERE={'vim_vm_id':vm['id']} )
812 if r==0:
813 print "nfvo.get_hosts virtual machine at VIM (%s) not found at tidnfvo" % vm['id']
814 continue
815 if r<0:
816 print "nfvo.get_hosts virtual machine at VIM (%s) error %d %s" % (vm['id'], r, c)
817 continue
818 server['vms'].append( {'name':vm['name'] , 'model':c[0]['name']} )
819 datacenter['Datacenters'][0]['servers'].append(server)
820 #return -400, "en construccion"
821
822 #print 'datacenters '+ json.dumps(datacenter, indent=4)
823 return result, datacenter
824
825 def new_scenario(mydb, tenant_id, topo):
826
827 # result, vims = get_vim(mydb, tenant_id)
828 # if result < 0:
829 # return result, vims
830 #1: parse input
831 if tenant_id != "any":
832 if not check_tenant(mydb, tenant_id):
833 print 'nfvo.new_scenario() tenant %s not found' % tenant_id
834 return -HTTP_Not_Found, 'Tenant %s not found' % tenant_id
835 if "tenant_id" in topo:
836 if topo["tenant_id"] != tenant_id:
837 print "nfvo.new_scenario() tenant '%s' not found" % tenant_id
838 return -HTTP_Unauthorized, "VNF can not have a different tenant owner '%s', must be '%s'" %(topo["tenant_id"], tenant_id)
839 else:
840 tenant_id=None
841
842 #1.1: get VNFs and external_networks (other_nets).
843 vnfs={}
844 other_nets={} #external_networks, bridge_networks and data_networkds
845 nodes = topo['topology']['nodes']
846 for k in nodes.keys():
847 if nodes[k]['type'] == 'VNF':
848 vnfs[k] = nodes[k]
849 vnfs[k]['ifaces'] = {}
850 elif nodes[k]['type'] == 'other_network' or nodes[k]['type'] == 'external_network':
851 other_nets[k] = nodes[k]
852 other_nets[k]['external']=True
853 elif nodes[k]['type'] == 'network':
854 other_nets[k] = nodes[k]
855 other_nets[k]['external']=False
856
857
858 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
859 for name,vnf in vnfs.items():
860 WHERE_={}
861 error_text = ""
862 error_pos = "'topology':'nodes':'" + name + "'"
863 if 'vnf_id' in vnf:
864 error_text += " 'vnf_id' " + vnf['vnf_id']
865 WHERE_['uuid'] = vnf['vnf_id']
866 if 'VNF model' in vnf:
867 error_text += " 'VNF model' " + vnf['VNF model']
868 WHERE_['name'] = vnf['VNF model']
869 if len(WHERE_) == 0:
870 return -HTTP_Bad_Request, "needed a 'vnf_id' or 'VNF model' at " + error_pos
871 r,vnf_db = mydb.get_table(SELECT=('uuid','name','description'), FROM='vnfs', WHERE=WHERE_)
872 if r<0:
873 print "nfvo.new_scenario Error getting vnfs",r,vnf_db
874 elif r==0:
875 print "nfvo.new_scenario Error" + error_text + " is not present at database"
876 return -HTTP_Bad_Request, "unknown" + error_text + " at " + error_pos
877 elif r>1:
878 print "nfvo.new_scenario Error more than one" + error_text + " are present at database"
879 return -HTTP_Bad_Request, "more than one" + error_text + " at " + error_pos + " Concrete with 'vnf_id'"
880 vnf['uuid']=vnf_db[0]['uuid']
881 vnf['description']=vnf_db[0]['description']
882 #get external interfaces
883 r,ext_ifaces = mydb.get_table(SELECT=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
884 FROM='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
885 WHERE={'vnfs.uuid':vnf['uuid']}, WHERE_NOT={'external_name':None} )
886 if r<0:
887 print "nfvo.new_scenario Error getting external interfaces of vnfs",r,ext_ifaces
888 return -HTTP_Internal_Server_Error, "Error getting external interfaces of vnfs: " + ext_ifaces
889 for ext_iface in ext_ifaces:
890 vnf['ifaces'][ ext_iface['name'] ] = {'uuid':ext_iface['iface_uuid'], 'type':ext_iface['type']}
891
892 #1.4 get list of connections
893 conections = topo['topology']['connections']
894 conections_list = []
895 for k in conections.keys():
896 if type(conections[k]['nodes'])==dict: #dict with node:iface pairs
897 ifaces_list = conections[k]['nodes'].items()
898 elif type(conections[k]['nodes'])==list: #list with dictionary
899 ifaces_list=[]
900 conection_pair_list = map(lambda x: x.items(), conections[k]['nodes'] )
901 for k2 in conection_pair_list:
902 ifaces_list += k2
903
904 con_type = conections[k].get("type", "link")
905 if con_type != "link":
906 if k in other_nets:
907 return -HTTP_Bad_Request, "format error. Reapeted network name at 'topology':'connections':'%s'" % (str(k))
908 other_nets[k] = {'external': False}
909 if conections[k].get("graph"):
910 other_nets[k]["graph"] = conections[k]["graph"]
911 ifaces_list.append( (k, None) )
912
913
914 if con_type == "external_network":
915 other_nets[k]['external'] = True
916 if conections[k].get("model"):
917 other_nets[k]["model"] = conections[k]["model"]
918 else:
919 other_nets[k]["model"] = k
920 if con_type == "dataplane_net" or con_type == "bridge_net":
921 other_nets[k]["model"] = con_type
922
923
924 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)
925 #print set(ifaces_list)
926 #check valid VNF and iface names
927 for iface in ifaces_list:
928 if iface[0] not in vnfs and iface[0] not in other_nets :
929 return -HTTP_Bad_Request, "format error. Invalid VNF name at 'topology':'connections':'%s':'nodes':'%s'" % (str(k), iface[0])
930 if iface[0] in vnfs and iface[1] not in vnfs[ iface[0] ]['ifaces']:
931 return -HTTP_Bad_Request, "format error. Invalid interface name at 'topology':'connections':'%s':'nodes':'%s':'%s'" % (str(k), iface[0], iface[1])
932
933 #1.5 unify connections from the pair list to a consolidated list
934 index=0
935 while index < len(conections_list):
936 index2 = index+1
937 while index2 < len(conections_list):
938 if len(conections_list[index] & conections_list[index2])>0: #common interface, join nets
939 conections_list[index] |= conections_list[index2]
940 del conections_list[index2]
941 else:
942 index2 += 1
943 conections_list[index] = list(conections_list[index]) # from set to list again
944 index += 1
945 #for k in conections_list:
946 # print k
947
948
949
950 #1.6 Delete non external nets
951 # for k in other_nets.keys():
952 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
953 # for con in conections_list:
954 # delete_indexes=[]
955 # for index in range(0,len(con)):
956 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
957 # for index in delete_indexes:
958 # del con[index]
959 # del other_nets[k]
960 #1.7: Check external_ports are present at database table datacenter_nets
961 for k,net in other_nets.items():
962 error_pos = "'topology':'nodes':'" + k + "'"
963 if net['external']==False:
964 if 'name' not in net:
965 net['name']=k
966 if 'model' not in net:
967 return -HTTP_Bad_Request, "needed a 'model' at " + error_pos
968 if net['model']=='bridge_net':
969 net['type']='bridge';
970 elif net['model']=='dataplane_net':
971 net['type']='data';
972 else:
973 return -HTTP_Bad_Request, "unknown 'model' '"+ net['model'] +"' at " + error_pos
974 else: #external
975 #IF we do not want to check that external network exist at datacenter
976 pass
977 #ELSE
978 # error_text = ""
979 # WHERE_={}
980 # if 'net_id' in net:
981 # error_text += " 'net_id' " + net['net_id']
982 # WHERE_['uuid'] = net['net_id']
983 # if 'model' in net:
984 # error_text += " 'model' " + net['model']
985 # WHERE_['name'] = net['model']
986 # if len(WHERE_) == 0:
987 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
988 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
989 # FROM='datacenter_nets', WHERE=WHERE_ )
990 # if r<0:
991 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
992 # elif r==0:
993 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
994 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
995 # elif r>1:
996 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
997 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
998 # other_nets[k].update(net_db[0])
999 #ENDIF
1000 net_list={}
1001 net_nb=0 #Number of nets
1002 for con in conections_list:
1003 #check if this is connected to a external net
1004 other_net_index=-1
1005 #print
1006 #print "con", con
1007 for index in range(0,len(con)):
1008 #check if this is connected to a external net
1009 for net_key in other_nets.keys():
1010 if con[index][0]==net_key:
1011 if other_net_index>=0:
1012 error_text="There is some interface connected both to net '%s' and net '%s'" % (con[other_net_index][0], net_key)
1013 print "nfvo.new_scenario " + error_text
1014 return -HTTP_Bad_Request, error_text
1015 else:
1016 other_net_index = index
1017 net_target = net_key
1018 break
1019 #print "other_net_index", other_net_index
1020 try:
1021 if other_net_index>=0:
1022 del con[other_net_index]
1023 #IF we do not want to check that external network exist at datacenter
1024 if other_nets[net_target]['external'] :
1025 if "name" not in other_nets[net_target]:
1026 other_nets[net_target]['name'] = other_nets[net_target]['model']
1027 if other_nets[net_target]["type"] == "external_network":
1028 if vnfs[ con[0][0] ]['ifaces'][ con[0][1] ]["type"] == "data":
1029 other_nets[net_target]["type"] = "data"
1030 else:
1031 other_nets[net_target]["type"] = "bridge"
1032 #ELSE
1033 # if other_nets[net_target]['external'] :
1034 # 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
1035 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1036 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1037 # print "nfvo.new_scenario " + error_text
1038 # return -HTTP_Bad_Request, error_text
1039 #ENDIF
1040 for iface in con:
1041 vnfs[ iface[0] ]['ifaces'][ iface[1] ]['net_key'] = net_target
1042 else:
1043 #create a net
1044 net_type_bridge=False
1045 net_type_data=False
1046 net_target = "__-__net"+str(net_nb)
1047 net_list[net_target] = {'name': "net-"+str(net_nb), 'description':"net-%s in scenario %s" %(net_nb,topo['name']),
1048 'external':False}
1049 for iface in con:
1050 vnfs[ iface[0] ]['ifaces'][ iface[1] ]['net_key'] = net_target
1051 iface_type = vnfs[ iface[0] ]['ifaces'][ iface[1] ]['type']
1052 if iface_type=='mgmt' or iface_type=='bridge':
1053 net_type_bridge = True
1054 else:
1055 net_type_data = True
1056 if net_type_bridge and net_type_data:
1057 error_text = "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface[0], iface[1])
1058 print "nfvo.new_scenario " + error_text
1059 return -HTTP_Bad_Request, error_text
1060 elif net_type_bridge:
1061 type_='bridge'
1062 else:
1063 type_='data' if len(con)>2 else 'ptp'
1064 net_list[net_target]['type'] = type_
1065 net_nb+=1
1066 except Exception:
1067 error_text = "Error connection node %s : %s does not match any VNF or interface" % (iface[0], iface[1])
1068 print "nfvo.new_scenario " + error_text
1069 #raise e
1070 return -HTTP_Bad_Request, error_text
1071
1072 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1073 #1.8.1 obtain management net
1074 r,mgmt_net = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1075 FROM='datacenter_nets', WHERE={'name':'mgmt'} )
1076 #1.8.2 check all interfaces from all vnfs
1077 if r>0:
1078 add_mgmt_net = False
1079 for vnf in vnfs.values():
1080 for iface in vnf['ifaces'].values():
1081 if iface['type']=='mgmt' and 'net_key' not in iface:
1082 #iface not connected
1083 iface['net_key'] = 'mgmt'
1084 add_mgmt_net = True
1085 if add_mgmt_net and 'mgmt' not in net_list:
1086 net_list['mgmt']=mgmt_net[0]
1087 net_list['mgmt']['external']=True
1088 net_list['mgmt']['graph']={'visible':False}
1089
1090 net_list.update(other_nets)
1091 print
1092 print 'net_list', net_list
1093 print
1094 print 'vnfs', vnfs
1095 print
1096
1097 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1098 r,c = mydb.new_scenario( { 'vnfs':vnfs, 'nets':net_list,
1099 'tenant_id':tenant_id, 'name':topo['name'],
1100 'description':topo.get('description',topo['name']),
1101 'public': topo.get('public', False)
1102 })
1103
1104 return r,c
1105
1106 def new_scenario_v02(mydb, tenant_id, scenario_dict):
1107 scenario = scenario_dict["scenario"]
1108 if tenant_id != "any":
1109 if not check_tenant(mydb, tenant_id):
1110 print 'nfvo.new_scenario_v02() tenant %s not found' % tenant_id
1111 return -HTTP_Not_Found, 'Tenant %s not found' % tenant_id
1112 if "tenant_id" in scenario:
1113 if scenario["tenant_id"] != tenant_id:
1114 print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1115 return -HTTP_Unauthorized, "VNF can not have a different tenant owner '%s', must be '%s'" %(scenario["tenant_id"], tenant_id)
1116 else:
1117 tenant_id=None
1118
1119 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1120 for name,vnf in scenario["vnfs"].iteritems():
1121 WHERE_={}
1122 error_text = ""
1123 error_pos = "'topology':'nodes':'" + name + "'"
1124 if 'vnf_id' in vnf:
1125 error_text += " 'vnf_id' " + vnf['vnf_id']
1126 WHERE_['uuid'] = vnf['vnf_id']
1127 if 'vnf_name' in vnf:
1128 error_text += " 'vnf_name' " + vnf['vnf_name']
1129 WHERE_['name'] = vnf['vnf_name']
1130 if len(WHERE_) == 0:
1131 return -HTTP_Bad_Request, "needed a 'vnf_id' or 'VNF model' at " + error_pos
1132 r,vnf_db = mydb.get_table(SELECT=('uuid','name','description'), FROM='vnfs', WHERE=WHERE_)
1133 if r<0:
1134 print "nfvo.new_scenario Error getting vnfs",r,vnf_db
1135 elif r==0:
1136 print "nfvo.new_scenario Error" + error_text + " is not present at database"
1137 return -HTTP_Bad_Request, "unknown" + error_text + " at " + error_pos
1138 elif r>1:
1139 print "nfvo.new_scenario Error more than one" + error_text + " are present at database"
1140 return -HTTP_Bad_Request, "more than one" + error_text + " at " + error_pos + " Concrete with 'vnf_id'"
1141 vnf['uuid']=vnf_db[0]['uuid']
1142 vnf['description']=vnf_db[0]['description']
1143 vnf['ifaces'] = {}
1144 #get external interfaces
1145 r,ext_ifaces = mydb.get_table(SELECT=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1146 FROM='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1147 WHERE={'vnfs.uuid':vnf['uuid']}, WHERE_NOT={'external_name':None} )
1148 if r<0:
1149 print "nfvo.new_scenario Error getting external interfaces of vnfs",r,ext_ifaces
1150 return -HTTP_Internal_Server_Error, "Error getting external interfaces of vnfs: " + ext_ifaces
1151 for ext_iface in ext_ifaces:
1152 vnf['ifaces'][ ext_iface['name'] ] = {'uuid':ext_iface['iface_uuid'], 'type':ext_iface['type']}
1153
1154 #2: Insert net_key at every vnf interface
1155 for net_name,net in scenario["networks"].iteritems():
1156 net_type_bridge=False
1157 net_type_data=False
1158 for iface_dict in net["interfaces"]:
1159 for vnf,iface in iface_dict.iteritems():
1160 if vnf not in scenario["vnfs"]:
1161 error_text = "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name, vnf)
1162 print "nfvo.new_scenario_v02 " + error_text
1163 return -HTTP_Bad_Request, error_text
1164 if iface not in scenario["vnfs"][vnf]['ifaces']:
1165 error_text = "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name, iface)
1166 print "nfvo.new_scenario_v02 " + error_text
1167 return -HTTP_Bad_Request, error_text
1168 if "net_key" in scenario["vnfs"][vnf]['ifaces'][iface]:
1169 error_text = "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1170 % (net_name, iface,scenario["vnfs"][vnf]['ifaces'][iface]['net_key'])
1171 print "nfvo.new_scenario_v02 " + error_text
1172 return -HTTP_Bad_Request, error_text
1173 scenario["vnfs"][vnf]['ifaces'][ iface ]['net_key'] = net_name
1174 iface_type = scenario["vnfs"][vnf]['ifaces'][iface]['type']
1175 if iface_type=='mgmt' or iface_type=='bridge':
1176 net_type_bridge = True
1177 else:
1178 net_type_data = True
1179 if net_type_bridge and net_type_data:
1180 error_text = "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name)
1181 print "nfvo.new_scenario " + error_text
1182 return -HTTP_Bad_Request, error_text
1183 elif net_type_bridge:
1184 type_='bridge'
1185 else:
1186 type_='data' if len(net["interfaces"])>2 else 'ptp'
1187 net['type'] = type_
1188 net['name'] = net_name
1189 net['external'] = net.get('external', False)
1190
1191 #3: insert at database
1192 scenario["nets"] = scenario["networks"]
1193 scenario['tenant_id'] = tenant_id
1194 r,c = mydb.new_scenario( scenario)
1195
1196 return r,c
1197
1198 def edit_scenario(mydb, tenant_id, scenario_id, data):
1199 data["uuid"] = scenario_id
1200 data["tenant_id"] = tenant_id
1201 r,c = mydb.edit_scenario( data )
1202 return r,c
1203
1204 def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instance_scenario_description, datacenter=None,vim_tenant=None, startvms=True):
1205 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1206 datacenter_id = None
1207 datacenter_name=None
1208 if datacenter != None:
1209 if utils.check_valid_uuid(datacenter):
1210 datacenter_id = datacenter
1211 else:
1212 datacenter_name = datacenter
1213 result, vims = get_vim(mydb, tenant_id, datacenter_id, datacenter_name, vim_tenant)
1214 if result < 0:
1215 logger.error("start_scenario error. Datacenter not found")
1216 return result, vims
1217 elif result == 0:
1218 return -HTTP_Not_Found, "datacenter '%s' not found" % str(datacenter)
1219 elif result > 1:
1220 logger.error("start_scenario error. Several datacenters available, you must concrete")
1221 return -HTTP_Bad_Request, "Several datacenters available, you must concrete"
1222 myvim = vims.values()[0]
1223 myvim_tenant = myvim['tenant_id']
1224 datacenter_id = myvim['id']
1225 datacenter_name = myvim['name']
1226 datacenter_tenant_id = myvim['config']['datacenter_tenant_id']
1227 rollbackList=[]
1228 try:
1229 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1230 result, scenarioDict = mydb.get_scenario(scenario_id, tenant_id, datacenter_id)
1231 if result < 0:
1232 logger.error("start_scenario error. Error interacting with NFVO DB")
1233 return result, scenarioDict
1234 elif result == 0:
1235 logger.error("start_scenario error. Scenario not found")
1236 return result, scenarioDict
1237
1238 scenarioDict['datacenter_tenant_id'] = datacenter_tenant_id
1239 scenarioDict['datacenter_id'] = datacenter_id
1240 #print '================scenarioDict======================='
1241 #print json.dumps(scenarioDict, indent=4)
1242 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1243
1244 logger.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict['name'],len(scenarioDict['vnfs']))
1245 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1246
1247 auxNetDict = {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1248 auxNetDict['scenario'] = {}
1249
1250 logger.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1251 for sce_net in scenarioDict['nets']:
1252 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1253
1254 myNetName = "%s.%s" % (instance_scenario_name, sce_net['name'])
1255 myNetName = myNetName[0:255] #limit length
1256 myNetType = sce_net['type']
1257 myNetDict = {}
1258 myNetDict["name"] = myNetName
1259 myNetDict["type"] = myNetType
1260 myNetDict["tenant_id"] = myvim_tenant
1261 #TODO:
1262 #We should use the dictionary as input parameter for new_network
1263 print myNetDict
1264 if not sce_net["external"]:
1265 network_id = myvim.new_network(myNetName, myNetType)
1266 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1267 sce_net['vim_id'] = network_id
1268 auxNetDict['scenario'][sce_net['uuid']] = network_id
1269 rollbackList.append({'what':'network','where':'vim','vim_id':datacenter_id,'uuid':network_id})
1270 else:
1271 if sce_net['vim_id'] == None:
1272 error_text = "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name, sce_net['name'])
1273 _, message = rollback(mydb, vims, rollbackList)
1274 logger.error("nfvo.start_scenario: %s", error_text)
1275 return -HTTP_Bad_Request, error_text
1276 logger.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict['name'],sce_net['vim_id'])
1277 auxNetDict['scenario'][sce_net['uuid']] = sce_net['vim_id']
1278
1279 logger.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1280 #For each vnf net, we create it and we add it to instanceNetlist.
1281 for sce_vnf in scenarioDict['vnfs']:
1282 for net in sce_vnf['nets']:
1283 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1284
1285 myNetName = "%s.%s" % (instance_scenario_name,net['name'])
1286 myNetName = myNetName[0:255] #limit length
1287 myNetType = net['type']
1288 myNetDict = {}
1289 myNetDict["name"] = myNetName
1290 myNetDict["type"] = myNetType
1291 myNetDict["tenant_id"] = myvim_tenant
1292 #print myNetDict
1293 #TODO:
1294 #We should use the dictionary as input parameter for new_network
1295 result, network_id = myvim.new_network(myNetName, myNetType)
1296 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1297 net['vim_id'] = network_id
1298 if sce_vnf['uuid'] not in auxNetDict:
1299 auxNetDict[sce_vnf['uuid']] = {}
1300 auxNetDict[sce_vnf['uuid']][net['uuid']] = network_id
1301 rollbackList.append({'what':'network','where':'vim','vim_id':datacenter_id,'uuid':network_id})
1302
1303 #print "auxNetDict:"
1304 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1305
1306 logger.debug("start_scenario 3. Creating new vm instances in the VIM")
1307 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1308 i = 0
1309 for sce_vnf in scenarioDict['vnfs']:
1310 for vm in sce_vnf['vms']:
1311 i += 1
1312 myVMDict = {}
1313 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1314 myVMDict['name'] = "%s.%s.%d" % (instance_scenario_name,sce_vnf['name'],i)
1315 #myVMDict['description'] = vm['description']
1316 myVMDict['description'] = myVMDict['name'][0:99]
1317 if not startvms:
1318 myVMDict['start'] = "no"
1319 myVMDict['name'] = myVMDict['name'][0:255] #limit name length
1320 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1321
1322 #create image at vim in case it not exist
1323 res, image_dict = mydb.get_table_by_uuid_name("images", vm['image_id'])
1324 if res<0:
1325 logger.error("start_scenario error getting image %s", str(image_dict))
1326 return res, image_dict
1327 res, image_id = create_or_use_image(mydb, vims, image_dict, [], True)
1328 if res < 0:
1329 logger.error("start_scenario error adding image to VIM: %s", str(image_dict))
1330 return res, image_id
1331 vm['vim_image_id'] = image_id
1332
1333 #create flavor at vim in case it not exist
1334 res, flavor_dict = mydb.get_table_by_uuid_name("flavors", vm['flavor_id'])
1335 if res<0:
1336 logger.error("start_scenario error getting flavor: %s", str(flavor_dict))
1337 return res, flavor_dict
1338 if flavor_dict['extended']!=None:
1339 flavor_dict['extended']= yaml.load(flavor_dict['extended'])
1340 res, flavor_id = create_or_use_flavor(mydb, vims, flavor_dict, [], True)
1341 if res < 0:
1342 logger.error("start_scenario error adding flavor to VIM: ", str(flavor_dict))
1343 return res, flavor_id
1344 vm['vim_flavor_id'] = flavor_id
1345
1346
1347 myVMDict['imageRef'] = vm['vim_image_id']
1348 myVMDict['flavorRef'] = vm['vim_flavor_id']
1349 myVMDict['networks'] = []
1350 for iface in vm['interfaces']:
1351 netDict = {}
1352 if iface['type']=="data":
1353 netDict['type'] = iface['model']
1354 elif "model" in iface and iface["model"]!=None:
1355 netDict['model']=iface['model']
1356 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1357 #discover type of interface looking at flavor
1358 for numa in flavor_dict.get('extended',{}).get('numas',[]):
1359 for flavor_iface in numa.get('interfaces',[]):
1360 if flavor_iface.get('name') == iface['internal_name']:
1361 if flavor_iface['dedicated'] == 'yes':
1362 netDict['type']="PF" #passthrough
1363 elif flavor_iface['dedicated'] == 'no':
1364 netDict['type']="VF" #siov
1365 elif flavor_iface['dedicated'] == 'yes:sriov':
1366 netDict['type']="VFnotShared" #sriov but only one sriov on the PF
1367 netDict["mac_address"] = flavor_iface.get("mac_address")
1368 break;
1369 netDict["use"]=iface['type']
1370 if netDict["use"]=="data" and not netDict.get("type"):
1371 #print "netDict", netDict
1372 #print "iface", iface
1373 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'])
1374 if flavor_dict.get('extended')==None:
1375 return -HTTP_Conflict, e_text + "After database migration some information is not available. \
1376 Try to delete and create the scenarios and VNFs again"
1377 else:
1378 return -HTTP_Internal_Server_Error, e_text
1379 if netDict["use"]=="mgmt" or netDict["use"]=="bridge":
1380 netDict["type"]="virtual"
1381 if "vpci" in iface and iface["vpci"] is not None:
1382 netDict['vpci'] = iface['vpci']
1383 if "mac" in iface and iface["mac"] is not None:
1384 netDict['mac_address'] = iface['mac']
1385 netDict['name'] = iface['internal_name']
1386 if iface['net_id'] is None:
1387 for vnf_iface in sce_vnf["interfaces"]:
1388 print iface
1389 print vnf_iface
1390 if vnf_iface['interface_id']==iface['uuid']:
1391 netDict['net_id'] = auxNetDict['scenario'][ vnf_iface['sce_net_id'] ]
1392 break
1393 else:
1394 netDict['net_id'] = auxNetDict[ sce_vnf['uuid'] ][ iface['net_id'] ]
1395 #skip bridge ifaces not connected to any net
1396 #if 'net_id' not in netDict or netDict['net_id']==None:
1397 # continue
1398 myVMDict['networks'].append(netDict)
1399 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1400 #print myVMDict['name']
1401 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1402 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1403 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1404 vm_id = myvim.new_vminstance(myVMDict['name'],myVMDict['description'],myVMDict.get('start', None),
1405 myVMDict['imageRef'],myVMDict['flavorRef'],myVMDict['networks'])
1406 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1407 vm['vim_id'] = vm_id
1408 rollbackList.append({'what':'vm','where':'vim','vim_id':datacenter_id,'uuid':vm_id})
1409 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1410 for net in myVMDict['networks']:
1411 if "vim_id" in net:
1412 for iface in vm['interfaces']:
1413 if net["name"]==iface["internal_name"]:
1414 iface["vim_id"]=net["vim_id"]
1415 break
1416
1417 logger.debug("start scenario Deployment done")
1418 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1419 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1420 result,c = mydb.new_instance_scenario_as_a_whole(tenant_id,instance_scenario_name, instance_scenario_description, scenarioDict)
1421 if result <0:
1422 error_text = c + "."
1423 _, message = rollback(mydb, vims, rollbackList)
1424 error_text += message
1425 print "start_scenario: " + error_text
1426 return result, error_text
1427
1428 return mydb.get_instance_scenario(c)
1429 except vimconn.vimconnException as e:
1430 _, message = rollback(mydb, vims, rollbackList)
1431 error_text = "VIM exception {} {}. {}".format(type(e).__name__, str(e), message)
1432 logger.error("start_scenario %s", error_text)
1433 return -e.http_code, error_text
1434
1435 def create_instance(mydb, tenant_id, instance_dict):
1436 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1437 scenario = instance_dict["scenario"]
1438 datacenter_id = None
1439 datacenter_name=None
1440 datacenter = instance_dict.get("datacenter")
1441 if datacenter:
1442 if utils.check_valid_uuid(datacenter):
1443 datacenter_id = datacenter
1444 else:
1445 datacenter_name = datacenter
1446 result, vims = get_vim(mydb, tenant_id, datacenter_id, datacenter_name, vim_tenant=None)
1447 if result < 0:
1448 logger.error("create_instance error. Datacenter not found")
1449 return result, vims
1450 elif result == 0:
1451 return -HTTP_Not_Found, "datacenter '%s' not found" % str(datacenter)
1452 elif result > 1:
1453 logger.error("create_instance error. Several datacenters available, you must concrete")
1454 return -HTTP_Bad_Request, "Several datacenters available, you must concrete"
1455 myvim = vims.values()[0]
1456 #myvim_tenant = myvim['tenant_id']
1457 datacenter_id = myvim['id']
1458 datacenter_name = myvim['name']
1459 datacenter_tenant_id = myvim['config']['datacenter_tenant_id']
1460 rollbackList=[]
1461
1462 #print "Checking that the scenario exists and getting the scenario dictionary"
1463 result, scenarioDict = mydb.get_scenario(scenario, tenant_id, datacenter_id)
1464 if result < 0:
1465 logger.error("create_instance error. Error interacting with NFVO DB")
1466 return result, scenarioDict
1467 elif result == 0:
1468 logger.error("create_instance error. Scenario not found")
1469 return result, scenarioDict
1470
1471 scenarioDict['datacenter_tenant_id'] = datacenter_tenant_id
1472 scenarioDict['datacenter_id'] = datacenter_id
1473
1474 auxNetDict = {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1475 auxNetDict['scenario'] = {}
1476
1477 #print "scenario dict: ",yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1478 instance_name = instance_dict["name"]
1479 instance_description = instance_dict.get("description")
1480 try:
1481 #0 check correct parameters
1482 for descriptor_net in instance_dict.get("networks",{}).keys():
1483 found=False
1484 for scenario_net in scenarioDict['nets']:
1485 if descriptor_net == scenario_net["name"]:
1486 found = True
1487 break
1488 if not found:
1489 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(descriptor_net), HTTP_Bad_Request)
1490 for descriptor_vnf in instance_dict.get("vnfs",{}).keys():
1491 found=False
1492 for scenario_vnf in scenarioDict['vnfs']:
1493 if descriptor_vnf == scenario_vnf['name']:
1494 found = True
1495 break
1496 if not found:
1497 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(descriptor_vnf), HTTP_Bad_Request)
1498
1499 #1. Creating new nets (sce_nets) in the VIM"
1500 for sce_net in scenarioDict['nets']:
1501 descriptor_net = instance_dict.get("networks",{}).get(sce_net["name"],{})
1502 net_name = descriptor_net.get("name")
1503 net_type = sce_net['type']
1504 lookfor_filter = {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
1505 if sce_net["external"]:
1506 if not net_name:
1507 net_name = sce_net["name"]
1508 if "netmap-use" in descriptor_net or "netmap-create" in descriptor_net:
1509 create_network = False
1510 lookfor_network = False
1511 if "netmap-use" in descriptor_net:
1512 lookfor_network = True
1513 if utils.check_valid_uuid(descriptor_net["netmap-use"]):
1514 filter_text = "scenario id '%s'" % descriptor_net["netmap-use"]
1515 lookfor_filter["id"] = descriptor_net["netmap-use"]
1516 else:
1517 filter_text = "scenario name '%s'" % descriptor_net["netmap-use"]
1518 lookfor_filter["name"] = descriptor_net["netmap-use"]
1519 if "netmap-create" in descriptor_net:
1520 create_network = True
1521 net_vim_name = net_name
1522 if descriptor_net["netmap-create"]:
1523 net_vim_name= descriptor_net["netmap-create"]
1524
1525 elif sce_net['vim_id'] != None:
1526 #there is a netmap at datacenter_nets database
1527 create_network = False
1528 lookfor_network = True
1529 lookfor_filter["id"] = sce_net['vim_id']
1530 filter_text = "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net['vim_id'], sce_net["name"])
1531 #look for network at datacenter and return error
1532 else:
1533 #There is not a netmap, look at datacenter for a net with this name and create if not found
1534 create_network = True
1535 lookfor_network = True
1536 lookfor_filter["name"] = sce_net["name"]
1537 net_vim_name = sce_net["name"]
1538 filter_text = "scenario name '%s'" % sce_net["name"]
1539 else:
1540 if not net_name:
1541 net_name = "%s.%s" %(instance_name, sce_net["name"])
1542 net_name = net_name[:255] #limit length
1543 net_vim_name = net_name
1544 create_network = True
1545 lookfor_network = False
1546
1547 if lookfor_network:
1548 vim_nets = myvim.get_network_list(filter_dict=lookfor_filter)
1549 if len(vim_nets) > 1:
1550 raise NfvoException("More than one candidate VIM network found for " + filter_text, HTTP_Bad_Request )
1551 elif len(vim_nets) == 0:
1552 if not create_network:
1553 raise NfvoException("No candidate VIM network found for " + filter_text, HTTP_Bad_Request )
1554 else:
1555 sce_net['vim_id'] = vim_nets[0]['id']
1556 auxNetDict['scenario'][sce_net['uuid']] = vim_nets[0]['id']
1557 create_network = False
1558 if create_network:
1559 #if network is not external
1560 network_id = myvim.new_network(net_vim_name, net_type)
1561 sce_net['vim_id'] = network_id
1562 auxNetDict['scenario'][sce_net['uuid']] = network_id
1563 rollbackList.append({'what':'network','where':'vim','vim_id':datacenter_id,'uuid':network_id})
1564
1565 #2. Creating new nets (vnf internal nets) in the VIM"
1566 #For each vnf net, we create it and we add it to instanceNetlist.
1567 for sce_vnf in scenarioDict['vnfs']:
1568 for net in sce_vnf['nets']:
1569 descriptor_net = instance_dict.get("vnfs",{}).get(sce_vnf["name"],{})
1570 net_name = descriptor_net.get("name")
1571 if not net_name:
1572 net_name = "%s.%s" %(instance_name, net["name"])
1573 net_name = net_name[:255] #limit length
1574 net_type = net['type']
1575 network_id = myvim.new_network(net_name, net_type)
1576 net['vim_id'] = network_id
1577 if sce_vnf['uuid'] not in auxNetDict:
1578 auxNetDict[sce_vnf['uuid']] = {}
1579 auxNetDict[sce_vnf['uuid']][net['uuid']] = network_id
1580 rollbackList.append({'what':'network','where':'vim','vim_id':datacenter_id,'uuid':network_id})
1581
1582 #print "auxNetDict:"
1583 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1584
1585 #3. Creating new vm instances in the VIM
1586 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1587 for sce_vnf in scenarioDict['vnfs']:
1588 i = 0
1589 for vm in sce_vnf['vms']:
1590 i += 1
1591 myVMDict = {}
1592 myVMDict['name'] = "%s.%s.%d" % (instance_name,sce_vnf['name'],i)
1593 myVMDict['description'] = myVMDict['name'][0:99]
1594 # if not startvms:
1595 # myVMDict['start'] = "no"
1596 myVMDict['name'] = myVMDict['name'][0:255] #limit name length
1597 #create image at vim in case it not exist
1598 res, image_dict = mydb.get_table_by_uuid_name("images", vm['image_id'])
1599 if res<0:
1600 raise NfvoException("Error getting VIM image "+ image_dict, -result)
1601 res, image_id = create_or_use_image(mydb, vims, image_dict, [], True)
1602 if res < 0:
1603 raise NfvoException("Error adding image to VIM " + image_dict, -result)
1604 vm['vim_image_id'] = image_id
1605
1606 #create flavor at vim in case it not exist
1607 res, flavor_dict = mydb.get_table_by_uuid_name("flavors", vm['flavor_id'])
1608 if res<0:
1609 raise NfvoException("Error getting VIM flavor "+ flavor_dict, -result)
1610 if flavor_dict['extended']!=None:
1611 flavor_dict['extended']= yaml.load(flavor_dict['extended'])
1612 res, flavor_id = create_or_use_flavor(mydb, vims, flavor_dict, [], True)
1613 if res < 0:
1614 raise NfvoException("Error adding flavor to VIM" + flavor_dict, -result)
1615 vm['vim_flavor_id'] = flavor_id
1616
1617 myVMDict['imageRef'] = vm['vim_image_id']
1618 myVMDict['flavorRef'] = vm['vim_flavor_id']
1619 myVMDict['networks'] = []
1620 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
1621 for iface in vm['interfaces']:
1622 netDict = {}
1623 if iface['type']=="data":
1624 netDict['type'] = iface['model']
1625 elif "model" in iface and iface["model"]!=None:
1626 netDict['model']=iface['model']
1627 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1628 #discover type of interface looking at flavor
1629 for numa in flavor_dict.get('extended',{}).get('numas',[]):
1630 for flavor_iface in numa.get('interfaces',[]):
1631 if flavor_iface.get('name') == iface['internal_name']:
1632 if flavor_iface['dedicated'] == 'yes':
1633 netDict['type']="PF" #passthrough
1634 elif flavor_iface['dedicated'] == 'no':
1635 netDict['type']="VF" #siov
1636 elif flavor_iface['dedicated'] == 'yes:sriov':
1637 netDict['type']="VFnotShared" #sriov but only one sriov on the PF
1638 netDict["mac_address"] = flavor_iface.get("mac_address")
1639 break;
1640 netDict["use"]=iface['type']
1641 if netDict["use"]=="data" and not netDict.get("type"):
1642 #print "netDict", netDict
1643 #print "iface", iface
1644 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'])
1645 if flavor_dict.get('extended')==None:
1646 raise NfvoException(e_text + "After database migration some information is not available. \
1647 Try to delete and create the scenarios and VNFs again", HTTP_Conflict)
1648 else:
1649 raise NfvoException(e_text, HTTP_Internal_Server_Error)
1650 if netDict["use"]=="mgmt" or netDict["use"]=="bridge":
1651 netDict["type"]="virtual"
1652 if "vpci" in iface and iface["vpci"] is not None:
1653 netDict['vpci'] = iface['vpci']
1654 if "mac" in iface and iface["mac"] is not None:
1655 netDict['mac_address'] = iface['mac']
1656 netDict['name'] = iface['internal_name']
1657 if iface['net_id'] is None:
1658 for vnf_iface in sce_vnf["interfaces"]:
1659 print iface
1660 print vnf_iface
1661 if vnf_iface['interface_id']==iface['uuid']:
1662 netDict['net_id'] = auxNetDict['scenario'][ vnf_iface['sce_net_id'] ]
1663 break
1664 else:
1665 netDict['net_id'] = auxNetDict[ sce_vnf['uuid'] ][ iface['net_id'] ]
1666 #skip bridge ifaces not connected to any net
1667 #if 'net_id' not in netDict or netDict['net_id']==None:
1668 # continue
1669 myVMDict['networks'].append(netDict)
1670 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1671 #print myVMDict['name']
1672 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1673 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1674 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1675 vm_id = myvim.new_vminstance(myVMDict['name'],myVMDict['description'],myVMDict.get('start', None),
1676 myVMDict['imageRef'],myVMDict['flavorRef'],myVMDict['networks'])
1677 vm['vim_id'] = vm_id
1678 rollbackList.append({'what':'vm','where':'vim','vim_id':datacenter_id,'uuid':vm_id})
1679 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1680 for net in myVMDict['networks']:
1681 if "vim_id" in net:
1682 for iface in vm['interfaces']:
1683 if net["name"]==iface["internal_name"]:
1684 iface["vim_id"]=net["vim_id"]
1685 break
1686 logger.debug("create_instance Deployment done")
1687 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1688 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1689 result,c = mydb.new_instance_scenario_as_a_whole(tenant_id,instance_name, instance_description, scenarioDict)
1690 if result <0:
1691 raise NfvoException(c, -result)
1692
1693 return mydb.get_instance_scenario(c)
1694 except NfvoException as e:
1695 _, message = rollback(mydb, vims, rollbackList)
1696 error_text = "{} {}. {}".format(type(e).__name__, str(e), message)
1697 logger.error("create_instance: %s", error_text)
1698 return -e.http_code, error_text
1699 except vimconn.vimconnException as e:
1700 _, message = rollback(mydb, vims, rollbackList)
1701 error_text = "VIM exception {} {}. {}".format(type(e).__name__, str(e), message)
1702 logger.error("create_instance: %s", error_text)
1703 return -e.http_code, error_text
1704
1705 def delete_instance(mydb, tenant_id, instance_id):
1706 #print "Checking that the instance_id exists and getting the instance dictionary"
1707 result, instanceDict = mydb.get_instance_scenario(instance_id, tenant_id)
1708 if result < 0:
1709 logger.error("nfvo.delete_instance() error. Error getting info from database")
1710 return result, instanceDict
1711 elif result == 0:
1712 logger.error("delete_instance error. Instance not found")
1713 return result, instanceDict
1714 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
1715 tenant_id = instanceDict["tenant_id"]
1716 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1717 result, vims = get_vim(mydb, tenant_id, instanceDict['datacenter_id'])
1718 if result < 0:
1719 logger.error("nfvo.delete_instance() error. Datacenter error %s %s", result, vims)
1720 return result, vims
1721 elif result == 0:
1722 logger.error("!!!!!! nfvo.delete_instance() datacenter not found!!!!")
1723 myvim = None
1724 else:
1725 myvim = vims.values()[0]
1726
1727
1728 #1. Delete from Database
1729
1730 #result,c = mydb.delete_row('instance_scenarios', instance_id, nfvo_tenant)
1731 result,c = mydb.delete_instance_scenario(instance_id, tenant_id)
1732 if result<0:
1733 return result, c
1734
1735 #2. delete from VIM
1736 if not myvim:
1737 error_msg = "Not possible to delete VIM VMs and networks. Datacenter not found at database!!!"
1738 else:
1739 error_msg = ""
1740
1741 #2.1 deleting VMs
1742 #vm_fail_list=[]
1743 for sce_vnf in instanceDict['vnfs']:
1744 if not myvim:
1745 continue
1746 for vm in sce_vnf['vms']:
1747 try:
1748 myvim.delete_vminstance(vm['vim_vm_id'])
1749 except vimconn.vimconnNotFoundException as e:
1750 error_msg+="\n VM id={} not found at VIM".format(vm['vim_vm_id'])
1751 logger.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
1752 vm['name'], vm['uuid'], vm['vim_vm_id'], sce_vnf['vnf_id'])
1753 except vimconn.vimconnException as e:
1754 error_msg+="\n Error: " + e.http_code + " VM id=" + vm['vim_vm_id']
1755 logger.error("Error %d deleting VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s': %s",
1756 e.http_code, vm['name'], vm['uuid'], vm['vim_vm_id'], sce_vnf['vnf_id'], str(e))
1757
1758 #2.2 deleting NETS
1759 #net_fail_list=[]
1760 for net in instanceDict['nets']:
1761 if net['external']:
1762 continue #skip not created nets
1763 if not myvim:
1764 continue
1765 try:
1766 myvim.delete_network(net['vim_net_id'])
1767 except vimconn.vimconnNotFoundException as e:
1768 error_msg+="\n NET id={} not found at VIM".format(net['vim_net_id'])
1769 logger.warn("NET '%s', VIM id '%s', from VNF_id '%s' not found",
1770 net['uuid'], vm['vim_net_id'], sce_vnf['vnf_id'])
1771 except vimconn.vimconnException as e:
1772 error_msg+="\n Error: " + e.http_code + " Net id=" + net['vim_vm_id']
1773 logger.error("Error %d deleting NET '%s', VIM id '%s', from VNF_id '%s': %s",
1774 e.http_code, net['uuid'], net['vim_net_id'], sce_vnf['vnf_id'], str(e))
1775 if len(error_msg)>0:
1776 return 1, 'instance ' + instance_id + ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
1777 else:
1778 return 1, 'instance ' + instance_id + ' deleted'
1779
1780 def refresh_instance(mydb, nfvo_tenant, instanceDict, datacenter=None, vim_tenant=None):
1781 '''Refreshes a scenario instance. It modifies instanceDict'''
1782 '''Returns:
1783 - 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
1784 - error_msg
1785 '''
1786 # Assumption: nfvo_tenant and instance_id were checked before entering into this function
1787 #print "nfvo.refresh_instance begins"
1788 #print json.dumps(instanceDict, indent=4)
1789
1790 #print "Getting the VIM URL and the VIM tenant_id"
1791 result, vims = get_vim(mydb, nfvo_tenant, instanceDict['datacenter_id'])
1792 if result < 0:
1793 logger.error("nfvo.refresh_instance() error. Datacenter not found")
1794 return result, vims
1795 elif result == 0:
1796 return -HTTP_Not_Found, "datacenter '%s' not found" % str(instanceDict['datacenter_id'])
1797 myvim = vims.values()[0]
1798
1799 # 1. Getting VIM vm and net list
1800 vms_updated = [] #List of VM instance uuids in openmano that were updated
1801 vms_notupdated=[]
1802 vm_list = []
1803 for sce_vnf in instanceDict['vnfs']:
1804 for vm in sce_vnf['vms']:
1805 vm_list.append(vm['vim_vm_id'])
1806 vms_notupdated.append(vm["uuid"])
1807
1808 nets_updated = [] #List of VM instance uuids in openmano that were updated
1809 nets_notupdated=[]
1810 net_list=[]
1811 for net in instanceDict['nets']:
1812 net_list.append(net['vim_net_id'])
1813 nets_notupdated.append(net["uuid"])
1814
1815 try:
1816 # 1. Getting the status of all VMs
1817 vm_dict = myvim.refresh_vms_status(vm_list)
1818
1819 # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
1820 for sce_vnf in instanceDict['vnfs']:
1821 for vm in sce_vnf['vms']:
1822 vm_id = vm['vim_vm_id']
1823 interfaces = vm_dict[vm_id].pop('interfaces', [])
1824 #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
1825 has_mgmt_iface = False
1826 for iface in vm["interfaces"]:
1827 if iface["type"]=="mgmt":
1828 has_mgmt_iface = True
1829 if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
1830 vm_dict[vm_id]['status'] = "ACTIVE"
1831 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'):
1832 vm['status'] = vm_dict[vm_id]['status']
1833 vm['error_msg'] = vm_dict[vm_id].get('error_msg')
1834 vm['vim_info'] = vm_dict[vm_id].get('vim_info')
1835 # 2.1. Update in openmano DB the VMs whose status changed
1836 result2, _ = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
1837 if result2<0:
1838 logger.error("nfvo.refresh_instance error database update: %s", result2)
1839 else:
1840 vms_notupdated.remove(vm["uuid"])
1841 if result2>0:
1842 vms_updated.append(vm["uuid"])
1843 # 2.2. Update in openmano DB the interface VMs
1844 for interface in interfaces:
1845 #translate from vim_net_id to instance_net_id
1846 network_id=None
1847 for net in instanceDict['nets']:
1848 if net["vim_net_id"] == interface["vim_net_id"]:
1849 network_id = net["uuid"]
1850 break
1851 if not network_id:
1852 continue
1853 del interface["vim_net_id"]
1854 result2, _ = mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
1855 if result2<0:
1856 logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
1857
1858 # 3. Getting the status of all nets
1859 net_dict = myvim.refresh_nets_status(net_list)
1860
1861 # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
1862 # TODO: update nets inside a vnf
1863 for net in instanceDict['nets']:
1864 net_id = net['vim_net_id']
1865 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'):
1866 net['status'] = net_dict[net_id]['status']
1867 net['error_msg'] = net_dict[net_id].get('error_msg')
1868 net['vim_info'] = net_dict[net_id].get('vim_info')
1869 # 5.1. Update in openmano DB the nets whose status changed
1870 result2, _ = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
1871 if result2<0:
1872 logger.error("nfvo.refresh_instance error database update: %s", result2)
1873 else:
1874 nets_notupdated.remove(net["uuid"])
1875 if result2>0:
1876 nets_updated.append(net["uuid"])
1877 except vimconn.vimconnException as e:
1878 logger.error("VIM exception %s %s", type(e).__name__, str(e))
1879 return -e.http_code, str(e)
1880
1881 # Returns appropriate output
1882 #print "nfvo.refresh_instance finishes"
1883 logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
1884 str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
1885 instance_id = instanceDict['uuid']
1886 if len(vms_notupdated)+len(nets_notupdated)>0:
1887 error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
1888 return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
1889
1890 return 0, 'Scenario instance ' + instance_id + ' refreshed.'
1891
1892 def instance_action(mydb,nfvo_tenant,instance_id, action_dict):
1893 #print "Checking that the instance_id exists and getting the instance dictionary"
1894 result, instanceDict = mydb.get_instance_scenario(instance_id, nfvo_tenant)
1895 if result < 0:
1896 logger.error("nfvo.instance_action() error. Error getting info from database")
1897 return result, instanceDict
1898 elif result == 0:
1899 logger.error("instance_action error. Instance not found")
1900 return -HTTP_Not_Found, "instance {} not found".format(instance_id)
1901 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
1902
1903 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1904 result, vims = get_vim(mydb, nfvo_tenant, instanceDict['datacenter_id'])
1905 if result < 0:
1906 logger.error("nfvo.instance_action() error. Datacenter not found")
1907 return result, vims
1908 elif result == 0:
1909 return -HTTP_Not_Found, "datacenter '{}' not found".format(str(instanceDict['datacenter_id']))
1910 myvim = vims.values()[0]
1911
1912
1913 input_vnfs = action_dict.pop("vnfs", [])
1914 input_vms = action_dict.pop("vms", [])
1915 action_over_all = True if len(input_vnfs)==0 and len (input_vms)==0 else False
1916 vm_result = {}
1917 vm_error = 0
1918 vm_ok = 0
1919 for sce_vnf in instanceDict['vnfs']:
1920 for vm in sce_vnf['vms']:
1921 if not action_over_all:
1922 if sce_vnf['uuid'] not in input_vnfs and sce_vnf['vnf_name'] not in input_vnfs and \
1923 vm['uuid'] not in input_vms and vm['name'] not in input_vms:
1924 continue
1925 try:
1926 data = myvim.action_vminstance(vm['vim_vm_id'], action_dict)
1927 if "console" in action_dict:
1928 if data["server"]=="127.0.0.1" or data["server"]=="localhost":
1929 vm_result[ vm['uuid'] ] = {"vim_result": -HTTP_Unauthorized,
1930 "description": "this console is only reachable by local interface",
1931 "name":vm['name']
1932 }
1933 vm_error+=1
1934 continue
1935 #print "console data", data
1936 r2, console_thread = create_or_use_console_proxy_thread(data["server"], data["port"])
1937 if r2<0:
1938 vm_result[ vm['uuid'] ] = {"vim_result": -r2, "name":vm['name'], "description": console_thread}
1939 else:
1940 vm_result[ vm['uuid'] ] = {"vim_result": result,
1941 "description": "%s//%s:%d/%s" %(data["protocol"], console_thread.host, console_thread.port, data["suffix"]),
1942 "name":vm['name']
1943 }
1944 vm_ok +=1
1945 else:
1946 vm_result[ vm['uuid'] ] = {"vim_result": result, "description": "ok", "name":vm['name']}
1947 vm_ok +=1
1948 except vimconn.vimconnException as e:
1949 vm_result[ vm['uuid'] ] = {"vim_result": e.http_code, "name":vm['name'], "description": str(e)}
1950 vm_error+=1
1951
1952 if vm_ok==0: #all goes wrong
1953 return 1, vm_result
1954 else:
1955 return 1, vm_result
1956
1957 def create_or_use_console_proxy_thread(console_server, console_port):
1958 #look for a non-used port
1959 console_thread_key = console_server + ":" + str(console_port)
1960 if console_thread_key in global_config["console_thread"]:
1961 #global_config["console_thread"][console_thread_key].start_timeout()
1962 return 1, global_config["console_thread"][console_thread_key]
1963
1964 for port in global_config["console_port_iterator"]():
1965 print "create_or_use_console_proxy_thread() port:", port
1966 if port in global_config["console_ports"]:
1967 continue
1968 try:
1969 clithread = cli.ConsoleProxyThread(global_config['http_host'], port, console_server, console_port)
1970 clithread.start()
1971 global_config["console_thread"][console_thread_key] = clithread
1972 global_config["console_ports"][port] = console_thread_key
1973 return 1, clithread
1974 except cli.ConsoleProxyExceptionPortUsed as e:
1975 #port used, try with onoher
1976 continue
1977 except cli.ConsoleProxyException as e:
1978 return -1, str(e)
1979 return -1, "Not found any free 'http_console_ports'"
1980
1981 def check_tenant(mydb, tenant_id):
1982 '''check that tenant exists at database'''
1983 result, _ = mydb.get_table(FROM='nfvo_tenants', SELECT=('uuid',), WHERE={'uuid': tenant_id})
1984 if result<=0: return False
1985 return True
1986
1987 def new_tenant(mydb, tenant_dict):
1988 result, tenant_id = mydb.new_row("nfvo_tenants", tenant_dict, None, add_uuid=True, log=True)
1989 if result < 0:
1990 return result, tenant_id
1991 return 200,tenant_id
1992
1993 def delete_tenant(mydb, tenant):
1994 #get nfvo_tenant info
1995 result,tenant_dict = mydb.get_table_by_uuid_name('nfvo_tenants', tenant, 'tenant')
1996 if result < 0:
1997 return result, tenant_dict
1998
1999 result, tenant_id = mydb.delete_row("nfvo_tenants", tenant_dict['uuid'], None)
2000 if result < 0:
2001 return result, tenant_id
2002 return 200, tenant_dict['uuid']
2003
2004 def new_datacenter(mydb, datacenter_descriptor):
2005 if "config" in datacenter_descriptor:
2006 datacenter_descriptor["config"]=yaml.safe_dump(datacenter_descriptor["config"],default_flow_style=True,width=256)
2007 result, datacenter_id = mydb.new_row("datacenters", datacenter_descriptor, None, add_uuid=True, log=True)
2008 if result < 0:
2009 return result, datacenter_id
2010 return 200,datacenter_id
2011
2012 def edit_datacenter(mydb, datacenter_id_name, datacenter_descriptor):
2013 #obtain data, check that only one exist
2014 result, content = mydb.get_table_by_uuid_name('datacenters', datacenter_id_name)
2015 if result < 0:
2016 return result, content
2017 #edit data
2018 datacenter_id = content['uuid']
2019 where={'uuid': content['uuid']}
2020 if "config" in datacenter_descriptor:
2021 if datacenter_descriptor['config']!=None:
2022 try:
2023 new_config_dict = datacenter_descriptor["config"]
2024 #delete null fields
2025 to_delete=[]
2026 for k in new_config_dict:
2027 if new_config_dict[k]==None:
2028 to_delete.append(k)
2029
2030 config_dict = yaml.load(content["config"])
2031 config_dict.update(new_config_dict)
2032 #delete null fields
2033 for k in to_delete:
2034 del config_dict[k]
2035 except Exception,e:
2036 return -HTTP_Bad_Request, "Bad format at datacenter:config " + str(e)
2037 datacenter_descriptor["config"]= yaml.safe_dump(config_dict,default_flow_style=True,width=256) if len(config_dict)>0 else None
2038 result, content = mydb.update_rows('datacenters', datacenter_descriptor, where)
2039 if result < 0:
2040 return result, datacenter_id
2041 return 200, datacenter_id
2042
2043 def delete_datacenter(mydb, datacenter):
2044 #get nfvo_tenant info
2045 result,datacenter_dict = mydb.get_table_by_uuid_name('datacenters', datacenter, 'datacenter')
2046 if result < 0:
2047 return result, datacenter_dict
2048
2049 result, datacenter_id = mydb.delete_row("datacenters", datacenter_dict['uuid'], None)
2050 if result < 0:
2051 return result, datacenter_id
2052 return 200, datacenter_dict['uuid']
2053
2054 def associate_datacenter_to_tenant(mydb, nfvo_tenant, datacenter, vim_tenant_id=None, vim_tenant_name=None, vim_username=None, vim_password=None):
2055 #get datacenter info
2056 if utils.check_valid_uuid(datacenter):
2057 result, vims = get_vim(mydb, datacenter_id=datacenter)
2058 else:
2059 result, vims = get_vim(mydb, datacenter_name=datacenter)
2060 if result < 0:
2061 print "nfvo.associate_datacenter_to_tenant() error. Datacenter not found"
2062 return result, vims
2063 elif result == 0:
2064 return -HTTP_Not_Found, "datacenter '%s' not found" % str(datacenter)
2065 elif result>1:
2066 print "nfvo.associate_datacenter_to_tenant() error. Several datacenters found"
2067 #print result, vims
2068 return -HTTP_Conflict, "More than one datacenters found, try to identify with uuid"
2069 datacenter_id=vims.keys()[0]
2070 myvim=vims[datacenter_id]
2071 datacenter_name=myvim["name"]
2072
2073 create_vim_tenant=True if vim_tenant_id==None and vim_tenant_name==None else False
2074
2075 #get nfvo_tenant info
2076 result,tenant_dict = mydb.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant)
2077 if result < 0:
2078 return result, tenant_dict
2079 if vim_tenant_name==None:
2080 vim_tenant_name=tenant_dict['name']
2081
2082 #check that this association does not exist before
2083 tenants_datacenter_dict={"nfvo_tenant_id":tenant_dict['uuid'], "datacenter_id":datacenter_id }
2084 result,content = mydb.get_table(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict)
2085 if result>0:
2086 return -HTTP_Conflict, "datacenter %s and tenant %s are already attached" %(datacenter_id, tenant_dict['uuid'])
2087 elif result<0:
2088 return result, content
2089
2090 vim_tenant_id_exist_atdb=False
2091 if not create_vim_tenant:
2092 where_={"datacenter_id": datacenter_id}
2093 if vim_tenant_id!=None:
2094 where_["vim_tenant_id"] = vim_tenant_id
2095 if vim_tenant_name!=None:
2096 where_["vim_tenant_name"] = vim_tenant_name
2097 #check if vim_tenant_id is already at database
2098 result,datacenter_tenants_dict = mydb.get_table(FROM='datacenter_tenants', WHERE=where_)
2099 if result < 0:
2100 return result, datacenter_tenants_dict
2101 elif result>=1:
2102 datacenter_tenants_dict = datacenter_tenants_dict[0]
2103 vim_tenant_id_exist_atdb=True
2104 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2105 else: #result=0
2106 datacenter_tenants_dict = {}
2107 #insert at table datacenter_tenants
2108 else: #if vim_tenant_id==None:
2109 #create tenant at VIM if not provided
2110 try:
2111 vim_tenant_id = myvim.new_tenant(vim_tenant_name, "created by openmano for datacenter "+datacenter_name)
2112 except vimconn.vimconnException as e:
2113 return -HTTP_Internal_Server_Error, "Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id, str(e))
2114 datacenter_tenants_dict = {}
2115 datacenter_tenants_dict["created"]="true"
2116
2117 #fill datacenter_tenants table
2118 if not vim_tenant_id_exist_atdb:
2119 datacenter_tenants_dict["vim_tenant_id"] = vim_tenant_id
2120 datacenter_tenants_dict["vim_tenant_name"] = vim_tenant_name
2121 datacenter_tenants_dict["user"] = vim_username
2122 datacenter_tenants_dict["passwd"] = vim_password
2123 datacenter_tenants_dict["datacenter_id"] = datacenter_id
2124 res,id_ = mydb.new_row('datacenter_tenants', datacenter_tenants_dict, tenant_dict['uuid'], True, True)
2125 if res<1:
2126 return -HTTP_Bad_Request, "Not possible to add %s to database datacenter_tenants table %s " %(vim_tenant_id, id_)
2127 datacenter_tenants_dict["uuid"] = id_
2128
2129 #fill tenants_datacenters table
2130 tenants_datacenter_dict["datacenter_tenant_id"]=datacenter_tenants_dict["uuid"]
2131 res,id_ = mydb.new_row('tenants_datacenters', tenants_datacenter_dict, tenant_dict['uuid'], False, True)
2132 if res<1:
2133 return -HTTP_Bad_Request, "Not possible to create an entry at database table datacenter_tenants: " + id_
2134 return 200, datacenter_id
2135
2136 def deassociate_datacenter_to_tenant(mydb, tenant_id, datacenter, vim_tenant_id=None):
2137 #get datacenter info
2138 if utils.check_valid_uuid(datacenter):
2139 result, vims = get_vim(mydb, datacenter_id=datacenter)
2140 else:
2141 result, vims = get_vim(mydb, datacenter_name=datacenter)
2142 if result < 0:
2143 print "nfvo.deassociate_datacenter_to_tenant() error. Datacenter not found"
2144 return result, vims
2145 elif result == 0:
2146 return -HTTP_Not_Found, "datacenter '%s' not found" % str(datacenter)
2147 elif result>1:
2148 print "nfvo.deassociate_datacenter_to_tenant() error. Several datacenters found"
2149 return -HTTP_Conflict, "More than one datacenters found, try to identify with uuid"
2150 datacenter_id=vims.keys()[0]
2151 myvim=vims[datacenter_id]
2152
2153 #get nfvo_tenant info
2154 if not tenant_id or tenant_id=="any":
2155 tenant_uuid = None
2156 else:
2157 result,tenant_dict = mydb.get_table_by_uuid_name('nfvo_tenants', tenant_id)
2158 if result < 0:
2159 return result, tenant_dict
2160 tenant_uuid = tenant_dict['uuid']
2161
2162 #check that this association exist before
2163 tenants_datacenter_dict={"datacenter_id":datacenter_id }
2164 if tenant_uuid:
2165 tenants_datacenter_dict["nfvo_tenant_id"] = tenant_uuid
2166 result,tenant_datacenter_list = mydb.get_table(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict)
2167 if result==0 and tenant_uuid:
2168 return -HTTP_Not_Found, "datacenter %s and tenant %s are not attached" %(datacenter_id, tenant_dict['uuid'])
2169 elif result<0:
2170 return result, tenant_datacenter_list
2171
2172 #delete this association
2173 result,data = mydb.delete_row_by_dict(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict)
2174 if result<0:
2175 return result,data
2176
2177 #get vim_tenant info and deletes
2178 warning=''
2179 for tenant_datacenter_item in tenant_datacenter_list:
2180 result,vim_tenant_dict = mydb.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item['datacenter_tenant_id'])
2181 if result > 0:
2182 #try to delete vim:tenant
2183 result,data = mydb.delete_row('datacenter_tenants', tenant_datacenter_item['datacenter_tenant_id'], tenant_uuid)
2184 if result<0:
2185 pass #the error will be caused because dependencies, vim_tenant can not be deleted
2186 elif vim_tenant_dict['created']=='true':
2187 #delete tenant at VIM if created by NFVO
2188 try:
2189 myvim.delete_tenant(vim_tenant_dict['vim_tenant_id'])
2190 except vimconn.vimconnException as e:
2191 warning = "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict['vim_tenant_id'], str(e))
2192 logger.warn(warning)
2193
2194 return 200, "datacenter %s detached.%s" %(datacenter_id, warning)
2195
2196 def datacenter_action(mydb, tenant_id, datacenter, action_dict):
2197 #DEPRECATED
2198 #get datacenter info
2199 if utils.check_valid_uuid(datacenter):
2200 result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter)
2201 else:
2202 result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter)
2203 if result < 0:
2204 logger.error("nfvo.datacenter_action() error. Datacenter not found")
2205 return result, vims
2206 elif result == 0:
2207 return -HTTP_Not_Found, "datacenter '%s' not found" % str(datacenter)
2208 elif result>1:
2209 logger.error("nfvo.datacenter_action() error. Several datacenters found")
2210 return -HTTP_Conflict, "More than one datacenters found, try to identify with uuid"
2211 datacenter_id=vims.keys()[0]
2212 myvim=vims[datacenter_id]
2213
2214 if 'net-update' in action_dict:
2215 try:
2216 content = myvim.get_network_list(filter_dict={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2217 #print content
2218 except vimconn.vimconnException as e:
2219 logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
2220 return -HTTP_Internal_Server_Error, str(e)
2221 #update nets Change from VIM format to NFVO format
2222 net_list=[]
2223 for net in content:
2224 net_nfvo={'datacenter_id': datacenter_id}
2225 net_nfvo['name'] = net['name']
2226 #net_nfvo['description']= net['name']
2227 net_nfvo['vim_net_id'] = net['id']
2228 net_nfvo['type'] = net['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2229 net_nfvo['shared'] = net['shared']
2230 net_nfvo['multipoint'] = False if net['type']=='ptp' else True
2231 net_list.append(net_nfvo)
2232 result, content = mydb.update_datacenter_nets(datacenter_id, net_list)
2233 if result < 0:
2234 return -HTTP_Internal_Server_Error, content
2235 logger.info("Inserted %d nets, deleted %d old nets", result, content)
2236
2237 return 200, result
2238 elif 'net-edit' in action_dict:
2239 net = action_dict['net-edit'].pop('net')
2240 what = 'vim_net_id' if utils.check_valid_uuid(net) else 'name'
2241 result, content = mydb.update_rows('datacenter_nets', action_dict['net-edit'],
2242 WHERE={'datacenter_id':datacenter_id, what: net})
2243 return result, content
2244 elif 'net-delete' in action_dict:
2245 net = action_dict['net-deelte'].get('net')
2246 what = 'vim_net_id' if utils.check_valid_uuid(net) else 'name'
2247 result, content = mydb.delete_row_by_dict(FROM='datacenter_nets',
2248 WHERE={'datacenter_id':datacenter_id, what: net})
2249 return result, content
2250
2251 else:
2252 return -HTTP_Bad_Request, "Unknown action " + str(action_dict)
2253
2254 def datacenter_edit_netmap(mydb, tenant_id, datacenter, netmap, action_dict):
2255 #get datacenter info
2256 if utils.check_valid_uuid(datacenter):
2257 result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter)
2258 else:
2259 result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter)
2260 if result < 0:
2261 print "nfvo.datacenter_action() error. Datacenter not found"
2262 return result, vims
2263 elif result == 0:
2264 return -HTTP_Not_Found, "datacenter '%s' not found" % str(datacenter)
2265 elif result>1:
2266 print "nfvo.datacenter_action() error. Several datacenters found"
2267 return -HTTP_Conflict, "More than one datacenters found, try to identify with uuid"
2268 datacenter_id=vims.keys()[0]
2269
2270 what = 'uuid' if utils.check_valid_uuid(netmap) else 'name'
2271 result, content = mydb.update_rows('datacenter_nets', action_dict['netmap'],
2272 WHERE={'datacenter_id':datacenter_id, what: netmap})
2273 return result, content
2274
2275 def datacenter_new_netmap(mydb, tenant_id, datacenter, action_dict=None):
2276 #get datacenter info
2277 if utils.check_valid_uuid(datacenter):
2278 result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter)
2279 else:
2280 result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter)
2281 if result < 0:
2282 logger.error("nfvo.datacenter_new_netmap() error. Datacenter not found")
2283 return result, vims
2284 elif result == 0:
2285 return -HTTP_Not_Found, "datacenter '%s' not found" % str(datacenter)
2286 elif result>1:
2287 logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2288 return -HTTP_Conflict, "More than one datacenters found, try to identify with uuid"
2289 datacenter_id=vims.keys()[0]
2290 myvim=vims[datacenter_id]
2291 filter_dict={}
2292 if action_dict:
2293 action_dict = action_dict["netmap"]
2294 if 'vim_id' in action_dict:
2295 filter_dict["id"] = action_dict['vim_id']
2296 if 'vim_name' in action_dict:
2297 filter_dict["name"] = action_dict['vim_name']
2298 else:
2299 filter_dict["shared"] = True
2300
2301 try:
2302 content = myvim.get_network_list(filter_dict=filter_dict)
2303 except vimconn.vimconnException as e:
2304 logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
2305 return -HTTP_Internal_Server_Error, str(e)
2306 if len(content)>1 and action_dict:
2307 return -HTTP_Conflict, "more than two networks found, specify with vim_id"
2308 elif len(content)==0: # and action_dict:
2309 return -HTTP_Not_Found, "Not found a network at VIM with " + str(filter_dict)
2310 net_list=[]
2311 for net in content:
2312 net_nfvo={'datacenter_id': datacenter_id}
2313 if action_dict and "name" in action_dict:
2314 net_nfvo['name'] = action_dict['name']
2315 else:
2316 net_nfvo['name'] = net['name']
2317 #net_nfvo['description']= net['name']
2318 net_nfvo['vim_net_id'] = net['id']
2319 net_nfvo['type'] = net['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2320 net_nfvo['shared'] = net['shared']
2321 net_nfvo['multipoint'] = False if net['type']=='ptp' else True
2322 result, content = mydb.new_row("datacenter_nets", net_nfvo, add_uuid=True)
2323 if action_dict and result < 0 :
2324 return result, content
2325 if result < 0:
2326 net_nfvo["status"] = "FAIL: " + content
2327 else:
2328 net_nfvo["status"] = "OK"
2329 net_nfvo["uuid"] = content
2330 net_list.append(net_nfvo)
2331 return 200, net_list
2332
2333 def vim_action_get(mydb, tenant_id, datacenter, item, name):
2334 #get datacenter info
2335 if utils.check_valid_uuid(datacenter):
2336 result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter)
2337 else:
2338 result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter)
2339 if result < 0:
2340 print "nfvo.datacenter_action() error. Datacenter not found"
2341 return result, vims
2342 elif result == 0:
2343 return -HTTP_Not_Found, "datacenter '%s' not found" % str(datacenter)
2344 elif result>1:
2345 print "nfvo.datacenter_action() error. Several datacenters found"
2346 return -HTTP_Conflict, "More than one datacenters found, try to identify with uuid"
2347 datacenter_id=vims.keys()[0]
2348 myvim=vims[datacenter_id]
2349 filter_dict={}
2350 if name:
2351 if utils.check_valid_uuid(name):
2352 filter_dict["id"] = name
2353 else:
2354 filter_dict["name"] = name
2355 try:
2356 if item=="networks":
2357 #filter_dict['tenant_id'] = myvim['tenant_id']
2358 content = myvim.get_network_list(filter_dict=filter_dict)
2359 elif item=="tenants":
2360 content = myvim.get_tenant_list(filter_dict=filter_dict)
2361 else:
2362 return -HTTP_Method_Not_Allowed, item + "?"
2363 print "vim_action response ", content #update nets Change from VIM format to NFVO format
2364 if name and len(content)==1:
2365 return 200, {item[:-1]: content[0]}
2366 elif name and len(content)==0:
2367 return -HTTP_Not_Found, "No %s found with %s" % (item[:-1], " and ".join(map(lambda x: str(x[0])+": "+str(x[1]), filter_dict.iteritems())))
2368 else:
2369 return 200, {item: content}
2370 except vimconn.vimconnException as e:
2371 print "vim_action Not possible to get_%s_list from VIM: %s " % (item, str(e))
2372 return -e.http_code, "Not possible to get_{}_list from VIM: {}".format(item, str(e))
2373
2374 def vim_action_delete(mydb, tenant_id, datacenter, item, name):
2375 #get datacenter info
2376 if tenant_id == "any":
2377 tenant_id=None
2378
2379 if utils.check_valid_uuid(datacenter):
2380 result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter)
2381 else:
2382 result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter)
2383 if result < 0:
2384 print "nfvo.datacenter_action() error. Datacenter not found"
2385 return result, vims
2386 elif result == 0:
2387 return -HTTP_Not_Found, "datacenter '%s' not found" % str(datacenter)
2388 elif result>1:
2389 print "nfvo.datacenter_action() error. Several datacenters found"
2390 return -HTTP_Conflict, "More than one datacenters found, try to identify with uuid"
2391 datacenter_id=vims.keys()[0]
2392 myvim=vims[datacenter_id]
2393 #get uuid name
2394 result, content = vim_action_get(mydb, tenant_id, datacenter, item, name)
2395 print content
2396 if result < 0:
2397 return result, content
2398 items = content.values()[0]
2399 if type(items)==list and len(items)==0:
2400 return -HTTP_Not_Found, "Not found " + item
2401 elif type(items)==list and len(items)>1:
2402 return -HTTP_Not_Found, "Found more than one %s with this name. Use uuid." % item
2403 else: # it is a dict
2404 item_id = items["id"]
2405 item_name = str(items.get("name"))
2406
2407 try:
2408 if item=="networks":
2409 content = myvim.delete_network(item_id)
2410 elif item=="tenants":
2411 content = myvim.delete_tenant(item_id)
2412 else:
2413 return -HTTP_Method_Not_Allowed, item + "?"
2414 except vimconn.vimconnException as e:
2415 print "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e))
2416 return -e.http_code, "Not possible to delete_{} {} from VIM: {}".format(item, name, str(e))
2417
2418 if result < 0:
2419 print "vim_action Not possible to delete %s %s from VIM: %s " % (item, name, content)
2420 return result, content
2421 return 200, "{} {} {} deleted".format(item[:-1], item_id,item_name)
2422
2423 def vim_action_create(mydb, tenant_id, datacenter, item, descriptor):
2424 #get datacenter info
2425 print "vim_action_create descriptor", descriptor
2426 if tenant_id == "any":
2427 tenant_id=None
2428
2429 if utils.check_valid_uuid(datacenter):
2430 result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter)
2431 else:
2432 result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter)
2433 if result < 0:
2434 print "nfvo.datacenter_action() error. Datacenter not found"
2435 return result, vims
2436 elif result == 0:
2437 return -HTTP_Not_Found, "datacenter '%s' not found" % str(datacenter)
2438 elif result>1:
2439 print "nfvo.datacenter_action() error. Several datacenters found"
2440 return -HTTP_Conflict, "More than one datacenters found, try to identify with uuid"
2441 datacenter_id=vims.keys()[0]
2442 myvim=vims[datacenter_id]
2443
2444 try:
2445 if item=="networks":
2446 net = descriptor["network"]
2447 net_name = net.pop("name")
2448 net_type = net.pop("type", "bridge")
2449 net_public=net.pop("shared", False)
2450 content = myvim.new_network(net_name, net_type, net_public, **net)
2451 elif item=="tenants":
2452 tenant = descriptor["tenant"]
2453 content = myvim.new_tenant(tenant["name"], tenant.get("description"))
2454 else:
2455 return -HTTP_Method_Not_Allowed, item + "?"
2456 except vimconn.vimconnException as e:
2457 print "vim_action Not possible to create {} at VIM: {} ".format(item, str(e))
2458 return -e.http_code, "Not possible to create {} at VIM: {}".format(item, str(e))
2459
2460 return vim_action_get(mydb, tenant_id, datacenter, item, content)
2461
2462