1 # -*- coding: utf-8 -*-
4 # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
5 # This file is part of openmano
8 # Licensed under the Apache License, Version 2.0 (the "License"); you may
9 # not use this file except in compliance with the License. You may obtain
10 # a copy of the License at
12 # http://www.apache.org/licenses/LICENSE-2.0
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17 # License for the specific language governing permissions and limitations
20 # For those usages not covered by the Apache License, Version 2.0 please
21 # contact with: nfvlabs@tid.es
25 NFVO engine, implementing all the methods for the creation, deletion and management of vnfs, scenarios and instances
27 __author__
="Alfonso Tierno, Gerardo Garcia, Pablo Montes"
28 __date__
="$16-sep-2014 22:05:01$"
35 from db_base
import HTTP_Unauthorized
, HTTP_Bad_Request
, HTTP_Internal_Server_Error
, HTTP_Not_Found
,\
36 HTTP_Conflict
, HTTP_Method_Not_Allowed
37 import console_proxy_thread
as cli
42 from uuid
import uuid4
43 from db_base
import db_base_Exception
46 from threading
import Lock
48 from lib_osm_openvim
import ovim
as ovim_module
49 from lib_osm_openvim
.ovim
import ovimException
50 from Crypto
.PublicKey
import RSA
52 import osm_im
.vnfd
as vnfd_catalog
53 import osm_im
.nsd
as nsd_catalog
54 from pyangbind
.lib
.serialise
import pybindJSONDecoder
55 from itertools
import chain
58 global vimconn_imported
60 global default_volume_size
61 default_volume_size
= '5' #size in GB
66 vimconn_imported
= {} # dictionary with VIM type as key, loaded module as value
67 vim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-VIMs
68 vim_persistent_info
= {}
69 logger
= logging
.getLogger('openmano.nfvo')
75 class NfvoException(Exception):
76 def __init__(self
, message
, http_code
):
77 self
.http_code
= http_code
78 Exception.__init
__(self
, message
)
84 if task_id
<= last_task_id
:
85 task_id
= last_task_id
+ 0.000001
86 last_task_id
= task_id
87 return "ACTION-{:.6f}".format(task_id
)
88 # return (t.strftime("%Y%m%dT%H%M%S.{}%Z", t.localtime(task_id))).format(int((task_id % 1)*1e6))
91 def new_task(name
, params
, depends
=None):
93 task_id
= get_task_id()
94 task
= {"status": "enqueued", "id": task_id
, "name": name
, "params": params
}
96 task
["depends"] = depends
101 return True if id[:5] == "TASK-" else False
104 def get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_name
, tenant_id
):
105 name
= datacenter_name
[:16]
106 if name
not in vim_threads
["names"]:
107 vim_threads
["names"].append(name
)
109 name
= datacenter_name
[:16] + "." + tenant_name
[:16]
110 if name
not in vim_threads
["names"]:
111 vim_threads
["names"].append(name
)
113 name
= datacenter_id
+ "-" + tenant_id
114 vim_threads
["names"].append(name
)
118 def start_service(mydb
):
119 global db
, global_config
120 db
= nfvo_db
.nfvo_db()
121 db
.connect(global_config
['db_host'], global_config
['db_user'], global_config
['db_passwd'], global_config
['db_name'])
124 # Initialize openvim for SDN control
125 # TODO: Avoid static configuration by adding new parameters to openmanod.cfg
126 # TODO: review ovim.py to delete not needed configuration
127 ovim_configuration
= {
128 'logger_name': 'openmano.ovim',
129 'network_vlan_range_start': 1000,
130 'network_vlan_range_end': 4096,
131 'db_name': global_config
["db_ovim_name"],
132 'db_host': global_config
["db_ovim_host"],
133 'db_user': global_config
["db_ovim_user"],
134 'db_passwd': global_config
["db_ovim_passwd"],
137 'network_type': 'bridge',
138 #TODO: log_level_of should not be needed. To be modified in ovim
139 'log_level_of': 'DEBUG'
142 # starts ovim library
143 ovim
= ovim_module
.ovim(ovim_configuration
)
146 #delete old unneeded vim_actions
150 from_
= 'tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join '\
151 'datacenter_tenants as dt on td.datacenter_tenant_id=dt.uuid'
152 select_
= ('type', 'd.config as config', 'd.uuid as datacenter_id', 'vim_url', 'vim_url_admin',
153 'd.name as datacenter_name', 'dt.uuid as datacenter_tenant_id',
154 'dt.vim_tenant_name as vim_tenant_name', 'dt.vim_tenant_id as vim_tenant_id',
155 'user', 'passwd', 'dt.config as dt_config', 'nfvo_tenant_id')
156 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
)
158 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
159 'datacenter_id': vim
.get('datacenter_id')}
161 extra
.update(yaml
.load(vim
["config"]))
162 if vim
.get('dt_config'):
163 extra
.update(yaml
.load(vim
["dt_config"]))
164 if vim
["type"] not in vimconn_imported
:
167 module
= "vimconn_" + vim
["type"]
168 pkg
= __import__("osm_ro." + module
)
169 vim_conn
= getattr(pkg
, module
)
170 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
171 # vim_conn = imp.load_module(vim["type"], *module_info)
172 vimconn_imported
[vim
["type"]] = vim_conn
173 except (IOError, ImportError) as e
:
174 # if module_info and module_info[0]:
175 # file.close(module_info[0])
176 raise NfvoException("Unknown vim type '{}'. Cannot open file '{}.py'; {}: {}".format(
177 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
179 thread_id
= vim
['datacenter_tenant_id']
180 vim_persistent_info
[thread_id
] = {}
183 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
184 myvim
= vimconn_imported
[ vim
["type"] ].vimconnector(
185 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
186 tenant_id
=vim
['vim_tenant_id'], tenant_name
=vim
['vim_tenant_name'],
187 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
188 user
=vim
['user'], passwd
=vim
['passwd'],
189 config
=extra
, persistent_info
=vim_persistent_info
[thread_id
]
191 except vimconn
.vimconnException
as e
:
193 logger
.error("Cannot launch thread for VIM {} '{}': {}".format(vim
['datacenter_name'],
194 vim
['datacenter_id'], e
))
195 except Exception as e
:
196 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, e
),
197 HTTP_Internal_Server_Error
)
198 thread_name
= get_non_used_vim_name(vim
['datacenter_name'], vim
['vim_tenant_id'], vim
['vim_tenant_name'],
199 vim
['vim_tenant_id'])
200 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, vim
['datacenter_name'],
201 vim
['datacenter_tenant_id'], db
=db
, db_lock
=db_lock
, ovim
=ovim
)
203 vim_threads
["running"][thread_id
] = new_thread
204 except db_base_Exception
as e
:
205 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
206 except ovim_module
.ovimException
as e
:
208 if message
[:22] == "DATABASE wrong version":
209 message
= "DATABASE wrong version of lib_osm_openvim {msg} -d{dbname} -u{dbuser} -p{dbpass} {ver}' "\
210 "at host {dbhost}".format(
211 msg
=message
[22:-3], dbname
=global_config
["db_ovim_name"],
212 dbuser
=global_config
["db_ovim_user"], dbpass
=global_config
["db_ovim_passwd"],
213 ver
=message
[-3:-1], dbhost
=global_config
["db_ovim_host"])
214 raise NfvoException(message
, HTTP_Bad_Request
)
218 global ovim
, global_config
221 for thread_id
,thread
in vim_threads
["running"].items():
222 thread
.insert_task("exit")
223 vim_threads
["deleting"][thread_id
] = thread
224 vim_threads
["running"] = {}
225 if global_config
and global_config
.get("console_thread"):
226 for thread
in global_config
["console_thread"]:
227 thread
.terminate
= True
230 return ("openmanod version {} {}\n(c) Copyright Telefonica".format(global_config
["version"],
231 global_config
["version_date"] ))
235 Clean unused or old entries at database to avoid unlimited growing
236 :param mydb: database connector
239 # get and delete unused vim_actions: all elements deleted, one week before, instance not present
240 now
= t
.time()-3600*24*7
241 instance_action_id
= None
244 actions_to_delete
= mydb
.get_rows(
245 SELECT
=("item", "item_id", "instance_action_id"),
246 FROM
="vim_actions as va join instance_actions as ia on va.instance_action_id=ia.uuid "
247 "left join instance_scenarios as i on ia.instance_id=i.uuid",
248 WHERE
={"va.action": "DELETE", "va.modified_at<": now
, "i.uuid": None,
249 "va.status": ("DONE", "SUPERSEDED")},
252 for to_delete
in actions_to_delete
:
253 mydb
.delete_row(FROM
="vim_actions", WHERE
=to_delete
)
254 if instance_action_id
!= to_delete
["instance_action_id"]:
255 instance_action_id
= to_delete
["instance_action_id"]
256 mydb
.delete_row(FROM
="instance_actions", WHERE
={"uuid": instance_action_id
})
257 nb_deleted
+= len(actions_to_delete
)
258 if len(actions_to_delete
) < 100:
261 logger
.debug("Removed {} unused vim_actions".format(nb_deleted
))
265 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
267 return result, content:
268 <0, error_text upon error
269 nb_records, flavor_list on success
272 WHERE_dict
['vnf_id'] = vnf_id
273 if nfvo_tenant
is not None:
274 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
276 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
277 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
278 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
279 #print "get_flavor_list result:", result
280 #print "get_flavor_list content:", content
282 for flavor
in flavors
:
283 flavorList
.append(flavor
['flavor_id'])
287 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
289 return result, content:
290 <0, error_text upon error
291 nb_records, flavor_list on success
294 WHERE_dict
['vnf_id'] = vnf_id
295 if nfvo_tenant
is not None:
296 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
298 #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
299 images
= mydb
.get_rows(FROM
='vms join images on vms.image_id=images.uuid',SELECT
=('image_id',),WHERE
=WHERE_dict
)
302 imageList
.append(image
['image_id'])
306 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
307 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None):
308 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
309 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
310 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
311 raise exception upon error
314 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
315 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
316 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
317 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
318 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
319 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
320 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
321 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'
322 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
323 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
324 'user','passwd', 'dt.config as dt_config')
326 from_
= 'datacenters as d'
327 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
329 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
332 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
333 'datacenter_id': vim
.get('datacenter_id')}
335 extra
.update(yaml
.load(vim
["config"]))
336 if vim
.get('dt_config'):
337 extra
.update(yaml
.load(vim
["dt_config"]))
338 if vim
["type"] not in vimconn_imported
:
341 module
= "vimconn_" + vim
["type"]
342 pkg
= __import__("osm_ro." + module
)
343 vim_conn
= getattr(pkg
, module
)
344 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
345 # vim_conn = imp.load_module(vim["type"], *module_info)
346 vimconn_imported
[vim
["type"]] = vim_conn
347 except (IOError, ImportError) as e
:
348 # if module_info and module_info[0]:
349 # file.close(module_info[0])
350 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
351 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
354 if 'datacenter_tenant_id' in vim
:
355 thread_id
= vim
["datacenter_tenant_id"]
356 if thread_id
not in vim_persistent_info
:
357 vim_persistent_info
[thread_id
] = {}
358 persistent_info
= vim_persistent_info
[thread_id
]
362 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
363 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
364 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
365 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
),
366 tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
367 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
368 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
369 config
=extra
, persistent_info
=persistent_info
371 except Exception as e
:
372 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
374 except db_base_Exception
as e
:
375 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
378 def rollback(mydb
, vims
, rollback_list
):
380 #delete things by reverse order
381 for i
in range(len(rollback_list
)-1, -1, -1):
382 item
= rollback_list
[i
]
383 if item
["where"]=="vim":
384 if item
["vim_id"] not in vims
:
386 if is_task_id(item
["uuid"]):
388 vim
= vims
[item
["vim_id"]]
390 if item
["what"]=="image":
391 vim
.delete_image(item
["uuid"])
392 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_vim_id": vim
["id"], "vim_id":item
["uuid"]})
393 elif item
["what"]=="flavor":
394 vim
.delete_flavor(item
["uuid"])
395 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
396 elif item
["what"]=="network":
397 vim
.delete_network(item
["uuid"])
398 elif item
["what"]=="vm":
399 vim
.delete_vminstance(item
["uuid"])
400 except vimconn
.vimconnException
as e
:
401 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
402 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
403 except db_base_Exception
as e
:
404 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
408 if item
["what"]=="image":
409 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
410 elif item
["what"]=="flavor":
411 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
412 except db_base_Exception
as e
:
413 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
414 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
415 if len(undeleted_items
)==0:
416 return True," Rollback successful."
418 return False," Rollback fails to delete: " + str(undeleted_items
)
421 def check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1):
423 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
425 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
427 #dataplane interfaces
428 for numa
in vnfc
.get("numas",() ):
429 for interface
in numa
.get("interfaces",()):
430 if interface
["name"] in name_dict
:
432 "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
433 vnfc
["name"], interface
["name"]),
435 name_dict
[ interface
["name"] ] = "underlay"
437 for interface
in vnfc
.get("bridge-ifaces",() ):
438 if interface
["name"] in name_dict
:
440 "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
441 vnfc
["name"], interface
["name"]),
443 name_dict
[ interface
["name"] ] = "overlay"
444 vnfc_interfaces
[ vnfc
["name"] ] = name_dict
445 # check bood-data info
446 # if "boot-data" in vnfc:
447 # # check that user-data is incompatible with users and config-files
448 # if (vnfc["boot-data"].get("users") or vnfc["boot-data"].get("config-files")) and vnfc["boot-data"].get("user-data"):
449 # raise NfvoException(
450 # "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
453 #check if the info in external_connections matches with the one in the vnfcs
455 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
456 if external_connection
["name"] in name_list
:
458 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
459 external_connection
["name"]),
461 name_list
.append(external_connection
["name"])
462 if external_connection
["VNFC"] not in vnfc_interfaces
:
464 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
465 external_connection
["name"], external_connection
["VNFC"]),
468 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
470 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
471 external_connection
["name"],
472 external_connection
["local_iface_name"]),
475 #check if the info in internal_connections matches with the one in the vnfcs
477 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
478 if internal_connection
["name"] in name_list
:
480 "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection".format(
481 internal_connection
["name"]),
483 name_list
.append(internal_connection
["name"])
484 #We should check that internal-connections of type "ptp" have only 2 elements
486 if len(internal_connection
["elements"])>2 and (internal_connection
.get("type") == "ptp" or internal_connection
.get("type") == "e-line"):
488 "Error at 'vnf:internal-connections[name:'{}']:elements', size must be 2 for a '{}' type. Consider change it to '{}' type".format(
489 internal_connection
["name"],
490 'ptp' if vnf_descriptor_version
==1 else 'e-line',
491 'data' if vnf_descriptor_version
==1 else "e-lan"),
493 for port
in internal_connection
["elements"]:
495 iface
= port
["local_iface_name"]
496 if vnf
not in vnfc_interfaces
:
498 "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
499 internal_connection
["name"], vnf
),
501 if iface
not in vnfc_interfaces
[ vnf
]:
503 "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
504 internal_connection
["name"], iface
),
506 return -HTTP_Bad_Request
,
507 if vnf_descriptor_version
==1 and "type" not in internal_connection
:
508 if vnfc_interfaces
[vnf
][iface
] == "overlay":
509 internal_connection
["type"] = "bridge"
511 internal_connection
["type"] = "data"
512 if vnf_descriptor_version
==2 and "implementation" not in internal_connection
:
513 if vnfc_interfaces
[vnf
][iface
] == "overlay":
514 internal_connection
["implementation"] = "overlay"
516 internal_connection
["implementation"] = "underlay"
517 if (internal_connection
.get("type") == "data" or internal_connection
.get("type") == "ptp" or \
518 internal_connection
.get("implementation") == "underlay") and vnfc_interfaces
[vnf
][iface
] == "overlay":
520 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
521 internal_connection
["name"],
522 iface
, 'bridge' if vnf_descriptor_version
==1 else 'overlay',
523 'data' if vnf_descriptor_version
==1 else 'underlay'),
525 if (internal_connection
.get("type") == "bridge" or internal_connection
.get("implementation") == "overlay") and \
526 vnfc_interfaces
[vnf
][iface
] == "underlay":
528 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
529 internal_connection
["name"], iface
,
530 'data' if vnf_descriptor_version
==1 else 'underlay',
531 'bridge' if vnf_descriptor_version
==1 else 'overlay'),
535 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=None):
537 if only_create_at_vim
:
538 image_mano_id
= image_dict
['uuid']
539 if return_on_error
== None:
540 return_on_error
= True
542 if image_dict
['location']:
543 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
545 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
547 image_mano_id
= images
[0]['uuid']
549 #create image in MANO DB
550 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
551 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
552 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
554 #temp_image_dict['location'] = image_dict.get('new_location') if image_dict['location'] is None
555 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
556 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
557 #create image at every vim
558 for vim_id
,vim
in vims
.iteritems():
559 datacenter_vim_id
= vim
["config"]["datacenter_tenant_id"]
560 image_created
="false"
562 image_db
= mydb
.get_rows(FROM
="datacenters_images",
563 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'image_id': image_mano_id
})
564 #look at VIM if this image exist
566 if image_dict
['location'] is not None:
567 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
570 filter_dict
['name'] = image_dict
['universal_name']
571 if image_dict
.get('checksum') != None:
572 filter_dict
['checksum'] = image_dict
['checksum']
573 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
574 vim_images
= vim
.get_image_list(filter_dict
)
575 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
576 if len(vim_images
) > 1:
577 raise vimconn
.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict
)), HTTP_Conflict
)
578 elif len(vim_images
) == 0:
579 raise vimconn
.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict
)))
581 #logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
582 image_vim_id
= vim_images
[0]['id']
584 except vimconn
.vimconnNotFoundException
as e
:
585 #Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
587 #image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
588 if image_dict
['location']:
589 image_vim_id
= vim
.new_image(image_dict
)
590 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
593 #If we reach this point, then the image has image name, and optionally checksum, and could not be found
594 raise vimconn
.vimconnException(str(e
))
595 except vimconn
.vimconnException
as e
:
597 logger
.error("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
600 logger
.warn("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
602 except vimconn
.vimconnException
as e
:
604 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
606 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
609 #if we reach here, the image has been created or existed
611 #add new vim_id at datacenters_images
612 mydb
.new_row('datacenters_images', {'datacenter_vim_id': datacenter_vim_id
,
613 'image_id':image_mano_id
,
614 'vim_id': image_vim_id
,
615 'created':image_created
})
616 elif image_db
[0]["vim_id"]!=image_vim_id
:
617 #modify existing vim_id at datacenters_images
618 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_vim_id':vim_id
, 'image_id':image_mano_id
})
620 return image_vim_id
if only_create_at_vim
else image_mano_id
623 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
624 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
625 'ram':flavor_dict
.get('ram'),
626 'vcpus':flavor_dict
.get('vcpus'),
628 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
629 del flavor_dict
['extended']
630 if 'extended' in flavor_dict
:
631 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
633 #look if flavor exist
634 if only_create_at_vim
:
635 flavor_mano_id
= flavor_dict
['uuid']
636 if return_on_error
== None:
637 return_on_error
= True
639 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
641 flavor_mano_id
= flavors
[0]['uuid']
644 #create one by one the images of aditional disks
645 dev_image_list
=[] #list of images
646 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
648 for device
in flavor_dict
['extended'].get('devices',[]):
649 if "image" not in device
and "image name" not in device
:
652 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
653 image_dict
['universal_name']=device
.get('image name')
654 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
655 image_dict
['location']=device
.get('image')
656 #image_dict['new_location']=vnfc.get('image location')
657 image_dict
['checksum']=device
.get('image checksum')
658 image_metadata_dict
= device
.get('image metadata', None)
659 image_metadata_str
= None
660 if image_metadata_dict
!= None:
661 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
662 image_dict
['metadata']=image_metadata_str
663 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
664 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
665 dev_image_list
.append(image_id
)
667 temp_flavor_dict
['name'] = flavor_dict
['name']
668 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
669 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
670 flavor_mano_id
= content
671 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
672 #create flavor at every vim
673 if 'uuid' in flavor_dict
:
674 del flavor_dict
['uuid']
676 for vim_id
,vim
in vims
.items():
677 datacenter_vim_id
= vim
["config"]["datacenter_tenant_id"]
678 flavor_created
="false"
680 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors",
681 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
})
682 #look at VIM if this flavor exist SKIPPED
683 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
685 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
689 # Create the flavor in VIM
690 # Translate images at devices from MANO id to VIM id
692 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
693 # make a copy of original devices
696 for device
in flavor_dict
["extended"].get("devices",[]):
699 devices_original
.append(dev
)
700 if 'image' in device
:
702 if 'image metadata' in device
:
703 del device
['image metadata']
704 if 'image checksum' in device
:
705 del device
['image checksum']
707 for index
in range(0,len(devices_original
)) :
708 device
=devices_original
[index
]
709 if "image" not in device
and "image name" not in device
:
711 disk_list
.append({'size': device
.get('size', default_volume_size
)})
714 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
715 image_dict
['universal_name']=device
.get('image name')
716 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
717 image_dict
['location']=device
.get('image')
718 # image_dict['new_location']=device.get('image location')
719 image_dict
['checksum']=device
.get('image checksum')
720 image_metadata_dict
= device
.get('image metadata', None)
721 image_metadata_str
= None
722 if image_metadata_dict
!= None:
723 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
724 image_dict
['metadata']=image_metadata_str
725 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
726 image_dict
["uuid"]=image_mano_id
727 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
729 #save disk information (image must be based on and size
730 disk_list
.append({'image_id': image_vim_id
, 'size': device
.get('size', default_volume_size
)})
732 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
735 #check that this vim_id exist in VIM, if not create
736 flavor_vim_id
=flavor_db
[0]["vim_id"]
738 vim
.get_flavor(flavor_vim_id
)
739 continue #flavor exist
740 except vimconn
.vimconnException
:
742 #create flavor at vim
743 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
746 flavor_vim_id
=vim
.get_flavor_id_from_data(flavor_dict
)
747 flavor_create
="false"
748 except vimconn
.vimconnException
as e
:
751 if not flavor_vim_id
:
752 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
753 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
754 flavor_created
="true"
755 except vimconn
.vimconnException
as e
:
757 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
759 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
762 #if reach here the flavor has been create or exist
763 if len(flavor_db
)==0:
764 #add new vim_id at datacenters_flavors
765 extended_devices_yaml
= None
766 if len(disk_list
) > 0:
767 extended_devices
= dict()
768 extended_devices
['disks'] = disk_list
769 extended_devices_yaml
= yaml
.safe_dump(extended_devices
,default_flow_style
=True,width
=256)
770 mydb
.new_row('datacenters_flavors',
771 {'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
, 'vim_id': flavor_vim_id
,
772 'created': flavor_created
, 'extended': extended_devices_yaml
})
773 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
774 #modify existing vim_id at datacenters_flavors
775 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
},
776 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
})
778 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
781 def get_str(obj
, field
, length
):
783 Obtain the str value,
788 value
= obj
.get(field
)
789 if value
is not None:
790 value
= str(value
)[:length
]
793 def _lookfor_or_create_image(db_image
, mydb
, descriptor
):
795 fill image content at db_image dictionary. Check if the image with this image and checksum exist
796 :param db_image: dictionary to insert data
797 :param mydb: database connector
798 :param descriptor: yang descriptor
799 :return: uuid if the image exist at DB, or None if a new image must be created with the data filled at db_image
802 db_image
["name"] = get_str(descriptor
, "image", 255)
803 db_image
["checksum"] = get_str(descriptor
, "image-checksum", 32)
804 if not db_image
["checksum"]: # Ensure that if empty string, None is stored
805 db_image
["checksum"] = None
806 if db_image
["name"].startswith("/"):
807 db_image
["location"] = db_image
["name"]
808 existing_images
= mydb
.get_rows(FROM
="images", WHERE
={'location': db_image
["location"]})
810 db_image
["universal_name"] = db_image
["name"]
811 existing_images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name': db_image
['universal_name'],
812 'checksum': db_image
['checksum']})
814 return existing_images
[0]["uuid"]
816 image_uuid
= str(uuid4())
817 db_image
["uuid"] = image_uuid
820 def new_vnfd_v3(mydb
, tenant_id
, vnf_descriptor
):
822 Parses an OSM IM vnfd_catalog and insert at DB
825 :param vnf_descriptor:
826 :return: The list of cretated vnf ids
829 myvnfd
= vnfd_catalog
.vnfd()
831 pybindJSONDecoder
.load_ietf_json(vnf_descriptor
, None, None, obj
=myvnfd
)
832 except Exception as e
:
833 raise NfvoException("Error. Invalid VNF descriptor format " + str(e
), HTTP_Bad_Request
)
843 vnfd_catalog_descriptor
= vnf_descriptor
.get("vnfd:vnfd-catalog")
844 if not vnfd_catalog_descriptor
:
845 vnfd_catalog_descriptor
= vnf_descriptor
.get("vnfd-catalog")
846 vnfd_descriptor_list
= vnfd_catalog_descriptor
.get("vnfd")
847 if not vnfd_descriptor_list
:
848 vnfd_descriptor_list
= vnfd_catalog_descriptor
.get("vnfd:vnfd")
849 for vnfd_yang
in myvnfd
.vnfd_catalog
.vnfd
.itervalues():
850 vnfd
= vnfd_yang
.get()
853 vnf_uuid
= str(uuid4())
854 uuid_list
.append(vnf_uuid
)
855 vnfd_uuid_list
.append(vnf_uuid
)
856 vnfd_id
= get_str(vnfd
, "id", 255)
860 "name": get_str(vnfd
, "name", 255),
861 "description": get_str(vnfd
, "description", 255),
862 "tenant_id": tenant_id
,
863 "vendor": get_str(vnfd
, "vendor", 255),
864 "short_name": get_str(vnfd
, "short-name", 255),
865 "descriptor": str(vnf_descriptor
)[:60000]
868 for vnfd_descriptor
in vnfd_descriptor_list
:
869 if vnfd_descriptor
["id"] == str(vnfd
["id"]):
872 # table nets (internal-vld)
873 net_id2uuid
= {} # for mapping interface with network
874 for vld
in vnfd
.get("internal-vld").itervalues():
875 net_uuid
= str(uuid4())
876 uuid_list
.append(net_uuid
)
878 "name": get_str(vld
, "name", 255),
881 "description": get_str(vld
, "description", 255),
882 "type": "bridge", # TODO adjust depending on connection point type
884 net_id2uuid
[vld
.get("id")] = net_uuid
885 db_nets
.append(db_net
)
889 vdu_id2db_table_index
= {}
890 for vdu
in vnfd
.get("vdu").itervalues():
891 vm_uuid
= str(uuid4())
892 uuid_list
.append(vm_uuid
)
893 vdu_id
= get_str(vdu
, "id", 255)
897 "name": get_str(vdu
, "name", 255),
898 "description": get_str(vdu
, "description", 255),
901 vdu_id2uuid
[db_vm
["osm_id"]] = vm_uuid
902 vdu_id2db_table_index
[db_vm
["osm_id"]] = db_vms_index
904 db_vm
["count"] = int(vdu
["count"])
907 image_present
= False
911 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, vdu
)
913 image_uuid
= db_image
["uuid"]
914 db_images
.append(db_image
)
915 db_vm
["image_id"] = image_uuid
919 if vdu
.get("volumes"):
920 for volume_key
in sorted(vdu
["volumes"]):
921 volume
= vdu
["volumes"][volume_key
]
922 if not image_present
:
923 # Convert the first volume to vnfc.image
926 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, volume
)
928 image_uuid
= db_image
["uuid"]
929 db_images
.append(db_image
)
930 db_vm
["image_id"] = image_uuid
932 # Add Openmano devices
934 device
["type"] = str(volume
.get("device-type"))
935 if volume
.get("size"):
936 device
["size"] = int(volume
["size"])
937 if volume
.get("image"):
938 device
["image name"] = str(volume
["image"])
939 if volume
.get("image-checksum"):
940 device
["image checksum"] = str(volume
["image-checksum"])
941 devices
.append(device
)
945 if vdu
.get("cloud-init"):
946 boot_data
["user-data"] = str(vdu
["cloud-init"])
947 elif vdu
.get("cloud-init-file"):
948 # TODO Where this file content is present???
949 # boot_data["user-data"] = vnfd_yang.files[vdu["cloud-init-file"]]
950 boot_data
["user-data"] = str(vdu
["cloud-init-file"])
952 if vdu
.get("supplemental-boot-data"):
953 if vdu
["supplemental-boot-data"].get('boot-data-drive'):
954 boot_data
['boot-data-drive'] = True
955 if vdu
["supplemental-boot-data"].get('config-file'):
956 om_cfgfile_list
= list()
957 for custom_config_file
in vdu
["supplemental-boot-data"]['config-file'].itervalues():
958 # TODO Where this file content is present???
959 cfg_source
= str(custom_config_file
["source"])
960 om_cfgfile_list
.append({"dest": custom_config_file
["dest"],
961 "content": cfg_source
})
962 boot_data
['config-files'] = om_cfgfile_list
964 db_vm
["boot_data"] = yaml
.safe_dump(boot_data
, default_flow_style
=True, width
=256)
969 # table interfaces (internal/external interfaces)
970 flavor_epa_interfaces
= []
971 cp_name2iface_uuid
= {}
973 cp_name2db_interface
= {}
974 vdu_id2cp_name
= {} # stored only when one external connection point is presented at this VDU
975 # for iface in chain(vdu.get("internal-interface").itervalues(), vdu.get("external-interface").itervalues()):
976 for iface
in vdu
.get("interface").itervalues():
977 flavor_epa_interface
= {}
978 iface_uuid
= str(uuid4())
979 uuid_list
.append(iface_uuid
)
982 "internal_name": get_str(iface
, "name", 255),
985 flavor_epa_interface
["name"] = db_interface
["internal_name"]
986 if iface
.get("virtual-interface").get("vpci"):
987 db_interface
["vpci"] = get_str(iface
.get("virtual-interface"), "vpci", 12)
988 flavor_epa_interface
["vpci"] = db_interface
["vpci"]
990 if iface
.get("virtual-interface").get("bandwidth"):
991 bps
= int(iface
.get("virtual-interface").get("bandwidth"))
992 db_interface
["bw"] = int(math
.ceil(bps
/1000000.0))
993 flavor_epa_interface
["bandwidth"] = "{} Mbps".format(db_interface
["bw"])
995 if iface
.get("virtual-interface").get("type") == "OM-MGMT":
996 db_interface
["type"] = "mgmt"
997 elif iface
.get("virtual-interface").get("type") in ("VIRTIO", "E1000"):
998 db_interface
["type"] = "bridge"
999 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1000 elif iface
.get("virtual-interface").get("type") in ("SR-IOV", "PCI-PASSTHROUGH"):
1001 db_interface
["type"] = "data"
1002 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1003 flavor_epa_interface
["dedicated"] = "no" if iface
["virtual-interface"]["type"] == "SR-IOV" \
1005 flavor_epa_interfaces
.append(flavor_epa_interface
)
1007 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vdu[{}]':'interface':'virtual"
1008 "-interface':'type':'{}'. Interface type is not supported".format(
1009 vnfd_id
, vdu_id
, iface
.get("virtual-interface").get("type")),
1012 if iface
.get("external-connection-point-ref"):
1014 cp
= vnfd
.get("connection-point")[iface
.get("external-connection-point-ref")]
1015 db_interface
["external_name"] = get_str(cp
, "name", 255)
1016 cp_name2iface_uuid
[db_interface
["external_name"]] = iface_uuid
1017 cp_name2vm_uuid
[db_interface
["external_name"]] = vm_uuid
1018 cp_name2db_interface
[db_interface
["external_name"]] = db_interface
1019 for cp_descriptor
in vnfd_descriptor
["connection-point"]:
1020 if cp_descriptor
["name"] == db_interface
["external_name"]:
1025 if vdu_id
in vdu_id2cp_name
:
1026 vdu_id2cp_name
[vdu_id
] = None # more than two connecdtion point for this VDU
1028 vdu_id2cp_name
[vdu_id
] = db_interface
["external_name"]
1031 if str(cp_descriptor
.get("port-security-enabled")).lower() == "false":
1032 db_interface
["port_security"] = 0
1033 elif str(cp_descriptor
.get("port-security-enabled")).lower() == "true":
1034 db_interface
["port_security"] = 1
1036 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1037 "'interface[{iface}]':'vnfd-connection-point-ref':'{cp}' is not present"
1038 " at connection-point".format(
1039 vnf
=vnfd_id
, vdu
=vdu_id
, iface
=iface
["name"],
1040 cp
=iface
.get("vnfd-connection-point-ref")),
1042 elif iface
.get("internal-connection-point-ref"):
1044 for vld
in vnfd
.get("internal-vld").itervalues():
1045 for cp
in vld
.get("internal-connection-point").itervalues():
1046 if cp
.get("id-ref") == iface
.get("internal-connection-point-ref"):
1047 db_interface
["net_id"] = net_id2uuid
[vld
.get("id")]
1048 for cp_descriptor
in vnfd_descriptor
["connection-point"]:
1049 if cp_descriptor
["name"] == db_interface
["external_name"]:
1051 if str(cp_descriptor
.get("port-security-enabled")).lower() == "false":
1052 db_interface
["port_security"] = 0
1053 elif str(cp_descriptor
.get("port-security-enabled")).lower() == "true":
1054 db_interface
["port_security"] = 1
1057 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1058 "'interface[{iface}]':'vdu-internal-connection-point-ref':'{cp}' is not"
1059 " referenced by any internal-vld".format(
1060 vnf
=vnfd_id
, vdu
=vdu_id
, iface
=iface
["name"],
1061 cp
=iface
.get("vdu-internal-connection-point-ref")),
1063 if iface
.get("position") is not None:
1064 db_interface
["created_at"] = int(iface
.get("position")) - 1000
1065 db_interfaces
.append(db_interface
)
1069 "name": get_str(vdu
, "name", 250) + "-flv",
1070 "vcpus": int(vdu
["vm-flavor"].get("vcpu-count", 1)),
1071 "ram": int(vdu
["vm-flavor"].get("memory-mb", 1)),
1072 "disk": int(vdu
["vm-flavor"].get("storage-gb", 1)),
1078 extended
["devices"] = devices
1079 if flavor_epa_interfaces
:
1080 numa
["interfaces"] = flavor_epa_interfaces
1081 if vdu
.get("guest-epa"): # TODO or dedicated_int:
1082 epa_vcpu_set
= False
1083 if vdu
["guest-epa"].get("numa-node-policy"): # TODO or dedicated_int:
1084 numa_node_policy
= vdu
["guest-epa"].get("numa-node-policy")
1085 if numa_node_policy
.get("node"):
1086 numa_node
= numa_node_policy
["node"]['0']
1087 if numa_node
.get("num-cores"):
1088 numa
["cores"] = numa_node
["num-cores"]
1090 if numa_node
.get("paired-threads"):
1091 if numa_node
["paired-threads"].get("num-paired-threads"):
1092 numa
["paired-threads"] = int(numa_node
["paired-threads"]["num-paired-threads"])
1094 if len(numa_node
["paired-threads"].get("paired-thread-ids")):
1095 numa
["paired-threads-id"] = []
1096 for pair
in numa_node
["paired-threads"]["paired-thread-ids"].itervalues():
1097 numa
["paired-threads-id"].append(
1098 (str(pair
["thread-a"]), str(pair
["thread-b"]))
1100 if numa_node
.get("num-threads"):
1101 numa
["threads"] = int(numa_node
["num-threads"])
1103 if numa_node
.get("memory-mb"):
1104 numa
["memory"] = max(int(numa_node
["memory-mb"] / 1024), 1)
1105 if vdu
["guest-epa"].get("mempage-size"):
1106 if vdu
["guest-epa"]["mempage-size"] != "SMALL":
1107 numa
["memory"] = max(int(db_flavor
["ram"] / 1024), 1)
1108 if vdu
["guest-epa"].get("cpu-pinning-policy") and not epa_vcpu_set
:
1109 if vdu
["guest-epa"]["cpu-pinning-policy"] == "DEDICATED":
1110 if vdu
["guest-epa"].get("cpu-thread-pinning-policy") and \
1111 vdu
["guest-epa"]["cpu-thread-pinning-policy"] != "PREFER":
1112 numa
["cores"] = max(db_flavor
["vcpus"], 1)
1114 numa
["threads"] = max(db_flavor
["vcpus"], 1)
1116 extended
["numas"] = [numa
]
1118 extended_text
= yaml
.safe_dump(extended
, default_flow_style
=True, width
=256)
1119 db_flavor
["extended"] = extended_text
1120 # look if flavor exist
1121 temp_flavor_dict
= {'disk': db_flavor
.get('disk', 1),
1122 'ram': db_flavor
.get('ram'),
1123 'vcpus': db_flavor
.get('vcpus'),
1124 'extended': db_flavor
.get('extended')
1126 existing_flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
1127 if existing_flavors
:
1128 flavor_uuid
= existing_flavors
[0]["uuid"]
1130 flavor_uuid
= str(uuid4())
1131 uuid_list
.append(flavor_uuid
)
1132 db_flavor
["uuid"] = flavor_uuid
1133 db_flavors
.append(db_flavor
)
1134 db_vm
["flavor_id"] = flavor_uuid
1136 # VNF affinity and antiaffinity
1137 for pg
in vnfd
.get("placement-groups").itervalues():
1138 pg_name
= get_str(pg
, "name", 255)
1139 for vdu
in pg
.get("member-vdus").itervalues():
1140 vdu_id
= get_str(vdu
, "member-vdu-ref", 255)
1141 if vdu_id
not in vdu_id2db_table_index
:
1142 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'placement-groups[{pg}]':"
1143 "'member-vdus':'{vdu}'. Reference to a non-existing vdu".format(
1144 vnf
=vnfd_id
, pg
=pg_name
, vdu
=vdu_id
),
1146 db_vms
[vdu_id2db_table_index
[vdu_id
]]["availability_zone"] = pg_name
1147 # TODO consider the case of isolation and not colocation
1148 # if pg.get("strategy") == "ISOLATION":
1150 # VNF mgmt configuration
1152 if vnfd
["mgmt-interface"].get("vdu-id"):
1153 mgmt_vdu_id
= get_str(vnfd
["mgmt-interface"], "vdu-id", 255)
1154 if mgmt_vdu_id
not in vdu_id2uuid
:
1155 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'vdu-id':"
1156 "'{vdu}'. Reference to a non-existing vdu".format(
1157 vnf
=vnfd_id
, vdu
=mgmt_vdu_id
),
1159 mgmt_access
["vm_id"] = vdu_id2uuid
[vnfd
["mgmt-interface"]["vdu-id"]]
1160 # if only one cp is defined by this VDU, mark this interface as of type "mgmt"
1161 if vdu_id2cp_name
.get(mgmt_vdu_id
):
1162 cp_name2db_interface
[vdu_id2cp_name
[mgmt_vdu_id
]]["type"] = "mgmt"
1164 if vnfd
["mgmt-interface"].get("ip-address"):
1165 mgmt_access
["ip-address"] = str(vnfd
["mgmt-interface"].get("ip-address"))
1166 if vnfd
["mgmt-interface"].get("cp"):
1167 if vnfd
["mgmt-interface"]["cp"] not in cp_name2iface_uuid
:
1168 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'cp':'{cp}'. "
1169 "Reference to a non-existing connection-point".format(
1170 vnf
=vnfd_id
, cp
=vnfd
["mgmt-interface"]["cp"]),
1172 mgmt_access
["vm_id"] = cp_name2vm_uuid
[vnfd
["mgmt-interface"]["cp"]]
1173 mgmt_access
["interface_id"] = cp_name2iface_uuid
[vnfd
["mgmt-interface"]["cp"]]
1174 # mark this interface as of type mgmt
1175 cp_name2db_interface
[vnfd
["mgmt-interface"]["cp"]]["type"] = "mgmt"
1177 default_user
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1181 mgmt_access
["default_user"] = default_user
1182 required
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1185 mgmt_access
["required"] = required
1188 db_vnf
["mgmt_access"] = yaml
.safe_dump(mgmt_access
, default_flow_style
=True, width
=256)
1192 db_vnfs
.append(db_vnf
)
1196 {"images": db_images
},
1197 {"flavors": db_flavors
},
1199 {"interfaces": db_interfaces
},
1202 logger
.debug("create_vnf Deployment done vnfDict: %s",
1203 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
1204 mydb
.new_rows(db_tables
, uuid_list
)
1205 return vnfd_uuid_list
1206 except NfvoException
:
1208 except Exception as e
:
1209 logger
.error("Exception {}".format(e
))
1210 raise # NfvoException("Exception {}".format(e), HTTP_Bad_Request)
1213 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
1214 global global_config
1216 # Step 1. Check the VNF descriptor
1217 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
1218 # Step 2. Check tenant exist
1220 if tenant_id
!= "any":
1221 check_tenant(mydb
, tenant_id
)
1222 if "tenant_id" in vnf_descriptor
["vnf"]:
1223 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1224 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1227 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1228 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1229 if global_config
["auto_push_VNF_to_VIMs"]:
1230 vims
= get_vim(mydb
, tenant_id
)
1232 # Step 4. Review the descriptor and add missing fields
1233 #print vnf_descriptor
1234 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1235 vnf_name
= vnf_descriptor
['vnf']['name']
1236 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1237 if "physical" in vnf_descriptor
['vnf']:
1238 del vnf_descriptor
['vnf']['physical']
1239 #print vnf_descriptor
1241 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1242 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1243 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1245 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1246 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1247 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1249 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1250 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1252 VNFCitem
["name"] = vnfc
['name']
1253 VNFCitem
["availability_zone"] = vnfc
.get('availability_zone')
1254 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
1256 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1259 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1260 myflavorDict
["description"] = VNFCitem
["description"]
1261 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1262 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1263 myflavorDict
["disk"] = vnfc
.get("disk", 1)
1264 myflavorDict
["extended"] = {}
1266 devices
= vnfc
.get("devices")
1268 myflavorDict
["extended"]["devices"] = devices
1271 # 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
1272 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1274 # Previous code has been commented
1275 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1276 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1277 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1278 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1280 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1282 # print "Error creating flavor: unknown processor model. Rollback successful."
1283 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1285 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1286 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1288 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1289 myflavorDict
['extended']['numas'] = vnfc
['numas']
1293 # Step 6.2 New flavors are created in the VIM
1294 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1296 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1297 VNFCitem
["flavor_id"] = flavor_id
1298 VNFCDict
[vnfc
['name']] = VNFCitem
1300 logger
.debug("Creating new images in the VIM for each VNFC")
1301 # Step 6.3 New images are created in the VIM
1302 #For each VNFC, we must create the appropriate image.
1303 #This "for" loop might be integrated with the previous one
1304 #In case this integration is made, the VNFCDict might become a VNFClist.
1305 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1306 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1308 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1309 image_dict
['universal_name']=vnfc
.get('image name')
1310 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1311 image_dict
['location']=vnfc
.get('VNFC image')
1312 #image_dict['new_location']=vnfc.get('image location')
1313 image_dict
['checksum']=vnfc
.get('image checksum')
1314 image_metadata_dict
= vnfc
.get('image metadata', None)
1315 image_metadata_str
= None
1316 if image_metadata_dict
is not None:
1317 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1318 image_dict
['metadata']=image_metadata_str
1319 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1320 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1321 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1322 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1323 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1324 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1325 if vnfc
.get("boot-data"):
1326 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1329 # Step 7. Storing the VNF descriptor in the repository
1330 if "descriptor" not in vnf_descriptor
["vnf"]:
1331 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1333 # Step 8. Adding the VNF to the NFVO DB
1334 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1336 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1337 _
, message
= rollback(mydb
, vims
, rollback_list
)
1338 if isinstance(e
, db_base_Exception
):
1339 error_text
= "Exception at database"
1340 elif isinstance(e
, KeyError):
1341 error_text
= "KeyError exception "
1342 e
.http_code
= HTTP_Internal_Server_Error
1344 error_text
= "Exception at VIM"
1345 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1346 #logger.error("start_scenario %s", error_text)
1347 raise NfvoException(error_text
, e
.http_code
)
1350 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
1351 global global_config
1353 # Step 1. Check the VNF descriptor
1354 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
1355 # Step 2. Check tenant exist
1357 if tenant_id
!= "any":
1358 check_tenant(mydb
, tenant_id
)
1359 if "tenant_id" in vnf_descriptor
["vnf"]:
1360 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1361 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1364 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1365 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1366 if global_config
["auto_push_VNF_to_VIMs"]:
1367 vims
= get_vim(mydb
, tenant_id
)
1369 # Step 4. Review the descriptor and add missing fields
1370 #print vnf_descriptor
1371 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1372 vnf_name
= vnf_descriptor
['vnf']['name']
1373 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1374 if "physical" in vnf_descriptor
['vnf']:
1375 del vnf_descriptor
['vnf']['physical']
1376 #print vnf_descriptor
1378 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1379 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1380 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1382 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1383 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1384 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1386 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1387 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1389 VNFCitem
["name"] = vnfc
['name']
1390 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
1392 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1395 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1396 myflavorDict
["description"] = VNFCitem
["description"]
1397 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1398 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1399 myflavorDict
["disk"] = vnfc
.get("disk", 1)
1400 myflavorDict
["extended"] = {}
1402 devices
= vnfc
.get("devices")
1404 myflavorDict
["extended"]["devices"] = devices
1407 # 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
1408 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1410 # Previous code has been commented
1411 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1412 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1413 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1414 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1416 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1418 # print "Error creating flavor: unknown processor model. Rollback successful."
1419 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1421 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1422 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1424 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1425 myflavorDict
['extended']['numas'] = vnfc
['numas']
1429 # Step 6.2 New flavors are created in the VIM
1430 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1432 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1433 VNFCitem
["flavor_id"] = flavor_id
1434 VNFCDict
[vnfc
['name']] = VNFCitem
1436 logger
.debug("Creating new images in the VIM for each VNFC")
1437 # Step 6.3 New images are created in the VIM
1438 #For each VNFC, we must create the appropriate image.
1439 #This "for" loop might be integrated with the previous one
1440 #In case this integration is made, the VNFCDict might become a VNFClist.
1441 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1442 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1444 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1445 image_dict
['universal_name']=vnfc
.get('image name')
1446 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1447 image_dict
['location']=vnfc
.get('VNFC image')
1448 #image_dict['new_location']=vnfc.get('image location')
1449 image_dict
['checksum']=vnfc
.get('image checksum')
1450 image_metadata_dict
= vnfc
.get('image metadata', None)
1451 image_metadata_str
= None
1452 if image_metadata_dict
is not None:
1453 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1454 image_dict
['metadata']=image_metadata_str
1455 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1456 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1457 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1458 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1459 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1460 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1461 if vnfc
.get("boot-data"):
1462 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1464 # Step 7. Storing the VNF descriptor in the repository
1465 if "descriptor" not in vnf_descriptor
["vnf"]:
1466 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1468 # Step 8. Adding the VNF to the NFVO DB
1469 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1471 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1472 _
, message
= rollback(mydb
, vims
, rollback_list
)
1473 if isinstance(e
, db_base_Exception
):
1474 error_text
= "Exception at database"
1475 elif isinstance(e
, KeyError):
1476 error_text
= "KeyError exception "
1477 e
.http_code
= HTTP_Internal_Server_Error
1479 error_text
= "Exception at VIM"
1480 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1481 #logger.error("start_scenario %s", error_text)
1482 raise NfvoException(error_text
, e
.http_code
)
1485 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
1486 #check valid tenant_id
1487 check_tenant(mydb
, tenant_id
)
1490 if tenant_id
!= "any":
1491 where_or
["tenant_id"] = tenant_id
1492 where_or
["public"] = True
1493 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1495 vnf_id
= vnf
["uuid"]
1496 filter_keys
= ('uuid', 'name', 'description', 'public', "tenant_id", "osm_id", "created_at")
1497 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
1498 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
1499 data
={'vnf' : filtered_content
}
1501 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
1502 SELECT
=('vms.uuid as uuid', 'vms.osm_id as osm_id', 'vms.name as name', 'vms.description as description',
1504 WHERE
={'vnfs.uuid': vnf_id
} )
1506 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1507 # change boot_data into boot-data
1509 if vm
.get("boot_data"):
1510 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
1513 data
['vnf']['VNFC'] = content
1514 #TODO: GET all the information from a VNFC and include it in the output.
1517 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
1518 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
1519 WHERE
={'vnfs.uuid': vnf_id
} )
1520 data
['vnf']['nets'] = content
1522 #GET ip-profile for each net
1523 for net
in data
['vnf']['nets']:
1524 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1525 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1526 WHERE
={'net_id': net
["uuid"]} )
1527 if len(ipprofiles
)==1:
1528 net
["ip_profile"] = ipprofiles
[0]
1529 elif len(ipprofiles
)>1:
1530 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
1533 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1535 #GET External Interfaces
1536 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1537 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1538 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1539 WHERE
={'vnfs.uuid': vnf_id
, 'interfaces.external_name<>': None} )
1541 data
['vnf']['external-connections'] = content
1546 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1547 # Check tenant exist
1548 if tenant_id
!= "any":
1549 check_tenant(mydb
, tenant_id
)
1550 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1551 vims
= get_vim(mydb
, tenant_id
)
1555 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1557 if tenant_id
!= "any":
1558 where_or
["tenant_id"] = tenant_id
1559 where_or
["public"] = True
1560 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1561 vnf_id
= vnf
["uuid"]
1563 # "Getting the list of flavors and tenants of the VNF"
1564 flavorList
= get_flavorlist(mydb
, vnf_id
)
1565 if len(flavorList
)==0:
1566 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1568 imageList
= get_imagelist(mydb
, vnf_id
)
1569 if len(imageList
)==0:
1570 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1572 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1574 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1577 for flavor
in flavorList
:
1578 #check if flavor is used by other vnf
1580 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1582 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1584 #flavor not used, must be deleted
1586 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
1587 for flavor_vim
in c
:
1588 if flavor_vim
["datacenter_vim_id"] not in vims
: # TODO change to datacenter_tenant_id
1590 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
1592 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
1594 myvim
.delete_flavor(flavor_vim
["vim_id"])
1595 except vimconn
.vimconnNotFoundException
as e
:
1596 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
1597 except vimconn
.vimconnException
as e
:
1598 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1599 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1600 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
1601 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1602 mydb
.delete_row_by_id('flavors', flavor
)
1603 except db_base_Exception
as e
:
1604 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1605 undeletedItems
.append("flavor %s" % flavor
)
1608 for image
in imageList
:
1610 #check if image is used by other vnf
1611 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
1613 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1615 #image not used, must be deleted
1617 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1619 if image_vim
["datacenter_vim_id"] not in vims
: # TODO change to datacenter_tenant_id
1621 if image_vim
['created']=='false': #skip this image because not created by openmano
1623 myvim
=vims
[ image_vim
["datacenter_id"] ]
1625 myvim
.delete_image(image_vim
["vim_id"])
1626 except vimconn
.vimconnNotFoundException
as e
:
1627 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1628 except vimconn
.vimconnException
as e
:
1629 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1630 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1631 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1632 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1633 mydb
.delete_row_by_id('images', image
)
1634 except db_base_Exception
as e
:
1635 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1636 undeletedItems
.append("image %s" % image
)
1638 return vnf_id
+ " " + vnf
["name"]
1640 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1643 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1644 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1648 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
1649 myvim
= vims
.values()[0]
1650 result
,servers
= myvim
.get_hosts_info()
1652 return result
, servers
1653 topology
= {'name':myvim
['name'] , 'servers': servers
}
1654 return result
, topology
1657 def get_hosts(mydb
, nfvo_tenant_id
):
1658 vims
= get_vim(mydb
, nfvo_tenant_id
)
1660 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
1662 #print "nfvo.datacenter_action() error. Several datacenters found"
1663 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1664 myvim
= vims
.values()[0]
1666 hosts
= myvim
.get_hosts()
1667 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1669 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1671 server
={'name':host
['name'], 'vms':[]}
1672 for vm
in host
['instances']:
1673 #get internal name and model
1675 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1676 WHERE
={'vim_vm_id':vm
['id']} )
1678 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1680 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1682 except db_base_Exception
as e
:
1683 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1684 datacenter
['Datacenters'][0]['servers'].append(server
)
1685 #return -400, "en construccion"
1687 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1689 except vimconn
.vimconnException
as e
:
1690 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1693 def new_scenario(mydb
, tenant_id
, topo
):
1695 # result, vims = get_vim(mydb, tenant_id)
1697 # return result, vims
1699 if tenant_id
!= "any":
1700 check_tenant(mydb
, tenant_id
)
1701 if "tenant_id" in topo
:
1702 if topo
["tenant_id"] != tenant_id
:
1703 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1708 #1.1: get VNFs and external_networks (other_nets).
1710 other_nets
={} #external_networks, bridge_networks and data_networkds
1711 nodes
= topo
['topology']['nodes']
1712 for k
in nodes
.keys():
1713 if nodes
[k
]['type'] == 'VNF':
1715 vnfs
[k
]['ifaces'] = {}
1716 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1717 other_nets
[k
] = nodes
[k
]
1718 other_nets
[k
]['external']=True
1719 elif nodes
[k
]['type'] == 'network':
1720 other_nets
[k
] = nodes
[k
]
1721 other_nets
[k
]['external']=False
1724 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1725 for name
,vnf
in vnfs
.items():
1726 where
= {"OR": {"tenant_id": tenant_id
, 'public': "true"}}
1728 error_pos
= "'topology':'nodes':'" + name
+ "'"
1730 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1731 where
['uuid'] = vnf
['vnf_id']
1732 if 'VNF model' in vnf
:
1733 error_text
+= " 'VNF model' " + vnf
['VNF model']
1734 where
['name'] = vnf
['VNF model']
1736 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
1738 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1742 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1744 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1745 vnf
['uuid']=vnf_db
[0]['uuid']
1746 vnf
['description']=vnf_db
[0]['description']
1747 #get external interfaces
1748 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1749 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1750 WHERE
={'vnfs.uuid':vnf
['uuid'], 'external_name<>': None} )
1751 for ext_iface
in ext_ifaces
:
1752 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1754 #1.4 get list of connections
1755 conections
= topo
['topology']['connections']
1756 conections_list
= []
1757 conections_list_name
= []
1758 for k
in conections
.keys():
1759 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1760 ifaces_list
= conections
[k
]['nodes'].items()
1761 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1763 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1764 for k2
in conection_pair_list
:
1767 con_type
= conections
[k
].get("type", "link")
1768 if con_type
!= "link":
1770 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
1771 other_nets
[k
] = {'external': False}
1772 if conections
[k
].get("graph"):
1773 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1774 ifaces_list
.append( (k
, None) )
1777 if con_type
== "external_network":
1778 other_nets
[k
]['external'] = True
1779 if conections
[k
].get("model"):
1780 other_nets
[k
]["model"] = conections
[k
]["model"]
1782 other_nets
[k
]["model"] = k
1783 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1784 other_nets
[k
]["model"] = con_type
1786 conections_list_name
.append(k
)
1787 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)
1788 #print set(ifaces_list)
1789 #check valid VNF and iface names
1790 for iface
in ifaces_list
:
1791 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1792 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1793 str(k
), iface
[0]), HTTP_Not_Found
)
1794 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1795 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1796 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
1798 #1.5 unify connections from the pair list to a consolidated list
1800 while index
< len(conections_list
):
1802 while index2
< len(conections_list
):
1803 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1804 conections_list
[index
] |
= conections_list
[index2
]
1805 del conections_list
[index2
]
1806 del conections_list_name
[index2
]
1809 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1811 #for k in conections_list:
1816 #1.6 Delete non external nets
1817 # for k in other_nets.keys():
1818 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1819 # for con in conections_list:
1821 # for index in range(0,len(con)):
1822 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1823 # for index in delete_indexes:
1826 #1.7: Check external_ports are present at database table datacenter_nets
1827 for k
,net
in other_nets
.items():
1828 error_pos
= "'topology':'nodes':'" + k
+ "'"
1829 if net
['external']==False:
1830 if 'name' not in net
:
1832 if 'model' not in net
:
1833 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1834 if net
['model']=='bridge_net':
1835 net
['type']='bridge';
1836 elif net
['model']=='dataplane_net':
1839 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1841 #IF we do not want to check that external network exist at datacenter
1846 # if 'net_id' in net:
1847 # error_text += " 'net_id' " + net['net_id']
1848 # WHERE_['uuid'] = net['net_id']
1849 # if 'model' in net:
1850 # error_text += " 'model' " + net['model']
1851 # WHERE_['name'] = net['model']
1852 # if len(WHERE_) == 0:
1853 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1854 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1855 # FROM='datacenter_nets', WHERE=WHERE_ )
1857 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1859 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1860 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1862 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1863 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1864 # other_nets[k].update(net_db[0])
1867 net_nb
=0 #Number of nets
1868 for con
in conections_list
:
1869 #check if this is connected to a external net
1873 for index
in range(0,len(con
)):
1874 #check if this is connected to a external net
1875 for net_key
in other_nets
.keys():
1876 if con
[index
][0]==net_key
:
1877 if other_net_index
>=0:
1878 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1879 #print "nfvo.new_scenario " + error_text
1880 raise NfvoException(error_text
, HTTP_Bad_Request
)
1882 other_net_index
= index
1883 net_target
= net_key
1885 #print "other_net_index", other_net_index
1887 if other_net_index
>=0:
1888 del con
[other_net_index
]
1889 #IF we do not want to check that external network exist at datacenter
1890 if other_nets
[net_target
]['external'] :
1891 if "name" not in other_nets
[net_target
]:
1892 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1893 if other_nets
[net_target
]["type"] == "external_network":
1894 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1895 other_nets
[net_target
]["type"] = "data"
1897 other_nets
[net_target
]["type"] = "bridge"
1899 # if other_nets[net_target]['external'] :
1900 # 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
1901 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1902 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1903 # print "nfvo.new_scenario " + error_text
1904 # return -HTTP_Bad_Request, error_text
1907 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1910 net_type_bridge
=False
1912 net_target
= "__-__net"+str(net_nb
)
1913 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
1914 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1917 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1918 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1919 if iface_type
=='mgmt' or iface_type
=='bridge':
1920 net_type_bridge
= True
1922 net_type_data
= True
1923 if net_type_bridge
and net_type_data
:
1924 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1925 #print "nfvo.new_scenario " + error_text
1926 raise NfvoException(error_text
, HTTP_Bad_Request
)
1927 elif net_type_bridge
:
1930 type_
='data' if len(con
)>2 else 'ptp'
1931 net_list
[net_target
]['type'] = type_
1934 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1935 #print "nfvo.new_scenario " + error_text
1937 raise NfvoException(error_text
, HTTP_Bad_Request
)
1939 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1940 #1.8.1 obtain management net
1941 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1942 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1943 #1.8.2 check all interfaces from all vnfs
1945 add_mgmt_net
= False
1946 for vnf
in vnfs
.values():
1947 for iface
in vnf
['ifaces'].values():
1948 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1949 #iface not connected
1950 iface
['net_key'] = 'mgmt'
1952 if add_mgmt_net
and 'mgmt' not in net_list
:
1953 net_list
['mgmt']=mgmt_net
[0]
1954 net_list
['mgmt']['external']=True
1955 net_list
['mgmt']['graph']={'visible':False}
1957 net_list
.update(other_nets
)
1959 #print 'net_list', net_list
1964 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1965 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1966 'tenant_id':tenant_id
, 'name':topo
['name'],
1967 'description':topo
.get('description',topo
['name']),
1968 'public': topo
.get('public', False)
1974 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
1975 """ This creates a new scenario for version 0.2 and 0.3"""
1976 scenario
= scenario_dict
["scenario"]
1977 if tenant_id
!= "any":
1978 check_tenant(mydb
, tenant_id
)
1979 if "tenant_id" in scenario
:
1980 if scenario
["tenant_id"] != tenant_id
:
1981 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1982 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1983 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1987 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
1988 for name
,vnf
in scenario
["vnfs"].iteritems():
1989 where
= {"OR": {"tenant_id": tenant_id
, 'public': "true"}}
1991 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1993 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1994 where
['uuid'] = vnf
['vnf_id']
1995 if 'vnf_name' in vnf
:
1996 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1997 where
['name'] = vnf
['vnf_name']
1999 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
2000 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
2003 if len(vnf_db
) == 0:
2004 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
2005 elif len(vnf_db
) > 1:
2006 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
2007 vnf
['uuid'] = vnf_db
[0]['uuid']
2008 vnf
['description'] = vnf_db
[0]['description']
2010 # get external interfaces
2011 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
2012 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
2013 WHERE
={'vnfs.uuid':vnf
['uuid'], 'external_name<>': None} )
2014 for ext_iface
in ext_ifaces
:
2015 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
2016 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
2018 # 2: Insert net_key and ip_address at every vnf interface
2019 for net_name
, net
in scenario
["networks"].items():
2020 net_type_bridge
= False
2021 net_type_data
= False
2022 for iface_dict
in net
["interfaces"]:
2023 if version
== "0.2":
2024 temp_dict
= iface_dict
2026 elif version
== "0.3":
2027 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
2028 ip_address
= iface_dict
.get('ip_address', None)
2029 for vnf
, iface
in temp_dict
.items():
2030 if vnf
not in scenario
["vnfs"]:
2031 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
2033 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2034 raise NfvoException(error_text
, HTTP_Not_Found
)
2035 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
2036 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
2037 .format(net_name
, iface
)
2038 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2039 raise NfvoException(error_text
, HTTP_Bad_Request
)
2040 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
2041 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
2042 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
2043 # logger.debug("nfvo.new_scenario_v02 " + error_text)
2044 raise NfvoException(error_text
, HTTP_Bad_Request
)
2045 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
2046 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
2047 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
2048 if iface_type
== 'mgmt' or iface_type
== 'bridge':
2049 net_type_bridge
= True
2051 net_type_data
= True
2053 if net_type_bridge
and net_type_data
:
2054 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
2056 # logger.debug("nfvo.new_scenario " + error_text)
2057 raise NfvoException(error_text
, HTTP_Bad_Request
)
2058 elif net_type_bridge
:
2061 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
2063 if net
.get("implementation"): # for v0.3
2064 if type_
== "bridge" and net
["implementation"] == "underlay":
2065 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
2066 "'network':'{}'".format(net_name
)
2067 # logger.debug(error_text)
2068 raise NfvoException(error_text
, HTTP_Bad_Request
)
2069 elif type_
!= "bridge" and net
["implementation"] == "overlay":
2070 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
2071 "'network':'{}'".format(net_name
)
2072 # logger.debug(error_text)
2073 raise NfvoException(error_text
, HTTP_Bad_Request
)
2074 net
.pop("implementation")
2075 if "type" in net
and version
== "0.3": # for v0.3
2076 if type_
== "data" and net
["type"] == "e-line":
2077 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
2078 "'e-line' at 'network':'{}'".format(net_name
)
2079 # logger.debug(error_text)
2080 raise NfvoException(error_text
, HTTP_Bad_Request
)
2081 elif type_
== "ptp" and net
["type"] == "e-lan":
2085 net
['name'] = net_name
2086 net
['external'] = net
.get('external', False)
2088 # 3: insert at database
2089 scenario
["nets"] = scenario
["networks"]
2090 scenario
['tenant_id'] = tenant_id
2091 scenario_id
= mydb
.new_scenario(scenario
)
2095 def new_nsd_v3(mydb
, tenant_id
, nsd_descriptor
):
2097 Parses an OSM IM nsd_catalog and insert at DB
2100 :param nsd_descriptor:
2101 :return: The list of cretated NSD ids
2104 mynsd
= nsd_catalog
.nsd()
2106 pybindJSONDecoder
.load_ietf_json(nsd_descriptor
, None, None, obj
=mynsd
)
2107 except Exception as e
:
2108 raise NfvoException("Error. Invalid NS descriptor format: " + str(e
), HTTP_Bad_Request
)
2112 db_sce_interfaces
= []
2114 db_ip_profiles_index
= 0
2117 for nsd_yang
in mynsd
.nsd_catalog
.nsd
.itervalues():
2118 nsd
= nsd_yang
.get()
2121 scenario_uuid
= str(uuid4())
2122 uuid_list
.append(scenario_uuid
)
2123 nsd_uuid_list
.append(scenario_uuid
)
2125 "uuid": scenario_uuid
,
2126 "osm_id": get_str(nsd
, "id", 255),
2127 "name": get_str(nsd
, "name", 255),
2128 "description": get_str(nsd
, "description", 255),
2129 "tenant_id": tenant_id
,
2130 "vendor": get_str(nsd
, "vendor", 255),
2131 "short_name": get_str(nsd
, "short-name", 255),
2132 "descriptor": str(nsd_descriptor
)[:60000],
2134 db_scenarios
.append(db_scenario
)
2136 # table sce_vnfs (constituent-vnfd)
2137 vnf_index2scevnf_uuid
= {}
2138 vnf_index2vnf_uuid
= {}
2139 for vnf
in nsd
.get("constituent-vnfd").itervalues():
2140 existing_vnf
= mydb
.get_rows(FROM
="vnfs", WHERE
={'osm_id': str(vnf
["vnfd-id-ref"])[:255],
2141 'tenant_id': tenant_id
})
2142 if not existing_vnf
:
2143 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'constituent-vnfd':'vnfd-id-ref':"
2144 "'{}'. Reference to a non-existing VNFD in the catalog".format(
2145 str(nsd
["id"]), str(vnf
["vnfd-id-ref"])[:255]),
2147 sce_vnf_uuid
= str(uuid4())
2148 uuid_list
.append(sce_vnf_uuid
)
2150 "uuid": sce_vnf_uuid
,
2151 "scenario_id": scenario_uuid
,
2152 "name": existing_vnf
[0]["name"][:200] + "." + get_str(vnf
, "member-vnf-index", 5),
2153 "vnf_id": existing_vnf
[0]["uuid"],
2154 "member_vnf_index": int(vnf
["member-vnf-index"]),
2155 # TODO 'start-by-default': True
2157 vnf_index2scevnf_uuid
[int(vnf
['member-vnf-index'])] = sce_vnf_uuid
2158 vnf_index2vnf_uuid
[int(vnf
['member-vnf-index'])] = existing_vnf
[0]["uuid"]
2159 db_sce_vnfs
.append(db_sce_vnf
)
2161 # table ip_profiles (ip-profiles)
2162 ip_profile_name2db_table_index
= {}
2163 for ip_profile
in nsd
.get("ip-profiles").itervalues():
2165 "ip_version": str(ip_profile
["ip-profile-params"].get("ip-version", "ipv4")),
2166 "subnet_address": str(ip_profile
["ip-profile-params"].get("subnet-address")),
2167 "gateway_address": str(ip_profile
["ip-profile-params"].get("gateway-address")),
2168 "dhcp_enabled": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("enabled", True)),
2169 "dhcp_start_address": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("start-address")),
2170 "dhcp_count": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("count")),
2173 for dns
in ip_profile
["ip-profile-params"]["dns-server"].itervalues():
2174 dns_list
.append(str(dns
.get("address")))
2175 db_ip_profile
["dns_address"] = ";".join(dns_list
)
2176 if ip_profile
["ip-profile-params"].get('security-group'):
2177 db_ip_profile
["security_group"] = ip_profile
["ip-profile-params"]['security-group']
2178 ip_profile_name2db_table_index
[str(ip_profile
["name"])] = db_ip_profiles_index
2179 db_ip_profiles_index
+= 1
2180 db_ip_profiles
.append(db_ip_profile
)
2182 # table sce_nets (internal-vld)
2183 for vld
in nsd
.get("vld").itervalues():
2184 sce_net_uuid
= str(uuid4())
2185 uuid_list
.append(sce_net_uuid
)
2187 "uuid": sce_net_uuid
,
2188 "name": get_str(vld
, "name", 255),
2189 "scenario_id": scenario_uuid
,
2191 "multipoint": not vld
.get("type") == "ELINE",
2193 "description": get_str(vld
, "description", 255),
2195 # guess type of network
2196 if vld
.get("mgmt-network"):
2197 db_sce_net
["type"] = "bridge"
2198 db_sce_net
["external"] = True
2199 elif vld
.get("provider-network").get("overlay-type") == "VLAN":
2200 db_sce_net
["type"] = "data"
2202 # later on it will be fixed to bridge or data depending on the type of interfaces attached to it
2203 db_sce_net
["type"] = None
2204 db_sce_nets
.append(db_sce_net
)
2206 # ip-profile, link db_ip_profile with db_sce_net
2207 if vld
.get("ip-profile-ref"):
2208 ip_profile_name
= vld
.get("ip-profile-ref")
2209 if ip_profile_name
not in ip_profile_name2db_table_index
:
2210 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'ip-profile-ref':'{}'."
2211 " Reference to a non-existing 'ip_profiles'".format(
2212 str(nsd
["id"]), str(vld
["id"]), str(vld
["ip-profile-ref"])),
2214 db_ip_profiles
[ip_profile_name2db_table_index
[ip_profile_name
]]["sce_net_id"] = sce_net_uuid
2216 # table sce_interfaces (vld:vnfd-connection-point-ref)
2217 for iface
in vld
.get("vnfd-connection-point-ref").itervalues():
2218 vnf_index
= int(iface
['member-vnf-index-ref'])
2219 # check correct parameters
2220 if vnf_index
not in vnf_index2vnf_uuid
:
2221 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2222 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2223 "'nsd':'constituent-vnfd'".format(
2224 str(nsd
["id"]), str(vld
["id"]), str(iface
["member-vnf-index-ref"])),
2227 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid', 'i.type as iface_type'),
2228 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2229 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2230 'external_name': get_str(iface
, "vnfd-connection-point-ref",
2232 if not existing_ifaces
:
2233 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2234 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2235 "connection-point name at VNFD '{}'".format(
2236 str(nsd
["id"]), str(vld
["id"]), str(iface
["vnfd-connection-point-ref"]),
2237 str(iface
.get("vnfd-id-ref"))[:255]),
2239 interface_uuid
= existing_ifaces
[0]["uuid"]
2240 if existing_ifaces
[0]["iface_type"] == "data" and not db_sce_net
["type"]:
2241 db_sce_net
["type"] = "data"
2242 sce_interface_uuid
= str(uuid4())
2243 uuid_list
.append(sce_net_uuid
)
2244 db_sce_interface
= {
2245 "uuid": sce_interface_uuid
,
2246 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2247 "sce_net_id": sce_net_uuid
,
2248 "interface_id": interface_uuid
,
2249 # "ip_address": #TODO
2251 db_sce_interfaces
.append(db_sce_interface
)
2252 if not db_sce_net
["type"]:
2253 db_sce_net
["type"] = "bridge"
2256 {"scenarios": db_scenarios
},
2257 {"sce_nets": db_sce_nets
},
2258 {"ip_profiles": db_ip_profiles
},
2259 {"sce_vnfs": db_sce_vnfs
},
2260 {"sce_interfaces": db_sce_interfaces
},
2263 logger
.debug("create_vnf Deployment done vnfDict: %s",
2264 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
2265 mydb
.new_rows(db_tables
, uuid_list
)
2266 return nsd_uuid_list
2267 except NfvoException
:
2269 except Exception as e
:
2270 logger
.error("Exception {}".format(e
))
2271 raise # NfvoException("Exception {}".format(e), HTTP_Bad_Request)
2274 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
2275 data
["uuid"] = scenario_id
2276 data
["tenant_id"] = tenant_id
2277 c
= mydb
.edit_scenario( data
)
2281 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
2282 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2283 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
2284 vims
= {datacenter_id
: myvim
}
2285 myvim_tenant
= myvim
['tenant_id']
2286 datacenter_name
= myvim
['name']
2290 #print "Checking that the scenario_id exists and getting the scenario dictionary"
2291 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
=datacenter_id
)
2292 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
2293 scenarioDict
['datacenter_id'] = datacenter_id
2294 #print '================scenarioDict======================='
2295 #print json.dumps(scenarioDict, indent=4)
2296 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
2298 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
2299 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2301 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
2302 auxNetDict
['scenario'] = {}
2304 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
2305 for sce_net
in scenarioDict
['nets']:
2306 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
2308 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
2309 myNetName
= myNetName
[0:255] #limit length
2310 myNetType
= sce_net
['type']
2312 myNetDict
["name"] = myNetName
2313 myNetDict
["type"] = myNetType
2314 myNetDict
["tenant_id"] = myvim_tenant
2315 myNetIPProfile
= sce_net
.get('ip_profile', None)
2317 #We should use the dictionary as input parameter for new_network
2319 if not sce_net
["external"]:
2320 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2321 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
2322 sce_net
['vim_id'] = network_id
2323 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
2324 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2325 sce_net
["created"] = True
2327 if sce_net
['vim_id'] == None:
2328 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
2329 _
, message
= rollback(mydb
, vims
, rollbackList
)
2330 logger
.error("nfvo.start_scenario: %s", error_text
)
2331 raise NfvoException(error_text
, HTTP_Bad_Request
)
2332 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
2333 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
2335 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
2336 #For each vnf net, we create it and we add it to instanceNetlist.
2338 for sce_vnf
in scenarioDict
['vnfs']:
2339 for net
in sce_vnf
['nets']:
2340 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
2342 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
2343 myNetName
= myNetName
[0:255] #limit length
2344 myNetType
= net
['type']
2346 myNetDict
["name"] = myNetName
2347 myNetDict
["type"] = myNetType
2348 myNetDict
["tenant_id"] = myvim_tenant
2349 myNetIPProfile
= net
.get('ip_profile', None)
2352 #We should use the dictionary as input parameter for new_network
2353 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2354 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
2355 net
['vim_id'] = network_id
2356 if sce_vnf
['uuid'] not in auxNetDict
:
2357 auxNetDict
[sce_vnf
['uuid']] = {}
2358 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
2359 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2360 net
["created"] = True
2362 #print "auxNetDict:"
2363 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2365 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
2366 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2368 for sce_vnf
in scenarioDict
['vnfs']:
2369 vnf_availability_zones
= []
2370 for vm
in sce_vnf
['vms']:
2371 vm_av
= vm
.get('availability_zone')
2372 if vm_av
and vm_av
not in vnf_availability_zones
:
2373 vnf_availability_zones
.append(vm_av
)
2375 # check if there is enough availability zones available at vim level.
2376 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
2377 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
2378 raise NfvoException('No enough availability zones at VIM for this deployment', HTTP_Bad_Request
)
2380 for vm
in sce_vnf
['vms']:
2383 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
2384 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
2385 #myVMDict['description'] = vm['description']
2386 myVMDict
['description'] = myVMDict
['name'][0:99]
2388 myVMDict
['start'] = "no"
2389 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2390 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
2392 #create image at vim in case it not exist
2393 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2394 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
2395 vm
['vim_image_id'] = image_id
2397 #create flavor at vim in case it not exist
2398 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2399 if flavor_dict
['extended']!=None:
2400 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2401 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
2402 vm
['vim_flavor_id'] = flavor_id
2405 myVMDict
['imageRef'] = vm
['vim_image_id']
2406 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2407 myVMDict
['networks'] = []
2408 for iface
in vm
['interfaces']:
2410 if iface
['type']=="data":
2411 netDict
['type'] = iface
['model']
2412 elif "model" in iface
and iface
["model"]!=None:
2413 netDict
['model']=iface
['model']
2414 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2415 #discover type of interface looking at flavor
2416 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2417 for flavor_iface
in numa
.get('interfaces',[]):
2418 if flavor_iface
.get('name') == iface
['internal_name']:
2419 if flavor_iface
['dedicated'] == 'yes':
2420 netDict
['type']="PF" #passthrough
2421 elif flavor_iface
['dedicated'] == 'no':
2422 netDict
['type']="VF" #siov
2423 elif flavor_iface
['dedicated'] == 'yes:sriov':
2424 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2425 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2427 netDict
["use"]=iface
['type']
2428 if netDict
["use"]=="data" and not netDict
.get("type"):
2429 #print "netDict", netDict
2430 #print "iface", iface
2431 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'])
2432 if flavor_dict
.get('extended')==None:
2433 raise NfvoException(e_text
+ "After database migration some information is not available. \
2434 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
2436 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
2437 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2438 netDict
["type"]="virtual"
2439 if "vpci" in iface
and iface
["vpci"] is not None:
2440 netDict
['vpci'] = iface
['vpci']
2441 if "mac" in iface
and iface
["mac"] is not None:
2442 netDict
['mac_address'] = iface
['mac']
2443 if "port-security" in iface
and iface
["port-security"] is not None:
2444 netDict
['port_security'] = iface
['port-security']
2445 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2446 netDict
['floating_ip'] = iface
['floating-ip']
2447 netDict
['name'] = iface
['internal_name']
2448 if iface
['net_id'] is None:
2449 for vnf_iface
in sce_vnf
["interfaces"]:
2452 if vnf_iface
['interface_id']==iface
['uuid']:
2453 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
2456 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2457 #skip bridge ifaces not connected to any net
2458 #if 'net_id' not in netDict or netDict['net_id']==None:
2460 myVMDict
['networks'].append(netDict
)
2461 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2462 #print myVMDict['name']
2463 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2464 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2465 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2467 if 'availability_zone' in myVMDict
:
2468 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
2472 vm_id
, _
= myvim
.new_vminstance(myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2473 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2474 availability_zone_index
=av_index
,
2475 availability_zone_list
=vnf_availability_zones
)
2476 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
2477 vm
['vim_id'] = vm_id
2478 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2479 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2480 for net
in myVMDict
['networks']:
2482 for iface
in vm
['interfaces']:
2483 if net
["name"]==iface
["internal_name"]:
2484 iface
["vim_id"]=net
["vim_id"]
2487 logger
.debug("start scenario Deployment done")
2488 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2489 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
2490 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
2491 return mydb
.get_instance_scenario(instance_id
)
2493 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
2494 _
, message
= rollback(mydb
, vims
, rollbackList
)
2495 if isinstance(e
, db_base_Exception
):
2496 error_text
= "Exception at database"
2498 error_text
= "Exception at VIM"
2499 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2500 #logger.error("start_scenario %s", error_text)
2501 raise NfvoException(error_text
, e
.http_code
)
2503 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
2504 """ join the cloud config information into cloud_config_preserve.
2505 In case of conflict cloud_config_preserve preserves
2508 if not cloud_config_preserve
and not cloud_config
:
2511 new_cloud_config
= {"key-pairs":[], "users":[]}
2513 if cloud_config_preserve
:
2514 for key
in cloud_config_preserve
.get("key-pairs", () ):
2515 if key
not in new_cloud_config
["key-pairs"]:
2516 new_cloud_config
["key-pairs"].append(key
)
2518 for key
in cloud_config
.get("key-pairs", () ):
2519 if key
not in new_cloud_config
["key-pairs"]:
2520 new_cloud_config
["key-pairs"].append(key
)
2521 if not new_cloud_config
["key-pairs"]:
2522 del new_cloud_config
["key-pairs"]
2526 new_cloud_config
["users"] += cloud_config
.get("users", () )
2527 if cloud_config_preserve
:
2528 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
2529 index_to_delete
= []
2530 users
= new_cloud_config
.get("users", [])
2531 for index0
in range(0,len(users
)):
2532 if index0
in index_to_delete
:
2534 for index1
in range(index0
+1,len(users
)):
2535 if index1
in index_to_delete
:
2537 if users
[index0
]["name"] == users
[index1
]["name"]:
2538 index_to_delete
.append(index1
)
2539 for key
in users
[index1
].get("key-pairs",()):
2540 if "key-pairs" not in users
[index0
]:
2541 users
[index0
]["key-pairs"] = [key
]
2542 elif key
not in users
[index0
]["key-pairs"]:
2543 users
[index0
]["key-pairs"].append(key
)
2544 index_to_delete
.sort(reverse
=True)
2545 for index
in index_to_delete
:
2547 if not new_cloud_config
["users"]:
2548 del new_cloud_config
["users"]
2551 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
2552 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
2553 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
2554 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
2557 new_cloud_config
["user-data"] = []
2558 if cloud_config
and cloud_config
.get("user-data"):
2559 if isinstance(cloud_config
["user-data"], list):
2560 new_cloud_config
["user-data"] += cloud_config
["user-data"]
2562 new_cloud_config
["user-data"].append(cloud_config
["user-data"])
2563 if cloud_config_preserve
and cloud_config_preserve
.get("user-data"):
2564 if isinstance(cloud_config_preserve
["user-data"], list):
2565 new_cloud_config
["user-data"] += cloud_config_preserve
["user-data"]
2567 new_cloud_config
["user-data"].append(cloud_config_preserve
["user-data"])
2568 if not new_cloud_config
["user-data"]:
2569 del new_cloud_config
["user-data"]
2572 new_cloud_config
["config-files"] = []
2573 if cloud_config
and cloud_config
.get("config-files") != None:
2574 new_cloud_config
["config-files"] += cloud_config
["config-files"]
2575 if cloud_config_preserve
:
2576 for file in cloud_config_preserve
.get("config-files", ()):
2577 for index
in range(0, len(new_cloud_config
["config-files"])):
2578 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
2579 new_cloud_config
["config-files"][index
] = file
2582 new_cloud_config
["config-files"].append(file)
2583 if not new_cloud_config
["config-files"]:
2584 del new_cloud_config
["config-files"]
2585 return new_cloud_config
2588 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
2589 datacenter_id
= None
2590 datacenter_name
= None
2593 if datacenter_tenant_id
:
2594 thread_id
= datacenter_tenant_id
2595 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
2597 where_
={"td.nfvo_tenant_id": tenant_id
}
2598 if datacenter_id_name
:
2599 if utils
.check_valid_uuid(datacenter_id_name
):
2600 datacenter_id
= datacenter_id_name
2601 where_
["dt.datacenter_id"] = datacenter_id
2603 datacenter_name
= datacenter_id_name
2604 where_
["d.name"] = datacenter_name
2605 if datacenter_tenant_id
:
2606 where_
["dt.uuid"] = datacenter_tenant_id
2607 datacenters
= mydb
.get_rows(
2608 SELECT
=("dt.uuid as datacenter_tenant_id",),
2609 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
2610 "join datacenters as d on d.uuid=dt.datacenter_id",
2612 if len(datacenters
) > 1:
2613 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2615 thread_id
= datacenters
[0]["datacenter_tenant_id"]
2616 thread
= vim_threads
["running"].get(thread_id
)
2618 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
2619 return thread_id
, thread
2620 except db_base_Exception
as e
:
2621 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
2624 def get_datacenter_uuid(mydb
, tenant_id
, datacenter_id_name
):
2626 if utils
.check_valid_uuid(datacenter_id_name
):
2627 WHERE_dict
['d.uuid'] = datacenter_id_name
2629 WHERE_dict
['d.name'] = datacenter_id_name
2632 WHERE_dict
['nfvo_tenant_id'] = tenant_id
2633 from_
= "tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join datacenter_tenants as" \
2634 " dt on td.datacenter_tenant_id=dt.uuid"
2636 from_
= 'datacenters as d'
2637 vimaccounts
= mydb
.get_rows(FROM
=from_
, SELECT
=("d.uuid as uuid",), WHERE
=WHERE_dict
)
2638 if len(vimaccounts
) == 0:
2639 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
2640 elif len(vimaccounts
)>1:
2641 #print "nfvo.datacenter_action() error. Several datacenters found"
2642 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2643 return vimaccounts
[0]["uuid"]
2646 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
2647 datacenter_id
= None
2648 datacenter_name
= None
2649 if datacenter_id_name
:
2650 if utils
.check_valid_uuid(datacenter_id_name
):
2651 datacenter_id
= datacenter_id_name
2653 datacenter_name
= datacenter_id_name
2654 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
2656 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
2658 #print "nfvo.datacenter_action() error. Several datacenters found"
2659 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2660 return vims
.keys()[0], vims
.values()[0]
2664 '''Takes dict d and updates it with the values in dict u.'''
2665 '''It merges all depth levels'''
2666 for k
, v
in u
.iteritems():
2667 if isinstance(v
, collections
.Mapping
):
2668 r
= update(d
.get(k
, {}), v
)
2674 def create_instance(mydb
, tenant_id
, instance_dict
):
2675 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2676 # logger.debug("Creating instance...")
2677 scenario
= instance_dict
["scenario"]
2679 # find main datacenter
2681 myvim_threads_id
= {}
2682 datacenter
= instance_dict
.get("datacenter")
2683 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2684 myvims
[default_datacenter_id
] = vim
2685 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
2686 tenant
= mydb
.get_rows_by_id('nfvo_tenants', tenant_id
)
2687 # myvim_tenant = myvim['tenant_id']
2691 # print "Checking that the scenario exists and getting the scenario dictionary"
2692 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, datacenter_vim_id
=myvim_threads_id
[default_datacenter_id
],
2693 datacenter_id
=default_datacenter_id
)
2695 # logger.debug(">>>>>> Dictionaries before merging")
2696 # logger.debug(">>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
2697 # logger.debug(">>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
2699 db_instance_vnfs
= []
2700 db_instance_vms
= []
2701 db_instance_interfaces
= []
2706 instance_name
= instance_dict
["name"]
2707 instance_uuid
= str(uuid4())
2708 uuid_list
.append(instance_uuid
)
2709 db_instance_scenario
= {
2710 "uuid": instance_uuid
,
2711 "name": instance_name
,
2712 "tenant_id": tenant_id
,
2713 "scenario_id": scenarioDict
['uuid'],
2714 "datacenter_id": default_datacenter_id
,
2715 # filled bellow 'datacenter_tenant_id'
2716 "description": instance_dict
.get("description"),
2718 if scenarioDict
.get("cloud-config"):
2719 db_instance_scenario
["cloud_config"] = yaml
.safe_dump(scenarioDict
["cloud-config"],
2720 default_flow_style
=True, width
=256)
2721 instance_action_id
= get_task_id()
2722 db_instance_action
= {
2723 "uuid": instance_action_id
, # same uuid for the instance and the action on create
2724 "tenant_id": tenant_id
,
2725 "instance_id": instance_uuid
,
2726 "description": "CREATE",
2729 # Auxiliary dictionaries from x to y
2730 vnf_net2instance
= {}
2731 sce_net2instance
= {}
2732 net2task_id
= {'scenario': {}}
2734 # logger.debug("Creating instance from scenario-dict:\n%s",
2735 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
2737 # 0 check correct parameters
2738 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).iteritems():
2740 for scenario_net
in scenarioDict
['nets']:
2741 if net_name
== scenario_net
["name"]:
2745 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
),
2747 if "sites" not in net_instance_desc
:
2748 net_instance_desc
["sites"] = [ {} ]
2749 site_without_datacenter_field
= False
2750 for site
in net_instance_desc
["sites"]:
2751 if site
.get("datacenter"):
2752 site
["datacenter"] = get_datacenter_uuid(mydb
, tenant_id
, site
["datacenter"])
2753 if site
["datacenter"] not in myvims
:
2754 # Add this datacenter to myvims
2755 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
2757 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
2758 site
["datacenter"] = d
# change name to id
2760 if site_without_datacenter_field
:
2761 raise NfvoException("Found more than one entries without datacenter field at "
2762 "instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
2763 site_without_datacenter_field
= True
2764 site
["datacenter"] = default_datacenter_id
# change name to id
2766 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
2768 for scenario_vnf
in scenarioDict
['vnfs']:
2769 if vnf_name
== scenario_vnf
['name']:
2773 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
2774 if "datacenter" in vnf_instance_desc
:
2775 # Add this datacenter to myvims
2776 vnf_instance_desc
["datacenter"] = get_datacenter_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2777 if vnf_instance_desc
["datacenter"] not in myvims
:
2778 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2780 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2781 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
2783 # 0.1 parse cloud-config parameters
2784 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
2785 # We add the RO key to cloud_config
2786 if tenant
[0].get('RO_pub_key'):
2787 RO_key
= {"key-pairs": [tenant
[0]['RO_pub_key']]}
2788 cloud_config
= unify_cloud_config(cloud_config
, RO_key
)
2790 # 0.2 merge instance information into scenario
2791 # Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
2792 # However, this is not possible yet.
2793 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
2794 for scenario_net
in scenarioDict
['nets']:
2795 if net_name
== scenario_net
["name"]:
2796 if 'ip-profile' in net_instance_desc
:
2797 # translate from input format to database format
2798 ipprofile_in
= net_instance_desc
['ip-profile']
2800 ipprofile_db
['subnet_address'] = ipprofile_in
.get('subnet-address')
2801 ipprofile_db
['ip_version'] = ipprofile_in
.get('ip-version', 'IPv4')
2802 ipprofile_db
['gateway_address'] = ipprofile_in
.get('gateway-address')
2803 ipprofile_db
['dns_address'] = ipprofile_in
.get('dns-address')
2804 if isinstance(ipprofile_db
['dns_address'], (list, tuple)):
2805 ipprofile_db
['dns_address'] = ";".join(ipprofile_db
['dns_address'])
2806 if 'dhcp' in ipprofile_in
:
2807 ipprofile_db
['dhcp_start_address'] = ipprofile_in
['dhcp'].get('start-address')
2808 ipprofile_db
['dhcp_enabled'] = ipprofile_in
['dhcp'].get('enabled', True)
2809 ipprofile_db
['dhcp_count'] = ipprofile_in
['dhcp'].get('count' )
2810 if 'ip_profile' not in scenario_net
:
2811 scenario_net
['ip_profile'] = ipprofile_db
2813 update(scenario_net
['ip_profile'], ipprofile_db
)
2814 for interface
in net_instance_desc
.get('interfaces', () ):
2815 if 'ip_address' in interface
:
2816 for vnf
in scenarioDict
['vnfs']:
2817 if interface
['vnf'] == vnf
['name']:
2818 for vnf_interface
in vnf
['interfaces']:
2819 if interface
['vnf_interface'] == vnf_interface
['external_name']:
2820 vnf_interface
['ip_address']=interface
['ip_address']
2822 # logger.debug(">>>>>>>> Merged dictionary")
2823 # logger.debug("Creating instance scenario-dict MERGED:\n%s",
2824 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
2826 # 1. Creating new nets (sce_nets) in the VIM"
2827 db_instance_nets
= []
2828 for sce_net
in scenarioDict
['nets']:
2829 descriptor_net
= instance_dict
.get("networks", {}).get(sce_net
["name"], {})
2830 net_name
= descriptor_net
.get("vim-network-name")
2831 sce_net2instance
[sce_net
['uuid']] = {}
2832 net2task_id
['scenario'][sce_net
['uuid']] = {}
2834 sites
= descriptor_net
.get("sites", [ {} ])
2836 if site
.get("datacenter"):
2837 vim
= myvims
[ site
["datacenter"] ]
2838 datacenter_id
= site
["datacenter"]
2839 myvim_thread_id
= myvim_threads_id
[ site
["datacenter"] ]
2841 vim
= myvims
[ default_datacenter_id
]
2842 datacenter_id
= default_datacenter_id
2843 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2844 net_type
= sce_net
['type']
2845 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} # 'shared': True
2848 if sce_net
["external"]:
2849 net_name
= sce_net
["name"]
2851 net_name
= "{}.{}".format(instance_name
, sce_net
["name"])
2852 net_name
= net_name
[:255] # limit length
2854 if "netmap-use" in site
or "netmap-create" in site
:
2855 create_network
= False
2856 lookfor_network
= False
2857 if "netmap-use" in site
:
2858 lookfor_network
= True
2859 if utils
.check_valid_uuid(site
["netmap-use"]):
2860 filter_text
= "scenario id '%s'" % site
["netmap-use"]
2861 lookfor_filter
["id"] = site
["netmap-use"]
2863 filter_text
= "scenario name '%s'" % site
["netmap-use"]
2864 lookfor_filter
["name"] = site
["netmap-use"]
2865 if "netmap-create" in site
:
2866 create_network
= True
2867 net_vim_name
= net_name
2868 if site
["netmap-create"]:
2869 net_vim_name
= site
["netmap-create"]
2870 elif sce_net
["external"]:
2871 if sce_net
['vim_id'] != None:
2872 # there is a netmap at datacenter_nets database # TODO REVISE!!!!
2873 create_network
= False
2874 lookfor_network
= True
2875 lookfor_filter
["id"] = sce_net
['vim_id']
2876 filter_text
= "vim_id '{}' datacenter_netmap name '{}'. Try to reload vims with "\
2877 "datacenter-net-update".format(sce_net
['vim_id'], sce_net
["name"])
2878 # look for network at datacenter and return error
2880 # There is not a netmap, look at datacenter for a net with this name and create if not found
2881 create_network
= True
2882 lookfor_network
= True
2883 lookfor_filter
["name"] = sce_net
["name"]
2884 net_vim_name
= sce_net
["name"]
2885 filter_text
= "scenario name '%s'" % sce_net
["name"]
2887 net_vim_name
= net_name
2888 create_network
= True
2889 lookfor_network
= False
2893 task_action
= "CREATE"
2894 task_extra
["params"] = (net_vim_name
, net_type
, sce_net
.get('ip_profile', None))
2896 task_extra
["find"] = (lookfor_filter
,)
2897 elif lookfor_network
:
2898 task_action
= "FIND"
2899 task_extra
["params"] = (lookfor_filter
,)
2901 # fill database content
2902 net_uuid
= str(uuid4())
2903 uuid_list
.append(net_uuid
)
2904 sce_net2instance
[sce_net
['uuid']][datacenter_id
] = net_uuid
2908 "instance_scenario_id": instance_uuid
,
2909 "sce_net_id": sce_net
["uuid"],
2910 "created": create_network
,
2911 'datacenter_id': datacenter_id
,
2912 'datacenter_tenant_id': myvim_thread_id
,
2913 'status': 'BUILD' if create_network
else "ACTIVE"
2915 db_instance_nets
.append(db_net
)
2917 "instance_action_id": instance_action_id
,
2918 "status": "SCHEDULED",
2919 "task_index": task_index
,
2920 "datacenter_vim_id": myvim_thread_id
,
2921 "action": task_action
,
2922 "item": "instance_nets",
2923 "item_id": net_uuid
,
2924 "extra": yaml
.safe_dump(task_extra
, default_flow_style
=True, width
=256)
2926 net2task_id
['scenario'][sce_net
['uuid']][datacenter_id
] = task_index
2928 db_vim_actions
.append(db_vim_action
)
2930 if 'ip_profile' in sce_net
:
2932 'instance_net_id': net_uuid
,
2933 'ip_version': sce_net
['ip_profile']['ip_version'],
2934 'subnet_address': sce_net
['ip_profile']['subnet_address'],
2935 'gateway_address': sce_net
['ip_profile']['gateway_address'],
2936 'dns_address': sce_net
['ip_profile']['dns_address'],
2937 'dhcp_enabled': sce_net
['ip_profile']['dhcp_enabled'],
2938 'dhcp_start_address': sce_net
['ip_profile']['dhcp_start_address'],
2939 'dhcp_count': sce_net
['ip_profile']['dhcp_count'],
2941 db_ip_profiles
.append(db_ip_profile
)
2943 # 2. Creating new nets (vnf internal nets) in the VIM"
2944 # For each vnf net, we create it and we add it to instanceNetlist.
2945 for sce_vnf
in scenarioDict
['vnfs']:
2946 for net
in sce_vnf
['nets']:
2947 if sce_vnf
.get("datacenter"):
2948 datacenter_id
= sce_vnf
["datacenter"]
2949 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
2951 datacenter_id
= default_datacenter_id
2952 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2953 descriptor_net
= instance_dict
.get("vnfs", {}).get(sce_vnf
["name"], {})
2954 net_name
= descriptor_net
.get("name")
2956 net_name
= "{}.{}".format(instance_name
, net
["name"])
2957 net_name
= net_name
[:255] # limit length
2958 net_type
= net
['type']
2960 if sce_vnf
['uuid'] not in vnf_net2instance
:
2961 vnf_net2instance
[sce_vnf
['uuid']] = {}
2962 if sce_vnf
['uuid'] not in net2task_id
:
2963 net2task_id
[sce_vnf
['uuid']] = {}
2964 net2task_id
[sce_vnf
['uuid']][net
['uuid']] = task_index
2966 # fill database content
2967 net_uuid
= str(uuid4())
2968 uuid_list
.append(net_uuid
)
2969 vnf_net2instance
[sce_vnf
['uuid']][net
['uuid']] = net_uuid
2973 "instance_scenario_id": instance_uuid
,
2974 "net_id": net
["uuid"],
2976 'datacenter_id': datacenter_id
,
2977 'datacenter_tenant_id': myvim_thread_id
,
2979 db_instance_nets
.append(db_net
)
2982 "instance_action_id": instance_action_id
,
2983 "task_index": task_index
,
2984 "datacenter_vim_id": myvim_thread_id
,
2985 "status": "SCHEDULED",
2987 "item": "instance_nets",
2988 "item_id": net_uuid
,
2989 "extra": yaml
.safe_dump({"params": (net_name
, net_type
, net
.get('ip_profile',None))},
2990 default_flow_style
=True, width
=256)
2993 db_vim_actions
.append(db_vim_action
)
2995 if 'ip_profile' in net
:
2997 'instance_net_id': net_uuid
,
2998 'ip_version': net
['ip_profile']['ip_version'],
2999 'subnet_address': net
['ip_profile']['subnet_address'],
3000 'gateway_address': net
['ip_profile']['gateway_address'],
3001 'dns_address': net
['ip_profile']['dns_address'],
3002 'dhcp_enabled': net
['ip_profile']['dhcp_enabled'],
3003 'dhcp_start_address': net
['ip_profile']['dhcp_start_address'],
3004 'dhcp_count': net
['ip_profile']['dhcp_count'],
3006 db_ip_profiles
.append(db_ip_profile
)
3008 # print "vnf_net2instance:"
3009 # print yaml.safe_dump(vnf_net2instance, indent=4, default_flow_style=False)
3011 # 3. Creating new vm instances in the VIM
3012 # myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
3013 sce_vnf_list
= sorted(scenarioDict
['vnfs'], key
=lambda k
: k
['name'])
3014 for sce_vnf
in sce_vnf_list
:
3015 vnf_availability_zones
= []
3016 for vm
in sce_vnf
['vms']:
3017 vm_av
= vm
.get('availability_zone')
3018 if vm_av
and vm_av
not in vnf_availability_zones
:
3019 vnf_availability_zones
.append(vm_av
)
3021 # check if there is enough availability zones available at vim level.
3022 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
3023 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
3024 raise NfvoException('No enough availability zones at VIM for this deployment', HTTP_Bad_Request
)
3026 if sce_vnf
.get("datacenter"):
3027 vim
= myvims
[ sce_vnf
["datacenter"] ]
3028 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"] ]
3029 datacenter_id
= sce_vnf
["datacenter"]
3031 vim
= myvims
[ default_datacenter_id
]
3032 myvim_thread_id
= myvim_threads_id
[ default_datacenter_id
]
3033 datacenter_id
= default_datacenter_id
3034 sce_vnf
["datacenter_id"] = datacenter_id
3037 vnf_uuid
= str(uuid4())
3038 uuid_list
.append(vnf_uuid
)
3041 'instance_scenario_id': instance_uuid
,
3042 'vnf_id': sce_vnf
['vnf_id'],
3043 'sce_vnf_id': sce_vnf
['uuid'],
3044 'datacenter_id': datacenter_id
,
3045 'datacenter_tenant_id': myvim_thread_id
,
3047 db_instance_vnfs
.append(db_instance_vnf
)
3049 for vm
in sce_vnf
['vms']:
3051 myVMDict
['name'] = "{}.{}.{}".format(instance_name
[:64], sce_vnf
['name'][:64], vm
["name"][:64])
3052 myVMDict
['description'] = myVMDict
['name'][0:99]
3054 # myVMDict['start'] = "no"
3055 myVMDict
['name'] = myVMDict
['name'][0:255] # limit name length
3056 #create image at vim in case it not exist
3057 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
3058 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
3059 vm
['vim_image_id'] = image_id
3061 # create flavor at vim in case it not exist
3062 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
3063 if flavor_dict
['extended']!=None:
3064 flavor_dict
['extended'] = yaml
.load(flavor_dict
['extended'])
3065 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
3067 # Obtain information for additional disks
3068 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',), WHERE
={'vim_id': flavor_id
})
3069 if not extended_flavor_dict
:
3070 raise NfvoException("flavor '{}' not found".format(flavor_id
), HTTP_Not_Found
)
3073 # extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
3074 myVMDict
['disks'] = None
3075 extended_info
= extended_flavor_dict
[0]['extended']
3076 if extended_info
!= None:
3077 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
3078 if 'disks' in extended_flavor_dict_yaml
:
3079 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
3081 vm
['vim_flavor_id'] = flavor_id
3082 myVMDict
['imageRef'] = vm
['vim_image_id']
3083 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
3084 myVMDict
['availability_zone'] = vm
.get('availability_zone')
3085 myVMDict
['networks'] = []
3086 task_depends_on
= []
3087 # TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
3089 for iface
in vm
['interfaces']:
3091 if iface
['type']=="data":
3092 netDict
['type'] = iface
['model']
3093 elif "model" in iface
and iface
["model"]!=None:
3094 netDict
['model']=iface
['model']
3095 # TODO in future, remove this because mac_address will not be set, and the type of PV,VF
3096 # is obtained from iterface table model
3097 # discover type of interface looking at flavor
3098 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
3099 for flavor_iface
in numa
.get('interfaces',[]):
3100 if flavor_iface
.get('name') == iface
['internal_name']:
3101 if flavor_iface
['dedicated'] == 'yes':
3102 netDict
['type']="PF" #passthrough
3103 elif flavor_iface
['dedicated'] == 'no':
3104 netDict
['type']="VF" #siov
3105 elif flavor_iface
['dedicated'] == 'yes:sriov':
3106 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
3107 netDict
["mac_address"] = flavor_iface
.get("mac_address")
3109 netDict
["use"]=iface
['type']
3110 if netDict
["use"]=="data" and not netDict
.get("type"):
3111 #print "netDict", netDict
3112 #print "iface", iface
3113 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'])
3114 if flavor_dict
.get('extended')==None:
3115 raise NfvoException(e_text
+ "After database migration some information is not available. \
3116 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
3118 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
3119 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
3120 netDict
["type"]="virtual"
3121 if "vpci" in iface
and iface
["vpci"] is not None:
3122 netDict
['vpci'] = iface
['vpci']
3123 if "mac" in iface
and iface
["mac"] is not None:
3124 netDict
['mac_address'] = iface
['mac']
3125 if "port-security" in iface
and iface
["port-security"] is not None:
3126 netDict
['port_security'] = iface
['port-security']
3127 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
3128 netDict
['floating_ip'] = iface
['floating-ip']
3129 netDict
['name'] = iface
['internal_name']
3130 if iface
['net_id'] is None:
3131 for vnf_iface
in sce_vnf
["interfaces"]:
3134 if vnf_iface
['interface_id']==iface
['uuid']:
3135 netDict
['net_id'] = "TASK-{}".format(net2task_id
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
])
3136 instance_net_id
= sce_net2instance
[ vnf_iface
['sce_net_id'] ][datacenter_id
]
3137 task_depends_on
.append(net2task_id
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
])
3140 netDict
['net_id'] = "TASK-{}".format(net2task_id
[ sce_vnf
['uuid'] ][ iface
['net_id'] ])
3141 instance_net_id
= vnf_net2instance
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
3142 task_depends_on
.append(net2task_id
[sce_vnf
['uuid'] ][ iface
['net_id']])
3143 # skip bridge ifaces not connected to any net
3144 if 'net_id' not in netDict
or netDict
['net_id']==None:
3146 myVMDict
['networks'].append(netDict
)
3149 # 'instance_vm_id': instance_vm_uuid,
3150 "instance_net_id": instance_net_id
,
3151 'interface_id': iface
['uuid'],
3152 # 'vim_interface_id': ,
3153 'type': 'external' if iface
['external_name'] is not None else 'internal',
3154 'ip_address': iface
.get('ip_address'),
3155 'floating_ip': int(iface
.get('floating-ip', False)),
3156 'port_security': int(iface
.get('port-security', True))
3158 db_vm_ifaces
.append(db_vm_iface
)
3159 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3160 # print myVMDict['name']
3161 # print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
3162 # print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
3163 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3164 if vm
.get("boot_data"):
3165 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config
)
3167 cloud_config_vm
= cloud_config
3168 if myVMDict
.get('availability_zone'):
3169 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
3172 for vm_index
in range(0, vm
.get('count', 1)):
3174 if vm
.get('count', 1) > 1:
3175 vm_index_name
+= "." + chr(97 + vm_index
)
3176 task_params
= (myVMDict
['name']+vm_index_name
, myVMDict
['description'], myVMDict
.get('start', None),
3177 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'], cloud_config_vm
,
3178 myVMDict
['disks'], av_index
, vnf_availability_zones
)
3179 # put interface uuid back to scenario[vnfs][vms[[interfaces]
3180 for net
in myVMDict
['networks']:
3182 for iface
in vm
['interfaces']:
3183 if net
["name"]==iface
["internal_name"]:
3184 iface
["vim_id"]=net
["vim_id"]
3186 vm_uuid
= str(uuid4())
3187 uuid_list
.append(vm_uuid
)
3190 'instance_vnf_id': vnf_uuid
,
3191 #TODO delete "vim_vm_id": vm_id,
3192 "vm_id": vm
["uuid"],
3195 db_instance_vms
.append(db_vm
)
3198 for db_vm_iface
in db_vm_ifaces
:
3199 iface_uuid
= str(uuid4())
3200 uuid_list
.append(iface_uuid
)
3201 db_vm_iface_instance
= {
3203 "instance_vm_id": vm_uuid
3205 db_vm_iface_instance
.update(db_vm_iface
)
3206 if db_vm_iface_instance
.get("ip_address"): # increment ip_address
3207 ip
= db_vm_iface_instance
.get("ip_address")
3212 ip
= ip
[i
:] + str(int(ip
[:i
]) +1)
3213 db_vm_iface_instance
["ip_address"] = ip
3215 db_vm_iface_instance
["ip_address"] = None
3216 db_instance_interfaces
.append(db_vm_iface_instance
)
3217 myVMDict
['networks'][iface_index
]["uuid"] = iface_uuid
3221 "instance_action_id": instance_action_id
,
3222 "task_index": task_index
,
3223 "datacenter_vim_id": myvim_thread_id
,
3225 "status": "SCHEDULED",
3226 "item": "instance_vms",
3228 "extra": yaml
.safe_dump({"params": task_params
, "depends_on": task_depends_on
},
3229 default_flow_style
=True, width
=256)
3232 db_vim_actions
.append(db_vim_action
)
3234 scenarioDict
["datacenter2tenant"] = myvim_threads_id
3236 db_instance_action
["number_tasks"] = task_index
3237 db_instance_scenario
['datacenter_tenant_id'] = myvim_threads_id
[default_datacenter_id
]
3238 db_instance_scenario
['datacenter_id'] = default_datacenter_id
3240 {"instance_scenarios": db_instance_scenario
},
3241 {"instance_vnfs": db_instance_vnfs
},
3242 {"instance_nets": db_instance_nets
},
3243 {"ip_profiles": db_ip_profiles
},
3244 {"instance_vms": db_instance_vms
},
3245 {"instance_interfaces": db_instance_interfaces
},
3246 {"instance_actions": db_instance_action
},
3247 {"vim_actions": db_vim_actions
}
3250 logger
.debug("create_instance done DB tables: %s",
3251 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
3252 mydb
.new_rows(db_tables
, uuid_list
)
3253 for myvim_thread_id
in myvim_threads_id
.values():
3254 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
3256 returned_instance
= mydb
.get_instance_scenario(instance_uuid
)
3257 returned_instance
["action_id"] = instance_action_id
3258 return returned_instance
3259 except (NfvoException
, vimconn
.vimconnException
, db_base_Exception
) as e
:
3260 message
= rollback(mydb
, myvims
, rollbackList
)
3261 if isinstance(e
, db_base_Exception
):
3262 error_text
= "database Exception"
3263 elif isinstance(e
, vimconn
.vimconnException
):
3264 error_text
= "VIM Exception"
3266 error_text
= "Exception"
3267 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
3268 # logger.error("create_instance: %s", error_text)
3269 raise NfvoException(error_text
, e
.http_code
)
3272 def delete_instance(mydb
, tenant_id
, instance_id
):
3273 # print "Checking that the instance_id exists and getting the instance dictionary"
3274 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
3275 # print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
3276 tenant_id
= instanceDict
["tenant_id"]
3277 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
3279 # 1. Delete from Database
3280 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
3282 # 2. delete from VIM
3286 vimthread_affected
= {}
3287 net2vm_dependencies
= {}
3290 instance_action_id
= get_task_id()
3292 db_instance_action
= {
3293 "uuid": instance_action_id
, # same uuid for the instance and the action on create
3294 "tenant_id": tenant_id
,
3295 "instance_id": instance_id
,
3296 "description": "DELETE",
3297 # "number_tasks": 0 # filled bellow
3302 for sce_vnf
in instanceDict
['vnfs']:
3303 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
3304 vimthread_affected
[sce_vnf
["datacenter_tenant_id"]] = None
3305 if datacenter_key
not in myvims
:
3307 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
3308 except NfvoException
as e
:
3309 logger
.error(str(e
))
3311 myvim_threads
[datacenter_key
] = myvim_thread
3312 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
3313 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
3315 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
3316 sce_vnf
["datacenter_tenant_id"]))
3317 myvims
[datacenter_key
] = None
3319 myvims
[datacenter_key
] = vims
.values()[0]
3320 myvim
= myvims
[datacenter_key
]
3321 myvim_thread
= myvim_threads
[datacenter_key
]
3322 for vm
in sce_vnf
['vms']:
3324 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
3327 "instance_action_id": instance_action_id
,
3328 "task_index": task_index
,
3329 "datacenter_vim_id": sce_vnf
["datacenter_tenant_id"],
3331 "status": "SCHEDULED",
3332 "item": "instance_vms",
3333 "item_id": vm
["uuid"],
3334 "extra": yaml
.safe_dump({"params": vm
["interfaces"]},
3335 default_flow_style
=True, width
=256)
3337 db_vim_actions
.append(db_vim_action
)
3338 for interface
in vm
["interfaces"]:
3339 if not interface
.get("instance_net_id"):
3341 if interface
["instance_net_id"] not in net2vm_dependencies
:
3342 net2vm_dependencies
[interface
["instance_net_id"]] = []
3343 net2vm_dependencies
[interface
["instance_net_id"]].append(task_index
)
3348 for net
in instanceDict
['nets']:
3349 vimthread_affected
[net
["datacenter_tenant_id"]] = None
3350 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
3351 if datacenter_key
not in myvims
:
3353 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
3354 except NfvoException
as e
:
3355 logger
.error(str(e
))
3357 myvim_threads
[datacenter_key
] = myvim_thread
3358 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
3359 datacenter_tenant_id
=net
["datacenter_tenant_id"])
3361 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
3362 myvims
[datacenter_key
] = None
3364 myvims
[datacenter_key
] = vims
.values()[0]
3365 myvim
= myvims
[datacenter_key
]
3366 myvim_thread
= myvim_threads
[datacenter_key
]
3369 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
3371 extra
= {"params": (net
['vim_net_id'], net
['sdn_net_id'])}
3372 if net2vm_dependencies
.get(net
["uuid"]):
3373 extra
["depends_on"] = net2vm_dependencies
[net
["uuid"]]
3375 "instance_action_id": instance_action_id
,
3376 "task_index": task_index
,
3377 "datacenter_vim_id": net
["datacenter_tenant_id"],
3379 "status": "SCHEDULED",
3380 "item": "instance_nets",
3381 "item_id": net
["uuid"],
3382 "extra": yaml
.safe_dump(extra
, default_flow_style
=True, width
=256)
3385 db_vim_actions
.append(db_vim_action
)
3387 db_instance_action
["number_tasks"] = task_index
3389 {"instance_actions": db_instance_action
},
3390 {"vim_actions": db_vim_actions
}
3393 logger
.debug("delete_instance done DB tables: %s",
3394 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
3395 mydb
.new_rows(db_tables
, ())
3396 for myvim_thread_id
in vimthread_affected
.keys():
3397 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
3399 if len(error_msg
) > 0:
3400 return 'action_id={} instance {} deleted but some elements could not be deleted, or already deleted '\
3401 '(error: 404) from VIM: {}'.format(instance_action_id
, message
, error_msg
)
3403 return "action_id={} instance {} deleted".format(instance_action_id
, message
)
3406 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
3407 '''Refreshes a scenario instance. It modifies instanceDict'''
3409 - 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
3412 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
3413 # #print "nfvo.refresh_instance begins"
3414 # #print json.dumps(instanceDict, indent=4)
3416 # #print "Getting the VIM URL and the VIM tenant_id"
3419 # # 1. Getting VIM vm and net list
3420 # vms_updated = [] #List of VM instance uuids in openmano that were updated
3423 # for sce_vnf in instanceDict['vnfs']:
3424 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
3425 # if datacenter_key not in vm_list:
3426 # vm_list[datacenter_key] = []
3427 # if datacenter_key not in myvims:
3428 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
3429 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
3430 # if len(vims) == 0:
3431 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
3432 # myvims[datacenter_key] = None
3434 # myvims[datacenter_key] = vims.values()[0]
3435 # for vm in sce_vnf['vms']:
3436 # vm_list[datacenter_key].append(vm['vim_vm_id'])
3437 # vms_notupdated.append(vm["uuid"])
3439 # nets_updated = [] #List of VM instance uuids in openmano that were updated
3440 # nets_notupdated=[]
3442 # for net in instanceDict['nets']:
3443 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
3444 # if datacenter_key not in net_list:
3445 # net_list[datacenter_key] = []
3446 # if datacenter_key not in myvims:
3447 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
3448 # datacenter_tenant_id=net["datacenter_tenant_id"])
3449 # if len(vims) == 0:
3450 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
3451 # myvims[datacenter_key] = None
3453 # myvims[datacenter_key] = vims.values()[0]
3455 # net_list[datacenter_key].append(net['vim_net_id'])
3456 # nets_notupdated.append(net["uuid"])
3458 # # 1. Getting the status of all VMs
3460 # for datacenter_key in myvims:
3461 # if not vm_list.get(datacenter_key):
3465 # if not myvims[datacenter_key]:
3466 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
3469 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
3471 # except vimconn.vimconnException as e:
3472 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
3473 # failed_message = str(e)
3475 # for vm in vm_list[datacenter_key]:
3476 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
3478 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
3479 # for sce_vnf in instanceDict['vnfs']:
3480 # for vm in sce_vnf['vms']:
3481 # vm_id = vm['vim_vm_id']
3482 # interfaces = vm_dict[vm_id].pop('interfaces', [])
3483 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
3484 # has_mgmt_iface = False
3485 # for iface in vm["interfaces"]:
3486 # if iface["type"]=="mgmt":
3487 # has_mgmt_iface = True
3488 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
3489 # vm_dict[vm_id]['status'] = "ACTIVE"
3490 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
3491 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
3492 # 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'):
3493 # vm['status'] = vm_dict[vm_id]['status']
3494 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
3495 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
3496 # # 2.1. Update in openmano DB the VMs whose status changed
3498 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
3499 # vms_notupdated.remove(vm["uuid"])
3501 # vms_updated.append(vm["uuid"])
3502 # except db_base_Exception as e:
3503 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
3504 # # 2.2. Update in openmano DB the interface VMs
3505 # for interface in interfaces:
3506 # #translate from vim_net_id to instance_net_id
3507 # network_id_list=[]
3508 # for net in instanceDict['nets']:
3509 # if net["vim_net_id"] == interface["vim_net_id"]:
3510 # network_id_list.append(net["uuid"])
3511 # if not network_id_list:
3513 # del interface["vim_net_id"]
3515 # for network_id in network_id_list:
3516 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
3517 # except db_base_Exception as e:
3518 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
3520 # # 3. Getting the status of all nets
3522 # for datacenter_key in myvims:
3523 # if not net_list.get(datacenter_key):
3526 # failed_message = ""
3527 # if not myvims[datacenter_key]:
3528 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
3531 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
3533 # except vimconn.vimconnException as e:
3534 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
3535 # failed_message = str(e)
3537 # for net in net_list[datacenter_key]:
3538 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
3540 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
3541 # # TODO: update nets inside a vnf
3542 # for net in instanceDict['nets']:
3543 # net_id = net['vim_net_id']
3544 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
3545 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
3546 # 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'):
3547 # net['status'] = net_dict[net_id]['status']
3548 # net['error_msg'] = net_dict[net_id].get('error_msg')
3549 # net['vim_info'] = net_dict[net_id].get('vim_info')
3550 # # 5.1. Update in openmano DB the nets whose status changed
3552 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
3553 # nets_notupdated.remove(net["uuid"])
3555 # nets_updated.append(net["uuid"])
3556 # except db_base_Exception as e:
3557 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
3559 # # Returns appropriate output
3560 # #print "nfvo.refresh_instance finishes"
3561 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
3562 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
3563 instance_id
= instanceDict
['uuid']
3564 # if len(vms_notupdated)+len(nets_notupdated)>0:
3565 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
3566 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
3568 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
3570 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
3571 #print "Checking that the instance_id exists and getting the instance dictionary"
3572 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
3573 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
3575 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
3576 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
3578 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
3579 myvim
= vims
.values()[0]
3581 if action_dict
.get("create-vdu"):
3582 for vdu
in action_dict
["create-vdu"]:
3583 vdu_id
= vdu
.get("vdu-id")
3584 vdu_count
= vdu
.get("count", 1)
3585 # get from database TODO
3589 input_vnfs
= action_dict
.pop("vnfs", [])
3590 input_vms
= action_dict
.pop("vms", [])
3591 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
3595 for sce_vnf
in instanceDict
['vnfs']:
3596 for vm
in sce_vnf
['vms']:
3597 if not action_over_all
:
3598 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
3599 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
3602 if "add_public_key" in action_dict
:
3604 if sce_vnf
.get('mgmt_access'):
3605 mgmt_access
= yaml
.load(sce_vnf
['mgmt_access'])
3606 ssh_access
= mgmt_access
['config-access']['ssh-access']
3607 tenant
= mydb
.get_rows_by_id('nfvo_tenants', nfvo_tenant
)
3609 if ssh_access
['required'] and ssh_access
['default-user']:
3610 if 'ip_address' in vm
:
3611 mgmt_ip
= vm
['ip_address'].split(';')
3612 password
= mgmt_access
['config-access'].get('password')
3613 priv_RO_key
= decrypt_key(tenant
[0]['encrypted_RO_priv_key'], tenant
[0]['uuid'])
3614 myvim
.inject_user_key(mgmt_ip
[0], ssh_access
['default-user'],
3615 action_dict
['add_public_key'],
3616 password
=password
, ro_key
=priv_RO_key
)
3618 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
3619 HTTP_Internal_Server_Error
)
3621 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
3622 HTTP_Internal_Server_Error
)
3624 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
3625 HTTP_Internal_Server_Error
)
3627 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
3628 if "console" in action_dict
:
3629 if not global_config
["http_console_proxy"]:
3630 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
3631 "description": "{protocol}//{ip}:{port}/{suffix}".format(
3632 protocol
=data
["protocol"],
3633 ip
= data
["server"],
3634 port
= data
["port"],
3635 suffix
= data
["suffix"]),
3639 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
3640 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
3641 "description": "this console is only reachable by local interface",
3646 #print "console data", data
3648 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
3649 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
3650 "description": "{protocol}//{ip}:{port}/{suffix}".format(
3651 protocol
=data
["protocol"],
3652 ip
= global_config
["http_console_host"],
3653 port
= console_thread
.port
,
3654 suffix
= data
["suffix"]),
3658 except NfvoException
as e
:
3659 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
3663 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
3665 except vimconn
.vimconnException
as e
:
3666 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
3669 if vm_ok
==0: #all goes wrong
3674 def instance_action_get(mydb
, nfvo_tenant
, instance_id
, action_id
):
3676 if nfvo_tenant
and nfvo_tenant
!= "any":
3677 filter["tenant_id"] = nfvo_tenant
3678 if instance_id
and instance_id
!= "any":
3679 filter["instance_id"] = instance_id
3681 filter["uuid"] = action_id
3682 rows
= mydb
.get_rows(FROM
="instance_actions", WHERE
=filter)
3683 if not rows
and action_id
:
3684 raise NfvoException("Not found any action with this criteria", HTTP_Not_Found
)
3685 return {"ations": rows
}
3688 def create_or_use_console_proxy_thread(console_server
, console_port
):
3689 #look for a non-used port
3690 console_thread_key
= console_server
+ ":" + str(console_port
)
3691 if console_thread_key
in global_config
["console_thread"]:
3692 #global_config["console_thread"][console_thread_key].start_timeout()
3693 return global_config
["console_thread"][console_thread_key
]
3695 for port
in global_config
["console_port_iterator"]():
3696 #print "create_or_use_console_proxy_thread() port:", port
3697 if port
in global_config
["console_ports"]:
3700 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
3702 global_config
["console_thread"][console_thread_key
] = clithread
3703 global_config
["console_ports"][port
] = console_thread_key
3705 except cli
.ConsoleProxyExceptionPortUsed
as e
:
3706 #port used, try with onoher
3708 except cli
.ConsoleProxyException
as e
:
3709 raise NfvoException(str(e
), HTTP_Bad_Request
)
3710 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
3713 def check_tenant(mydb
, tenant_id
):
3714 '''check that tenant exists at database'''
3715 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
3717 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
3720 def new_tenant(mydb
, tenant_dict
):
3722 tenant_uuid
= str(uuid4())
3723 tenant_dict
['uuid'] = tenant_uuid
3725 pub_key
, priv_key
= create_RO_keypair(tenant_uuid
)
3726 tenant_dict
['RO_pub_key'] = pub_key
3727 tenant_dict
['encrypted_RO_priv_key'] = priv_key
3728 mydb
.new_row("nfvo_tenants", tenant_dict
, confidential_data
=True)
3729 except db_base_Exception
as e
:
3730 raise NfvoException("Error creating the new tenant: {} ".format(tenant_dict
['name']) + str(e
), HTTP_Internal_Server_Error
)
3733 def delete_tenant(mydb
, tenant
):
3734 #get nfvo_tenant info
3736 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
3737 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
3738 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
3741 def new_datacenter(mydb
, datacenter_descriptor
):
3742 if "config" in datacenter_descriptor
:
3743 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
3744 #Check that datacenter-type is correct
3745 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
3748 module
= "vimconn_" + datacenter_type
3749 pkg
= __import__("osm_ro." + module
)
3750 vim_conn
= getattr(pkg
, module
)
3751 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
3752 except (IOError, ImportError):
3753 # if module_info and module_info[0]:
3754 # file.close(module_info[0])
3755 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
3757 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True, confidential_data
=True)
3758 return datacenter_id
3761 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
3762 # obtain data, check that only one exist
3763 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
3766 datacenter_id
= datacenter
['uuid']
3767 where
={'uuid': datacenter
['uuid']}
3768 remove_port_mapping
= False
3769 if "config" in datacenter_descriptor
:
3770 if datacenter_descriptor
['config'] != None:
3772 new_config_dict
= datacenter_descriptor
["config"]
3775 for k
in new_config_dict
:
3776 if new_config_dict
[k
] == None:
3778 if k
== 'sdn-controller':
3779 remove_port_mapping
= True
3781 config_text
= datacenter
.get("config")
3784 config_dict
= yaml
.load(config_text
)
3785 config_dict
.update(new_config_dict
)
3789 except Exception as e
:
3790 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
3792 datacenter_descriptor
["config"] = yaml
.safe_dump(config_dict
, default_flow_style
=True, width
=256)
3794 datacenter_descriptor
["config"] = None
3795 if remove_port_mapping
:
3797 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_id
)
3798 except ovimException
as e
:
3799 logger
.error("Error deleting datacenter-port-mapping " + str(e
))
3801 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
3802 return datacenter_id
3805 def delete_datacenter(mydb
, datacenter
):
3806 #get nfvo_tenant info
3807 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
3808 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
3810 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_dict
['uuid'])
3811 except ovimException
as e
:
3812 logger
.error("Error deleting datacenter-port-mapping " + str(e
))
3813 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
3816 def associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter
, vim_tenant_id
=None, vim_tenant_name
=None, vim_username
=None, vim_password
=None, config
=None):
3817 # get datacenter info
3819 datacenter_id
= get_datacenter_uuid(mydb
, None, datacenter
)
3821 create_vim_tenant
= True if not vim_tenant_id
and not vim_tenant_name
else False
3823 # get nfvo_tenant info
3824 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
3825 if vim_tenant_name
==None:
3826 vim_tenant_name
=tenant_dict
['name']
3828 #check that this association does not exist before
3829 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
3830 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
3831 if len(tenants_datacenters
)>0:
3832 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
3834 vim_tenant_id_exist_atdb
=False
3835 if not create_vim_tenant
:
3836 where_
={"datacenter_id": datacenter_id
}
3837 if vim_tenant_id
!=None:
3838 where_
["vim_tenant_id"] = vim_tenant_id
3839 if vim_tenant_name
!=None:
3840 where_
["vim_tenant_name"] = vim_tenant_name
3841 #check if vim_tenant_id is already at database
3842 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
3843 if len(datacenter_tenants_dict
)>=1:
3844 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
3845 vim_tenant_id_exist_atdb
=True
3846 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
3848 datacenter_tenants_dict
= {}
3849 #insert at table datacenter_tenants
3850 else: #if vim_tenant_id==None:
3851 #create tenant at VIM if not provided
3853 _
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
, vim_user
=vim_username
,
3854 vim_passwd
=vim_password
)
3855 datacenter_name
= myvim
["name"]
3856 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
3857 except vimconn
.vimconnException
as e
:
3858 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
3859 datacenter_tenants_dict
= {}
3860 datacenter_tenants_dict
["created"]="true"
3862 #fill datacenter_tenants table
3863 if not vim_tenant_id_exist_atdb
:
3864 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
3865 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
3866 datacenter_tenants_dict
["user"] = vim_username
3867 datacenter_tenants_dict
["passwd"] = vim_password
3868 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
3870 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
3871 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True, confidential_data
=True)
3872 datacenter_tenants_dict
["uuid"] = id_
3874 #fill tenants_datacenters table
3875 datacenter_tenant_id
= datacenter_tenants_dict
["uuid"]
3876 tenants_datacenter_dict
["datacenter_tenant_id"] = datacenter_tenant_id
3877 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
3879 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_dict
['uuid'], datacenter_id
) # reload data
3880 datacenter_name
= myvim
["name"]
3881 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
3882 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, datacenter_name
, datacenter_tenant_id
,
3883 db
=db
, db_lock
=db_lock
, ovim
=ovim
)
3885 thread_id
= datacenter_tenants_dict
["uuid"]
3886 vim_threads
["running"][thread_id
] = new_thread
3887 return datacenter_id
3888 except vimconn
.vimconnException
as e
:
3889 raise NfvoException(str(e
), HTTP_Bad_Request
)
3892 def edit_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=None, vim_tenant_name
=None,
3893 vim_username
=None, vim_password
=None, config
=None):
3894 #Obtain the data of this datacenter_tenant_id
3895 vim_data
= mydb
.get_rows(
3896 SELECT
=("datacenter_tenants.vim_tenant_name", "datacenter_tenants.vim_tenant_id", "datacenter_tenants.user",
3897 "datacenter_tenants.passwd", "datacenter_tenants.config"),
3898 FROM
="datacenter_tenants JOIN tenants_datacenters ON datacenter_tenants.uuid=tenants_datacenters.datacenter_tenant_id",
3899 WHERE
={"tenants_datacenters.nfvo_tenant_id": nfvo_tenant
,
3900 "tenants_datacenters.datacenter_id": datacenter_id
})
3902 logger
.debug(str(vim_data
))
3903 if len(vim_data
) < 1:
3904 raise NfvoException("Datacenter {} is not attached for tenant {}".format(datacenter_id
, nfvo_tenant
), HTTP_Conflict
)
3908 v
['config'] = yaml
.load(v
['config'])
3911 v
['vim_tenant_id'] = vim_tenant_id
3913 v
['vim_tenant_name'] = vim_tenant_name
3915 v
['user'] = vim_username
3917 v
['passwd'] = vim_password
3921 v
['config'].update(config
)
3923 logger
.debug(str(v
))
3924 deassociate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'])
3925 associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'], vim_tenant_name
=v
['vim_tenant_name'],
3926 vim_username
=v
['user'], vim_password
=v
['passwd'], config
=v
['config'])
3928 return datacenter_id
3930 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
3931 #get nfvo_tenant info
3932 if not tenant_id
or tenant_id
=="any":
3935 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
3936 tenant_uuid
= tenant_dict
['uuid']
3938 datacenter_id
= get_datacenter_uuid(mydb
, tenant_uuid
, datacenter
)
3939 #check that this association exist before
3940 tenants_datacenter_dict
={"datacenter_id": datacenter_id
}
3942 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
3943 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
3944 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
3945 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
3947 #delete this association
3948 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
3950 #get vim_tenant info and deletes
3952 for tenant_datacenter_item
in tenant_datacenter_list
:
3953 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
3954 #try to delete vim:tenant
3956 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
3957 if vim_tenant_dict
['created']=='true':
3958 #delete tenant at VIM if created by NFVO
3960 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3961 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
3962 except vimconn
.vimconnException
as e
:
3963 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
3964 logger
.warn(warning
)
3965 except db_base_Exception
as e
:
3966 logger
.error("Cannot delete datacenter_tenants " + str(e
))
3967 pass # the error will be caused because dependencies, vim_tenant can not be deleted
3968 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
3969 thread
= vim_threads
["running"][thread_id
]
3970 thread
.insert_task("exit")
3971 vim_threads
["deleting"][thread_id
] = thread
3972 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
3975 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
3977 #get datacenter info
3978 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3980 if 'net-update' in action_dict
:
3982 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
3984 except vimconn
.vimconnException
as e
:
3985 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
3986 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
3987 #update nets Change from VIM format to NFVO format
3990 net_nfvo
={'datacenter_id': datacenter_id
}
3991 net_nfvo
['name'] = net
['name']
3992 #net_nfvo['description']= net['name']
3993 net_nfvo
['vim_net_id'] = net
['id']
3994 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
3995 net_nfvo
['shared'] = net
['shared']
3996 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
3997 net_list
.append(net_nfvo
)
3998 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
3999 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
4001 elif 'net-edit' in action_dict
:
4002 net
= action_dict
['net-edit'].pop('net')
4003 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
4004 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
4005 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
4007 elif 'net-delete' in action_dict
:
4008 net
= action_dict
['net-deelte'].get('net')
4009 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
4010 result
= mydb
.delete_row(FROM
='datacenter_nets',
4011 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
4015 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
4018 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
4019 #get datacenter info
4020 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4022 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
4023 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
4024 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
4028 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
4029 #get datacenter info
4030 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4033 action_dict
= action_dict
["netmap"]
4034 if 'vim_id' in action_dict
:
4035 filter_dict
["id"] = action_dict
['vim_id']
4036 if 'vim_name' in action_dict
:
4037 filter_dict
["name"] = action_dict
['vim_name']
4039 filter_dict
["shared"] = True
4042 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
4043 except vimconn
.vimconnException
as e
:
4044 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
4045 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
4046 if len(vim_nets
)>1 and action_dict
:
4047 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
4048 elif len(vim_nets
)==0: # and action_dict:
4049 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
4051 for net
in vim_nets
:
4052 net_nfvo
={'datacenter_id': datacenter_id
}
4053 if action_dict
and "name" in action_dict
:
4054 net_nfvo
['name'] = action_dict
['name']
4056 net_nfvo
['name'] = net
['name']
4057 #net_nfvo['description']= net['name']
4058 net_nfvo
['vim_net_id'] = net
['id']
4059 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
4060 net_nfvo
['shared'] = net
['shared']
4061 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
4063 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
4064 net_nfvo
["status"] = "OK"
4065 net_nfvo
["uuid"] = net_id
4066 except db_base_Exception
as e
:
4070 net_nfvo
["status"] = "FAIL: " + str(e
)
4071 net_list
.append(net_nfvo
)
4074 def get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
):
4075 # obtain all network data
4077 if utils
.check_valid_uuid(network_id
):
4078 filter_dict
= {"id": network_id
}
4080 filter_dict
= {"name": network_id
}
4082 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4083 network
= myvim
.get_network_list(filter_dict
=filter_dict
)
4084 except vimconn
.vimconnException
as e
:
4085 raise NfvoException("Not possible to get_sdn_net_id from VIM: {}".format(str(e
)), e
.http_code
)
4087 # ensure the network is defined
4088 if len(network
) == 0:
4089 raise NfvoException("Network {} is not present in the system".format(network_id
),
4092 # ensure there is only one network with the provided name
4093 if len(network
) > 1:
4094 raise NfvoException("Multiple networks present in vim identified by {}".format(network_id
), HTTP_Bad_Request
)
4096 # ensure it is a dataplane network
4097 if network
[0]['type'] != 'data':
4100 # ensure we use the id
4101 network_id
= network
[0]['id']
4103 # search in dabase mano_db in table instance nets for the sdn_net_id that corresponds to the vim_net_id==network_id
4104 # and with instance_scenario_id==NULL
4105 #search_dict = {'vim_net_id': network_id, 'instance_scenario_id': None}
4106 search_dict
= {'vim_net_id': network_id
}
4109 #sdn_network_id = mydb.get_rows(SELECT=('sdn_net_id',), FROM='instance_nets', WHERE=search_dict)[0]['sdn_net_id']
4110 result
= mydb
.get_rows(SELECT
=('sdn_net_id',), FROM
='instance_nets', WHERE
=search_dict
)
4111 except db_base_Exception
as e
:
4112 raise NfvoException("db_base_Exception obtaining SDN network to associated to vim network {}".format(
4113 network_id
) + str(e
), HTTP_Internal_Server_Error
)
4117 if net
['sdn_net_id'] != None:
4119 sdn_net_id
= net
['sdn_net_id']
4121 if sdn_net_counter
== 0:
4123 elif sdn_net_counter
== 1:
4126 raise NfvoException("More than one SDN network is associated to vim network {}".format(
4127 network_id
), HTTP_Internal_Server_Error
)
4129 def get_sdn_controller_id(mydb
, datacenter
):
4130 # Obtain sdn controller id
4131 config
= mydb
.get_rows(SELECT
=('config',), FROM
='datacenters', WHERE
={'uuid': datacenter
})[0].get('config', '{}')
4135 return yaml
.load(config
).get('sdn-controller')
4137 def vim_net_sdn_attach(mydb
, tenant_id
, datacenter
, network_id
, descriptor
):
4139 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
4140 if not sdn_network_id
:
4141 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
), HTTP_Internal_Server_Error
)
4143 #Obtain sdn controller id
4144 controller_id
= get_sdn_controller_id(mydb
, datacenter
)
4145 if not controller_id
:
4146 raise NfvoException("No SDN controller is set for datacenter {}".format(datacenter
), HTTP_Internal_Server_Error
)
4148 #Obtain sdn controller info
4149 sdn_controller
= ovim
.show_of_controller(controller_id
)
4152 'name': 'external_port',
4153 'net_id': sdn_network_id
,
4154 'ofc_id': controller_id
,
4155 'switch_dpid': sdn_controller
['dpid'],
4156 'switch_port': descriptor
['port']
4159 if 'vlan' in descriptor
:
4160 port_data
['vlan'] = descriptor
['vlan']
4161 if 'mac' in descriptor
:
4162 port_data
['mac'] = descriptor
['mac']
4164 result
= ovim
.new_port(port_data
)
4165 except ovimException
as e
:
4166 raise NfvoException("ovimException attaching SDN network {} to vim network {}".format(
4167 sdn_network_id
, network_id
) + str(e
), HTTP_Internal_Server_Error
)
4168 except db_base_Exception
as e
:
4169 raise NfvoException("db_base_Exception attaching SDN network to vim network {}".format(
4170 network_id
) + str(e
), HTTP_Internal_Server_Error
)
4172 return 'Port uuid: '+ result
4174 def vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, network_id
, port_id
=None):
4176 filter = {'uuid': port_id
}
4178 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
4179 if not sdn_network_id
:
4180 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
),
4181 HTTP_Internal_Server_Error
)
4182 #in case no port_id is specified only ports marked as 'external_port' will be detached
4183 filter = {'name': 'external_port', 'net_id': sdn_network_id
}
4186 port_list
= ovim
.get_ports(columns
={'uuid'}, filter=filter)
4187 except ovimException
as e
:
4188 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
4189 HTTP_Internal_Server_Error
)
4191 if len(port_list
) == 0:
4192 raise NfvoException("No ports attached to the network {} were found with the requested criteria".format(network_id
),
4196 for port
in port_list
:
4198 port_uuid_list
.append(port
['uuid'])
4199 ovim
.delete_port(port
['uuid'])
4200 except ovimException
as e
:
4201 raise NfvoException("ovimException deleting port {} for net {}. ".format(port
['uuid'], network_id
) + str(e
), HTTP_Internal_Server_Error
)
4203 return 'Detached ports uuid: {}'.format(','.join(port_uuid_list
))
4205 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
4206 #get datacenter info
4207 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4210 if utils
.check_valid_uuid(name
):
4211 filter_dict
["id"] = name
4213 filter_dict
["name"] = name
4215 if item
=="networks":
4216 #filter_dict['tenant_id'] = myvim['tenant_id']
4217 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
4219 if len(content
) == 0:
4220 raise NfvoException("Network {} is not present in the system. ".format(name
),
4223 #Update the networks with the attached ports
4225 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, net
['id'])
4226 if sdn_network_id
!= None:
4228 #port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan'}, filter={'name': 'external_port', 'net_id': sdn_network_id})
4229 port_list
= ovim
.get_ports(columns
={'uuid', 'switch_port', 'vlan','name'}, filter={'net_id': sdn_network_id
})
4230 except ovimException
as e
:
4231 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
), HTTP_Internal_Server_Error
)
4232 #Remove field name and if port name is external_port save it as 'type'
4233 for port
in port_list
:
4234 if port
['name'] == 'external_port':
4235 port
['type'] = "External"
4237 net
['sdn_network_id'] = sdn_network_id
4238 net
['sdn_attached_ports'] = port_list
4240 elif item
=="tenants":
4241 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
4242 elif item
== "images":
4244 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
4246 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
4247 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
4248 if name
and len(content
)==1:
4249 return {item
[:-1]: content
[0]}
4250 elif name
and len(content
)==0:
4251 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
4254 return {item
: content
}
4255 except vimconn
.vimconnException
as e
:
4256 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
4257 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
4260 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
4261 #get datacenter info
4262 if tenant_id
== "any":
4265 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4267 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
4268 logger
.debug("vim_action_delete vim response: " + str(content
))
4269 items
= content
.values()[0]
4270 if type(items
)==list and len(items
)==0:
4271 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
4272 elif type(items
)==list and len(items
)>1:
4273 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
4274 else: # it is a dict
4275 item_id
= items
["id"]
4276 item_name
= str(items
.get("name"))
4279 if item
=="networks":
4280 # If there is a SDN network associated to the vim-network, proceed to clear the relationship and delete it
4281 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, item_id
)
4282 if sdn_network_id
!= None:
4283 #Delete any port attachment to this network
4285 port_list
= ovim
.get_ports(columns
={'uuid'}, filter={'net_id': sdn_network_id
})
4286 except ovimException
as e
:
4287 raise NfvoException(
4288 "ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
4289 HTTP_Internal_Server_Error
)
4291 # By calling one by one all ports to be detached we ensure that not only the external_ports get detached
4292 for port
in port_list
:
4293 vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, item_id
, port
['uuid'])
4295 #Delete from 'instance_nets' the correspondence between the vim-net-id and the sdn-net-id
4297 mydb
.delete_row(FROM
='instance_nets', WHERE
={'instance_scenario_id': None, 'sdn_net_id': sdn_network_id
, 'vim_net_id': item_id
})
4298 except db_base_Exception
as e
:
4299 raise NfvoException("Error deleting correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
4300 str(e
), HTTP_Internal_Server_Error
)
4302 #Delete the SDN network
4304 ovim
.delete_network(sdn_network_id
)
4305 except ovimException
as e
:
4306 logger
.error("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
), exc_info
=True)
4307 raise NfvoException("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
),
4308 HTTP_Internal_Server_Error
)
4310 content
= myvim
.delete_network(item_id
)
4311 elif item
=="tenants":
4312 content
= myvim
.delete_tenant(item_id
)
4313 elif item
== "images":
4314 content
= myvim
.delete_image(item_id
)
4316 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
4317 except vimconn
.vimconnException
as e
:
4318 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
4319 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
4321 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
4324 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
4325 #get datacenter info
4326 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
4327 if tenant_id
== "any":
4329 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4331 if item
=="networks":
4332 net
= descriptor
["network"]
4333 net_name
= net
.pop("name")
4334 net_type
= net
.pop("type", "bridge")
4335 net_public
= net
.pop("shared", False)
4336 net_ipprofile
= net
.pop("ip_profile", None)
4337 net_vlan
= net
.pop("vlan", None)
4338 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
4340 #If the datacenter has a SDN controller defined and the network is of dataplane type, then create the sdn network
4341 if get_sdn_controller_id(mydb
, datacenter
) != None and (net_type
== 'data' or net_type
== 'ptp'):
4344 sdn_network
['vlan'] = net_vlan
4345 sdn_network
['type'] = net_type
4346 sdn_network
['name'] = net_name
4347 ovim_content
= ovim
.new_network(sdn_network
)
4348 except ovimException
as e
:
4349 self
.logger
.error("ovimException creating SDN network={} ".format(
4350 sdn_network
) + str(e
), exc_info
=True)
4351 raise NfvoException("ovimException creating SDN network={} ".format(sdn_network
) + str(e
),
4352 HTTP_Internal_Server_Error
)
4354 # Save entry in in dabase mano_db in table instance_nets to stablish a dictionary vim_net_id <->sdn_net_id
4355 # use instance_scenario_id=None to distinguish from real instaces of nets
4356 correspondence
= {'instance_scenario_id': None, 'sdn_net_id': ovim_content
, 'vim_net_id': content
}
4357 #obtain datacenter_tenant_id
4358 correspondence
['datacenter_tenant_id'] = mydb
.get_rows(SELECT
=('uuid',), FROM
='datacenter_tenants', WHERE
={'datacenter_id': datacenter
})[0]['uuid']
4361 mydb
.new_row('instance_nets', correspondence
, add_uuid
=True)
4362 except db_base_Exception
as e
:
4363 raise NfvoException("Error saving correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
4364 str(e
), HTTP_Internal_Server_Error
)
4365 elif item
=="tenants":
4366 tenant
= descriptor
["tenant"]
4367 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
4369 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
4370 except vimconn
.vimconnException
as e
:
4371 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
4373 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
4375 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
4376 data
= ovim
.new_of_controller(sdn_controller
)
4377 logger
.debug('New SDN controller created with uuid {}'.format(data
))
4380 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
4381 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
4382 msg
= 'SDN controller {} updated'.format(data
)
4386 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
4387 if controller_id
== None:
4388 data
= ovim
.get_of_controllers()
4390 data
= ovim
.show_of_controller(controller_id
)
4392 msg
= 'SDN controller list:\n {}'.format(data
)
4396 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
4397 select_
= ('uuid', 'config')
4398 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
4399 for datacenter
in datacenters
:
4400 if datacenter
['config']:
4401 config
= yaml
.load(datacenter
['config'])
4402 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
4403 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), HTTP_Conflict
)
4405 data
= ovim
.delete_of_controller(controller_id
)
4406 msg
= 'SDN controller {} deleted'.format(data
)
4410 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
4411 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
4412 if len(controller
) < 1:
4413 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), HTTP_Not_Found
)
4416 sdn_controller_id
= yaml
.load(controller
[0]["config"])["sdn-controller"]
4418 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), HTTP_Bad_Request
)
4420 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
4421 switch_dpid
= sdn_controller
["dpid"]
4424 for compute_node
in sdn_port_mapping
:
4425 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
4427 element
["compute_node"] = compute_node
["compute_node"]
4428 for port
in compute_node
["ports"]:
4429 element
["pci"] = port
.get("pci")
4430 element
["switch_port"] = port
.get("switch_port")
4431 element
["switch_mac"] = port
.get("switch_mac")
4432 if not element
["pci"] or not (element
["switch_port"] or element
["switch_mac"]):
4433 raise NfvoException ("The mapping must contain the 'pci' and at least one of the elements 'switch_port'"
4434 " or 'switch_mac'", HTTP_Bad_Request
)
4435 maps
.append(dict(element
))
4437 return ovim
.set_of_port_mapping(maps
, ofc_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, region
=datacenter_id
)
4439 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
4440 maps
= ovim
.get_of_port_mappings(db_filter
={"region": datacenter_id
})
4443 "sdn-controller": None,
4444 "datacenter-id": datacenter_id
,
4446 "ports_mapping": list()
4449 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
4450 if datacenter
['config']:
4451 config
= yaml
.load(datacenter
['config'])
4452 if 'sdn-controller' in config
:
4453 controller_id
= config
['sdn-controller']
4454 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
4455 result
["sdn-controller"] = controller_id
4456 result
["dpid"] = sdn_controller
["dpid"]
4458 if result
["sdn-controller"] == None:
4459 raise NfvoException("SDN controller is not defined for datacenter {}".format(datacenter_id
), HTTP_Bad_Request
)
4460 if result
["dpid"] == None:
4461 raise NfvoException("It was not possible to determine DPID for SDN controller {}".format(result
["sdn-controller"]),
4462 HTTP_Internal_Server_Error
)
4467 ports_correspondence_dict
= dict()
4469 if result
["sdn-controller"] != link
["ofc_id"]:
4470 raise NfvoException("The sdn-controller specified for different port mappings differ", HTTP_Internal_Server_Error
)
4471 if result
["dpid"] != link
["switch_dpid"]:
4472 raise NfvoException("The dpid specified for different port mappings differ", HTTP_Internal_Server_Error
)
4474 element
["pci"] = link
["pci"]
4475 if link
["switch_port"]:
4476 element
["switch_port"] = link
["switch_port"]
4477 if link
["switch_mac"]:
4478 element
["switch_mac"] = link
["switch_mac"]
4480 if not link
["compute_node"] in ports_correspondence_dict
:
4482 content
["compute_node"] = link
["compute_node"]
4483 content
["ports"] = list()
4484 ports_correspondence_dict
[link
["compute_node"]] = content
4486 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
4488 for key
in sorted(ports_correspondence_dict
):
4489 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
4493 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
4494 return ovim
.clear_of_port_mapping(db_filter
={"region":datacenter_id
})
4496 def create_RO_keypair(tenant_id
):
4498 Creates a public / private keys for a RO tenant and returns their values
4500 tenant_id: ID of the tenant
4502 public_key: Public key for the RO tenant
4503 private_key: Encrypted private key for RO tenant
4507 key
= RSA
.generate(bits
)
4509 public_key
= key
.publickey().exportKey('OpenSSH')
4510 if isinstance(public_key
, ValueError):
4511 raise NfvoException("Unable to create public key: {}".format(public_key
), HTTP_Internal_Server_Error
)
4512 private_key
= key
.exportKey(passphrase
=tenant_id
, pkcs
=8)
4513 except (ValueError, NameError) as e
:
4514 raise NfvoException("Unable to create private key: {}".format(e
), HTTP_Internal_Server_Error
)
4515 return public_key
, private_key
4517 def decrypt_key (key
, tenant_id
):
4519 Decrypts an encrypted RSA key
4521 key: Private key to be decrypted
4522 tenant_id: ID of the tenant
4524 unencrypted_key: Unencrypted private key for RO tenant
4527 key
= RSA
.importKey(key
,tenant_id
)
4528 unencrypted_key
= key
.exportKey('PEM')
4529 if isinstance(unencrypted_key
, ValueError):
4530 raise NfvoException("Unable to decrypt the private key: {}".format(unencrypted_key
), HTTP_Internal_Server_Error
)
4531 except ValueError as e
:
4532 raise NfvoException("Unable to decrypt the private key: {}".format(e
), HTTP_Internal_Server_Error
)
4533 return unencrypted_key