fix a VIM issue at network find or create if not exist
[osm/RO.git] / osm_ro / nfvo.py
index d5d2dc6..4ed6613 100644 (file)
@@ -46,10 +46,10 @@ from threading import Lock
 import time as t
 from lib_osm_openvim import ovim as ovim_module
 from lib_osm_openvim.ovim import ovimException
+from Crypto.PublicKey import RSA
 
 import osm_im.vnfd as vnfd_catalog
 import osm_im.nsd as nsd_catalog
-
 from pyangbind.lib.serialise import pybindJSONDecoder
 from itertools import chain
 
@@ -789,7 +789,7 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
         try:
             pybindJSONDecoder.load_ietf_json(vnf_descriptor, None, None, obj=myvnfd)
         except Exception as e:
-            raise NfvoException("Invalid yang descriptor format " + str(e), HTTP_Bad_Request)
+            raise NfvoException("Error. Invalid VNF descriptor format " + str(e), HTTP_Bad_Request)
         db_vnfs = []
         db_nets = []
         db_vms = []
@@ -799,8 +799,8 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
         db_flavors = []
         uuid_list = []
         vnfd_uuid_list = []
-        for rift_vnfd in myvnfd.vnfd_catalog.vnfd.itervalues():
-            vnfd = rift_vnfd.get()
+        for vnfd_yang in myvnfd.vnfd_catalog.vnfd.itervalues():
+            vnfd = vnfd_yang.get()
 
             # table vnf
             vnf_uuid = str(uuid4())
@@ -958,10 +958,10 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
                 # cloud-init
                 boot_data = {}
                 if vdu.get("cloud-init"):
-                    boot_data["user-data"] = vdu["cloud-init"]
+                    boot_data["user-data"] = str(vdu["cloud-init"])
                 elif vdu.get("cloud-init-file"):
                     # TODO Where this file content is present???
-                    # boot_data["user-data"] = rift_vnfd.files[vdu["cloud-init-file"]]
+                    # boot_data["user-data"] = vnfd_yang.files[vdu["cloud-init-file"]]
                     boot_data["user-data"] = str(vdu["cloud-init-file"])
 
                 if vdu.get("supplemental-boot-data"):
@@ -976,7 +976,7 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
                                                     "content": cfg_source})
                         boot_data['config-files'] = om_cfgfile_list
                 if boot_data:
-                    db_vm["boot_data"] = boot_data
+                    db_vm["boot_data"] = yaml.safe_dump(boot_data, default_flow_style=True, width=256)
 
                 db_vms.append(db_vm)
                 db_vms_index += 1
@@ -1009,7 +1009,11 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
                         db_interface["type"] = "data"
                         db_interface["model"] = get_str(iface.get("virtual-interface"), "type", 12)
                     else:
-                        raise ValueError("Interface type {} not supported".format(iface.get("virtual-interface").get("type")))
+                        raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vdu[{}]':'interface':'virtual"
+                                            "-interface':'type':'{}'. Interface type is not supported".format(
+                                                str(vnfd["id"])[:255], str(vdu["id"])[:255],
+                                                iface.get("virtual-interface").get("type")),
+                                            HTTP_Bad_Request)
 
                     if iface.get("external-connection-point-ref"):
                         try:
@@ -1021,12 +1025,12 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
                             # if cp.get("port-security-enabled") == False:
                             # elif cp.get("port-security-enabled") == True:
                         except KeyError:
-                            raise KeyError(
-                                "Error wrong reference at vnfd['{vnf}'] vdu['{vdu}']:internal-interface['{iface}']:"
-                                "vnfd-connection-point-ref '{cp}' is not present at connection-point".format(
-                                    vnf=vnfd["id"], vdu=vdu["id"], iface=iface["name"],
-                                    cp=iface.get("vnfd-connection-point-ref"))
-                            )
+                            raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
+                                                "'interface[{iface}]':'vnfd-connection-point-ref':'{cp}' is not present"
+                                                " at connection-point".format(
+                                                    vnf=vnfd["id"], vdu=vdu["id"], iface=iface["name"],
+                                                    cp=iface.get("vnfd-connection-point-ref")),
+                                                HTTP_Bad_Request)
                     elif iface.get("internal-connection-point-ref"):
                         try:
                             for vld in vnfd.get("internal-vld").itervalues():
@@ -1035,12 +1039,12 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
                                         db_interface["net_id"] = net_id2uuid[vld.get("id")]
                                         break
                         except KeyError:
-                            raise KeyError(
-                                "Error at vnfd['{vnf}'] vdu['{vdu}']:internal-interface['{iface}']:"
-                                "vdu-internal-connection-point-ref '{cp}' is not referenced by any internal-vld".format(
-                                    vnf=vnfd["id"], vdu=vdu["id"], iface=iface["name"],
-                                    cp=iface.get("vdu-internal-connection-point-ref"))
-                            )
+                            raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
+                                                "'interface[{iface}]':'vdu-internal-connection-point-ref':'{cp}' is not"
+                                                " referenced by any internal-vld".format(
+                                                    vnf=vnfd["id"], vdu=vdu["id"], iface=iface["name"],
+                                                    cp=iface.get("vdu-internal-connection-point-ref")),
+                                                HTTP_Bad_Request)
                     if iface.get("position") is not None:
                         db_interface["created_at"] = int(iface.get("position")) - 1000
                     db_interfaces.append(db_interface)
@@ -1051,9 +1055,10 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
                 for vdu in pg.get("member-vdus").itervalues():
                     vdu_id = get_str(vdu, "member-vdu-ref", 255)
                     if vdu_id not in vdu_id2db_table_index:
-                        raise KeyError(
-                            "Error at 'vnfd'['{vnf}']:'placement-groups'['{pg}']:'member-vdus':'{vdu}' references a non existing vdu".format(
-                                vnf=vnfd["id"], pg=pg_name, vdu=vdu_id))
+                        raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'placement-groups[{pg}]':"
+                                            "'member-vdus':'{vdu}'. Reference to a non-existing vdu".format(
+                                                vnf=vnfd["id"], pg=pg_name, vdu=vdu_id),
+                                            HTTP_Bad_Request)
                     db_vms[vdu_id2db_table_index[vdu_id]]["availability_zone"] = pg_name
                     # TODO consider the case of isolation and not colocation
                     # if pg.get("strategy") == "ISOLATION":
@@ -1062,26 +1067,36 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
             mgmt_access = {}
             if vnfd["mgmt-interface"].get("vdu-id"):
                 if vnfd["mgmt-interface"]["vdu-id"] not in vdu_id2uuid:
-                    raise KeyError(
-                        "Error at vnfd['{vnf}']:'mgmt-interface':'vdu-id':{vdu} reference a non existing vdu".format(
-                            vnf=vnfd["id"], vdu=vnfd["mgmt-interface"]["vdu-id"]))
+                    raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'vdu-id':"
+                                        "'{vdu}'. Reference to a non-existing vdu".format(
+                                            vnf=vnfd["id"], vdu=vnfd["mgmt-interface"]["vdu-id"]),
+                                        HTTP_Bad_Request)
                 mgmt_access["vm_id"] = vdu_id2uuid[vnfd["mgmt-interface"]["vdu-id"]]
             if vnfd["mgmt-interface"].get("ip-address"):
                 mgmt_access["ip-address"] = str(vnfd["mgmt-interface"].get("ip-address"))
             if vnfd["mgmt-interface"].get("cp"):
                 if vnfd["mgmt-interface"]["cp"] not in cp_name2iface_uuid:
-                    raise KeyError(
-                        "Error at vnfd['{vnf}']:'mgmt-interface':'cp':{cp} reference a non existing connection-point".
-                            format(vnf=vnfd["id"], cp=vnfd["mgmt-interface"]["cp"]))
+                    raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'cp':'{cp}'. "
+                                        "Reference to a non-existing connection-point".format(
+                                            vnf=vnfd["id"], cp=vnfd["mgmt-interface"]["cp"]),
+                                        HTTP_Bad_Request)
                 mgmt_access["vm_id"] = cp_name2vm_uuid[vnfd["mgmt-interface"]["cp"]]
                 mgmt_access["interface_id"] = cp_name2iface_uuid[vnfd["mgmt-interface"]["cp"]]
             default_user = get_str(vnfd.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
                                     "default-user", 64)
+
             if default_user:
                 mgmt_access["default_user"] = default_user
+            required = get_str(vnfd.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
+                                   "required", 6)
+            if required:
+                mgmt_access["required"] = required
+
             if mgmt_access:
                 db_vnf["mgmt_access"] = yaml.safe_dump(mgmt_access, default_flow_style=True, width=256)
 
+
+
             db_vnfs.append(db_vnf)
         db_tables=[
             {"vnfs": db_vnfs},
@@ -1096,6 +1111,8 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
                     yaml.safe_dump(db_tables, indent=4, default_flow_style=False) )
         mydb.new_rows(db_tables, uuid_list)
         return vnfd_uuid_list
+    except NfvoException:
+        raise
     except Exception as e:
         logger.error("Exception {}".format(e))
         raise  # NfvoException("Exception {}".format(e), HTTP_Bad_Request)
@@ -2003,7 +2020,7 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor):
         try:
             pybindJSONDecoder.load_ietf_json(nsd_descriptor, None, None, obj=mynsd)
         except Exception as e:
-            raise NfvoException("Invalid yang descriptor format " + str(e), HTTP_Bad_Request)
+            raise NfvoException("Error. Invalid NS descriptor format: " + str(e), HTTP_Bad_Request)
         db_scenarios = []
         db_sce_nets = []
         db_sce_vnfs = []
@@ -2012,8 +2029,8 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor):
         db_ip_profiles_index = 0
         uuid_list = []
         nsd_uuid_list = []
-        for rift_nsd in mynsd.nsd_catalog.nsd.itervalues():
-            nsd = rift_nsd.get()
+        for nsd_yang in mynsd.nsd_catalog.nsd.itervalues():
+            nsd = nsd_yang.get()
 
             # table sceanrios
             scenario_uuid = str(uuid4())
@@ -2038,9 +2055,10 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor):
                 existing_vnf = mydb.get_rows(FROM="vnfs", WHERE={'osm_id': str(vnf["vnfd-id-ref"])[:255],
                                                                       'tenant_id': tenant_id})
                 if not existing_vnf:
-                    raise KeyError("Error at 'nsd[{}]':'constituent-vnfd':'vnfd-id-ref':'{}' references a "
-                                   "non existing VNFD in the catalog".format(str(nsd["id"]),
-                                                                             str(vnf["vnfd-id-ref"])[:255]))
+                    raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'constituent-vnfd':'vnfd-id-ref':"
+                                        "'{}'. Reference to a non-existing VNFD in the catalog".format(
+                                            str(nsd["id"]), str(vnf["vnfd-id-ref"])[:255]),
+                                        HTTP_Bad_Request)
                 sce_vnf_uuid = str(uuid4())
                 uuid_list.append(sce_vnf_uuid)
                 db_sce_vnf = {
@@ -2103,9 +2121,10 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor):
                 if vld.get("ip-profile-ref"):
                     ip_profile_name = vld.get("ip-profile-ref")
                     if ip_profile_name not in ip_profile_name2db_table_index:
-                        raise KeyError("Error at 'nsd[{}]':'vld[{}]':'ip-profile-ref':'{}' references a non existing "
-                                       "'ip_profiles'".format(
-                                            str(nsd["id"]), str(vld["id"]), str(vld["ip-profile-ref"])))
+                        raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'ip-profile-ref':'{}'."
+                                            " Reference to a non-existing 'ip_profiles'".format(
+                                                str(nsd["id"]), str(vld["id"]), str(vld["ip-profile-ref"])),
+                                            HTTP_Bad_Request)
                     db_ip_profiles[ip_profile_name2db_table_index[ip_profile_name]]["sce_net_id"] = sce_net_uuid
 
                 # table sce_interfaces (vld:vnfd-connection-point-ref)
@@ -2113,9 +2132,11 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor):
                     vnf_index = int(iface['member-vnf-index-ref'])
                     # check correct parameters
                     if vnf_index not in vnf_index2vnf_uuid:
-                        raise KeyError("Error at 'nsd[{}]':'vld[{}]':'vnfd-connection-point-ref':'member-vnf-index-ref'"
-                                       ":'{}' references a non existing index at 'nsd':'constituent-vnfd'".format(
-                                            str(nsd["id"]), str(vld["id"]), str(iface["member-vnf-index-ref"])))
+                        raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
+                                            "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
+                                            "'nsd':'constituent-vnfd'".format(
+                                                str(nsd["id"]), str(vld["id"]), str(iface["member-vnf-index-ref"])),
+                                            HTTP_Bad_Request)
 
                     existing_ifaces = mydb.get_rows(SELECT=('i.uuid as uuid',),
                                                     FROM="interfaces as i join vms on i.vm_id=vms.uuid",
@@ -2123,11 +2144,12 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor):
                                                            'external_name': get_str(iface, "vnfd-connection-point-ref",
                                                                                     255)})
                     if not existing_ifaces:
-                        raise KeyError("Error at 'nsd[{}]':'vld[{}]':'vnfd-connection-point-ref':'vnfd-connection-point"
-                                       "-ref':'{}' references a non existing interface at VNFD '{}'".format(
-                            str(nsd["id"]), str(vld["id"]), str(iface["vnfd-connection-point-ref"]),
-                            str(iface.get("vnfd-id-ref"))[:255]))
-
+                        raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
+                                            "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
+                                            "connection-point name at VNFD '{}'".format(
+                                                str(nsd["id"]), str(vld["id"]), str(iface["vnfd-connection-point-ref"]),
+                                                str(iface.get("vnfd-id-ref"))[:255]),
+                                            HTTP_Bad_Request)
                     interface_uuid = existing_ifaces[0]["uuid"]
                     sce_interface_uuid = str(uuid4())
                     uuid_list.append(sce_net_uuid)
@@ -2152,6 +2174,8 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor):
                     yaml.safe_dump(db_tables, indent=4, default_flow_style=False) )
         mydb.new_rows(db_tables, uuid_list)
         return nsd_uuid_list
+    except NfvoException:
+        raise
     except Exception as e:
         logger.error("Exception {}".format(e))
         raise  # NfvoException("Exception {}".format(e), HTTP_Bad_Request)
@@ -2386,7 +2410,6 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc
         #logger.error("start_scenario %s", error_text)
         raise NfvoException(error_text, e.http_code)
 
-
 def unify_cloud_config(cloud_config_preserve, cloud_config):
     """ join the cloud config information into cloud_config_preserve.
     In case of conflict cloud_config_preserve preserves
@@ -2536,7 +2559,6 @@ def update(d, u):
             d[k] = u[k]
     return d
 
-
 def create_instance(mydb, tenant_id, instance_dict):
     # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
     # logger.debug("Creating instance...")
@@ -2549,7 +2571,9 @@ def create_instance(mydb, tenant_id, instance_dict):
     default_datacenter_id, vim = get_datacenter_by_name_uuid(mydb, tenant_id, datacenter)
     myvims[default_datacenter_id] = vim
     myvim_threads_id[default_datacenter_id], _ = get_vim_thread(mydb, tenant_id, default_datacenter_id)
+    tenant = mydb.get_rows_by_id('nfvo_tenants', tenant_id)
     # myvim_tenant = myvim['tenant_id']
+
     rollbackList=[]
 
     # print "Checking that the scenario exists and getting the scenario dictionary"
@@ -2644,6 +2668,10 @@ def create_instance(mydb, tenant_id, instance_dict):
 
         # 0.1 parse cloud-config parameters
         cloud_config = unify_cloud_config(instance_dict.get("cloud-config"), scenarioDict.get("cloud-config"))
+        # We add the RO key to cloud_config
+        if tenant[0].get('RO_pub_key'):
+            RO_key = {"key-pairs": [tenant[0]['RO_pub_key']]}
+            cloud_config = unify_cloud_config(cloud_config, RO_key)
 
         # 0.2 merge instance information into scenario
         # Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
@@ -2748,8 +2776,11 @@ def create_instance(mydb, tenant_id, instance_dict):
 
                 if lookfor_network and create_network:
                     # TODO create two tasks FIND + CREATE with their relationship
-                    task_action = "FIND_CREATE"
-                    task_params = (lookfor_filter, (net_vim_name, net_type, sce_net.get('ip_profile', None)))
+                    task_action = "FIND"
+                    task_params = (lookfor_filter,)
+                    # task_action = "CREATE"
+                    # task_params = (net_vim_name, net_type, sce_net.get('ip_profile', None))
+                    # task
                 elif lookfor_network:
                     task_action = "FIND"
                     task_params = (lookfor_filter,)
@@ -3442,7 +3473,6 @@ def refresh_instance(mydb, nfvo_tenant, instanceDict, datacenter=None, vim_tenan
 
     return 0, 'Scenario instance ' + instance_id + ' refreshed.'
 
-
 def instance_action(mydb,nfvo_tenant,instance_id, action_dict):
     #print "Checking that the instance_id exists and getting the instance dictionary"
     instanceDict = mydb.get_instance_scenario(instance_id, nfvo_tenant)
@@ -3475,44 +3505,69 @@ def instance_action(mydb,nfvo_tenant,instance_id, action_dict):
                                 vm['uuid'] not in input_vms and vm['name'] not in input_vms:
                     continue
             try:
-                data = myvim.action_vminstance(vm['vim_vm_id'], action_dict)
-                if "console" in action_dict:
-                    if not global_config["http_console_proxy"]:
-                        vm_result[ vm['uuid'] ] = {"vim_result": 200,
-                                                   "description": "{protocol}//{ip}:{port}/{suffix}".format(
-                                                                                protocol=data["protocol"],
-                                                                                ip = data["server"],
-                                                                                port = data["port"],
-                                                                                suffix = data["suffix"]),
-                                                   "name":vm['name']
-                                                }
-                        vm_ok +=1
-                    elif data["server"]=="127.0.0.1" or data["server"]=="localhost":
-                        vm_result[ vm['uuid'] ] = {"vim_result": -HTTP_Unauthorized,
-                                                   "description": "this console is only reachable by local interface",
-                                                   "name":vm['name']
-                                                }
-                        vm_error+=1
-                    else:
-                    #print "console data", data
+                if "add_public_key" in action_dict:
+                    mgmt_access = {}
+                    if sce_vnf.get('mgmt_access'):
+                        mgmt_access = yaml.load(sce_vnf['mgmt_access'])
+                        ssh_access = mgmt_access['config-access']['ssh-access']
+                        tenant = mydb.get_rows_by_id('nfvo_tenants', nfvo_tenant)
                         try:
-                            console_thread = create_or_use_console_proxy_thread(data["server"], data["port"])
+                            if ssh_access['required'] and ssh_access['default-user']:
+                                if 'ip_address' in vm:
+                                    mgmt_ip = vm['ip_address'].split(';')
+                                    password = mgmt_access['config-access'].get('password')
+                                    priv_RO_key = decrypt_key(tenant[0]['encrypted_RO_priv_key'], tenant[0]['uuid'])
+                                    myvim.inject_user_key(mgmt_ip[0], ssh_access['default-user'],
+                                                          action_dict['add_public_key'],
+                                                          password=password, ro_key=priv_RO_key)
+                            else:
+                                raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm['uuid']),
+                                                    HTTP_Internal_Server_Error)
+                        except KeyError:
+                            raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm['uuid']),
+                                                HTTP_Internal_Server_Error)
+                    else:
+                        raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm['uuid']),
+                                            HTTP_Internal_Server_Error)
+                else:
+                    data = myvim.action_vminstance(vm['vim_vm_id'], action_dict)
+                    if "console" in action_dict:
+                        if not global_config["http_console_proxy"]:
                             vm_result[ vm['uuid'] ] = {"vim_result": 200,
                                                        "description": "{protocol}//{ip}:{port}/{suffix}".format(
                                                                                     protocol=data["protocol"],
-                                                                                    ip = global_config["http_console_host"],
-                                                                                    port = console_thread.port,
+                                                                                    ip = data["server"],
+                                                                                    port = data["port"],
                                                                                     suffix = data["suffix"]),
                                                        "name":vm['name']
                                                     }
                             vm_ok +=1
-                        except NfvoException as e:
-                            vm_result[ vm['uuid'] ] = {"vim_result": e.http_code, "name":vm['name'], "description": str(e)}
+                        elif data["server"]=="127.0.0.1" or data["server"]=="localhost":
+                            vm_result[ vm['uuid'] ] = {"vim_result": -HTTP_Unauthorized,
+                                                       "description": "this console is only reachable by local interface",
+                                                       "name":vm['name']
+                                                    }
                             vm_error+=1
+                        else:
+                        #print "console data", data
+                            try:
+                                console_thread = create_or_use_console_proxy_thread(data["server"], data["port"])
+                                vm_result[ vm['uuid'] ] = {"vim_result": 200,
+                                                           "description": "{protocol}//{ip}:{port}/{suffix}".format(
+                                                                                        protocol=data["protocol"],
+                                                                                        ip = global_config["http_console_host"],
+                                                                                        port = console_thread.port,
+                                                                                        suffix = data["suffix"]),
+                                                           "name":vm['name']
+                                                        }
+                                vm_ok +=1
+                            except NfvoException as e:
+                                vm_result[ vm['uuid'] ] = {"vim_result": e.http_code, "name":vm['name'], "description": str(e)}
+                                vm_error+=1
 
-                else:
-                    vm_result[ vm['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm['name']}
-                    vm_ok +=1
+                    else:
+                        vm_result[ vm['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm['name']}
+                        vm_ok +=1
             except vimconn.vimconnException as e:
                 vm_result[ vm['uuid'] ] = {"vim_result": e.http_code, "name":vm['name'], "description": str(e)}
                 vm_error+=1
@@ -3568,11 +3623,18 @@ def check_tenant(mydb, tenant_id):
         raise NfvoException("tenant '{}' not found".format(tenant_id), HTTP_Not_Found)
     return
 
-
 def new_tenant(mydb, tenant_dict):
-    tenant_id = mydb.new_row("nfvo_tenants", tenant_dict, add_uuid=True)
-    return tenant_id
 
+    tenant_uuid = str(uuid4())
+    tenant_dict['uuid'] = tenant_uuid
+    try:
+        pub_key, priv_key = create_RO_keypair(tenant_uuid)
+        tenant_dict['RO_pub_key'] = pub_key
+        tenant_dict['encrypted_RO_priv_key'] = priv_key
+        mydb.new_row("nfvo_tenants", tenant_dict)
+    except db_base_Exception as e:
+        raise NfvoException("Error creating the new tenant: {} ".format(tenant_dict['name']) + str(e), HTTP_Internal_Server_Error)
+    return tenant_uuid
 
 def delete_tenant(mydb, tenant):
     #get nfvo_tenant info
@@ -4331,3 +4393,42 @@ def datacenter_sdn_port_mapping_list(mydb, tenant_id, datacenter_id):
 
 def datacenter_sdn_port_mapping_delete(mydb, tenant_id, datacenter_id):
     return ovim.clear_of_port_mapping(db_filter={"region":datacenter_id})
+
+def create_RO_keypair(tenant_id):
+    """
+    Creates a public / private keys for a RO tenant and returns their values
+    Params:
+        tenant_id: ID of the tenant
+    Return:
+        public_key: Public key for the RO tenant
+        private_key: Encrypted private key for RO tenant
+    """
+
+    bits = 2048
+    key = RSA.generate(bits)
+    try:
+        public_key = key.publickey().exportKey('OpenSSH')
+        if isinstance(public_key, ValueError):
+            raise NfvoException("Unable to create public key: {}".format(public_key), HTTP_Internal_Server_Error)
+        private_key = key.exportKey(passphrase=tenant_id, pkcs=8)
+    except (ValueError, NameError) as e:
+        raise NfvoException("Unable to create private key: {}".format(e), HTTP_Internal_Server_Error)
+    return public_key, private_key
+
+def decrypt_key (key, tenant_id):
+    """
+    Decrypts an encrypted RSA key
+    Params:
+        key: Private key to be decrypted
+        tenant_id: ID of the tenant
+    Return:
+        unencrypted_key: Unencrypted private key for RO tenant
+    """
+    try:
+        key = RSA.importKey(key,tenant_id)
+        unencrypted_key = key.exportKey('PEM')
+        if isinstance(unencrypted_key, ValueError):
+            raise NfvoException("Unable to decrypt the private key: {}".format(unencrypted_key), HTTP_Internal_Server_Error)
+    except ValueError as e:
+        raise NfvoException("Unable to decrypt the private key: {}".format(e), HTTP_Internal_Server_Error)
+    return unencrypted_key