timeout_large = 120
timeout_short = 30
- def __init__(self, loop, endpoint_url, **kwargs):
+ def __init__(self, loop, uri, **kwargs):
self.loop = loop
- self.endpoint_url = endpoint_url
+ self.uri = uri
self.username = kwargs.get("username")
self.password = kwargs.get("password")
self.tenant = None
self.datacenter_id_name = kwargs.get("datacenter")
self.datacenter = None
- logger_name = kwargs.get('logger_name', 'ROClient')
+ logger_name = kwargs.get('logger_name', 'lcm.ro')
self.logger = logging.getLogger(logger_name)
if kwargs.get("loglevel"):
self.logger.setLevel(kwargs["loglevel"])
return self.username
elif index == 'password':
return self.password
- elif index == 'endpoint_url':
- return self.endpoint_url
+ elif index == 'uri':
+ return self.uri
else:
raise KeyError("Invalid key '{}'".format(index))
self.username = value
elif index == 'password':
self.password = value
- elif index == 'endpoint_url':
- self.endpoint_url = value
+ elif index == 'uri':
+ self.uri = value
else:
raise KeyError("Invalid key '{}'".format(index))
self.tenant = None # force to reload tenant with different credentials
tenant_text = "/" + self.tenant
item_id = 0
- url = "{}{}/{}".format(self.endpoint_url, tenant_text, item)
+ url = "{}{}/{}".format(self.uri, tenant_text, item)
if self.check_if_uuid(item_id_name):
item_id = item_id_name
url += "/" + item_id_name
# check that exist
uuid = await self._get_item_uuid(session, item, item_id_name, all_tenants)
- url = "{}{}/{}/{}".format(self.endpoint_url, tenant_text, item, uuid)
+ url = "{}{}/{}/{}".format(self.uri, tenant_text, item, uuid)
if extra_item:
url += "/" + extra_item
if extra_item_id:
else:
action = "/{}".format(action)
- url = "{}{apiver}{tenant}/{item}{id}{action}".format(self.endpoint_url, apiver=api_version_text,
+ url = "{}{apiver}{tenant}/{item}{id}{action}".format(self.uri, apiver=api_version_text,
tenant=tenant_text, item=item, id=uuid, action=action)
self.logger.debug("RO POST %s %s", url, payload_req)
# timeout = aiohttp.ClientTimeout(total=self.timeout_large)
else:
uuid = item_id_name
- url = "{}{}/{}/{}".format(self.endpoint_url, tenant_text, item, uuid)
+ url = "{}{}/{}/{}".format(self.uri, tenant_text, item, uuid)
self.logger.debug("DELETE %s", url)
# timeout = aiohttp.ClientTimeout(total=self.timeout_short)
async with session.delete(url, headers=self.headers_req) as response:
await self._get_tenant(session)
tenant_text = "/" + self.tenant
- url = "{}{}/{}".format(self.endpoint_url, tenant_text, item)
+ url = "{}{}/{}".format(self.uri, tenant_text, item)
separator = "?"
if filter_dict:
for k in filter_dict:
payload_req = yaml.safe_dump(descriptor)
# print payload_req
- url = "{}{}/{}/{}".format(self.endpoint_url, tenant_text, item, item_id)
+ url = "{}{}/{}/{}".format(self.uri, tenant_text, item, item_id)
self.logger.debug("RO PUT %s %s", url, payload_req)
# timeout = aiohttp.ClientTimeout(total=self.timeout_large)
async with session.put(url, headers=self.headers_req, data=payload_req) as response:
try:
response_text = ""
async with aiohttp.ClientSession(loop=self.loop) as session:
- url = "{}/version".format(self.endpoint_url)
+ url = "{}/version".format(self.uri)
self.logger.debug("RO GET %s", url)
# timeout = aiohttp.ClientTimeout(total=self.timeout_short)
async with session.get(url, headers=self.headers_req) as response:
item_id = await self._get_item_uuid(session, self.client_to_RO[item], item_id_name, all_tenants=True)
await self._get_tenant(session)
- url = "{}/{tenant}/{item}/{item_id}".format(self.endpoint_url, tenant=self.tenant,
+ url = "{}/{tenant}/{item}/{item_id}".format(self.uri, tenant=self.tenant,
item=self.client_to_RO[item], item_id=item_id)
self.logger.debug("RO POST %s %s", url, payload_req)
# timeout = aiohttp.ClientTimeout(total=self.timeout_large)
item_id = await self._get_item_uuid(session, self.client_to_RO[item], item_id_name, all_tenants=False)
tenant = await self._get_tenant(session)
- url = "{}/{tenant}/{item}/{datacenter}".format(self.endpoint_url, tenant=tenant,
+ url = "{}/{tenant}/{item}/{datacenter}".format(self.uri, tenant=tenant,
item=self.client_to_RO[item], datacenter=item_id)
self.logger.debug("RO DELETE %s", url)
datacenter = self.get_datacenter(session)
if action == "list":
- url = "{}{}/vim/{}/{}".format(self.endpoint_url, tenant_text, datacenter, item)
+ url = "{}{}/vim/{}/{}".format(self.uri, tenant_text, datacenter, item)
self.logger.debug("GET %s", url)
mano_response = requests.get(url, headers=self.headers_req)
self.logger.debug("RO response: %s", mano_response.text)
else:
raise ROClientException(str(content), http_code=mano_response.status)
elif action == "get" or action == "show":
- url = "{}{}/vim/{}/{}/{}".format(self.endpoint_url, tenant_text, datacenter, item, uuid)
+ url = "{}{}/vim/{}/{}/{}".format(self.uri, tenant_text, datacenter, item, uuid)
self.logger.debug("GET %s", url)
mano_response = requests.get(url, headers=self.headers_req)
self.logger.debug("RO response: %s", mano_response.text)
else:
raise ROClientException(str(content), http_code=mano_response.status)
elif action == "delete":
- url = "{}{}/vim/{}/{}/{}".format(self.endpoint_url, tenant_text, datacenter, item, uuid)
+ url = "{}{}/vim/{}/{}/{}".format(self.uri, tenant_text, datacenter, item, uuid)
self.logger.debug("DELETE %s", url)
mano_response = requests.delete(url, headers=self.headers_req)
self.logger.debug("RO response: %s", mano_response.text)
descriptor[item[:-1]]['description'] = kwargs["description"]
payload_req = yaml.safe_dump(descriptor)
# print payload_req
- url = "{}{}/vim/{}/{}".format(self.endpoint_url, tenant_text, datacenter, item)
+ url = "{}{}/vim/{}/{}".format(self.uri, tenant_text, datacenter, item)
self.logger.debug("RO POST %s %s", url, payload_req)
mano_response = requests.post(url, headers=self.headers_req, data=payload_req)
self.logger.debug("RO response: %s", mano_response.text)
tenant_id = None
vim_id = False
loop = asyncio.get_event_loop()
- myClient = ROClient(endpoint_url=RO_URL, loop=loop, loglevel="DEBUG")
+ myClient = ROClient(uri=RO_URL, loop=loop, loglevel="DEBUG")
try:
# test tenant
content = loop.run_until_complete(myClient.get_list("tenant"))
from osm_lcm import ns
from osm_lcm import vim_sdn
from osm_lcm import netslice
-from osm_lcm import ROclient
+from osm_lcm.ng_ro import NgRoException, NgRoClient
+from osm_lcm.ROclient import ROClient, ROClientException
from time import time
from osm_lcm.lcm_utils import versiontuple, LcmException, TaskRegistry, LcmExceptionExit
config = self.read_config_file(config_file)
self.config = config
self.config["ro_config"] = {
- "endpoint_url": "http://{}:{}/openmano".format(config["RO"]["host"], config["RO"]["port"]),
+ "ng": config["RO"].get("ng", False),
+ "uri": config["RO"].get("uri"),
"tenant": config.get("tenant", "osm"),
- "logger_name": "lcm.ROclient",
- "loglevel": "ERROR",
+ "logger_name": "lcm.roclient",
+ "loglevel": config["RO"].get("loglevel", "ERROR"),
}
+ if not self.config["ro_config"]["uri"]:
+ if not self.config["ro_config"]["ng"]:
+ self.config["ro_config"]["uri"] = "http://{}:{}/openmano".format(config["RO"]["host"],
+ config["RO"]["port"])
+ else:
+ self.config["ro_config"]["uri"] = "http://{}:{}/ro".format(config["RO"]["host"], config["RO"]["port"])
self.loop = loop or asyncio.get_event_loop()
last_error = None
while True:
try:
- ro_server = ROclient.ROClient(self.loop, **self.config["ro_config"])
+ if self.config["ro_config"].get("ng"):
+ ro_server = NgRoClient(self.loop, **self.config["ro_config"])
+ else:
+ ro_server = ROClient(self.loop, **self.config["ro_config"])
ro_version = await ro_server.get_version()
if versiontuple(ro_version) < versiontuple(min_RO_version):
raise LcmException("Not compatible osm/RO version '{}'. Needed '{}' or higher".format(
ro_version, min_RO_version))
self.logger.info("Connected to RO version {}".format(ro_version))
return
- except ROclient.ROClientException as e:
+ except (ROClientException, NgRoException) as e:
tries -= 1
- error_text = "Error while connecting to RO on {}: {}".format(self.config["ro_config"]["endpoint_url"],
- e)
+ error_text = "Error while connecting to RO on {}: {}".format(self.config["ro_config"]["uri"], e)
if tries <= 0:
self.logger.critical(error_text)
raise LcmException(error_text)
--- /dev/null
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2020 Telefónica Investigación y Desarrollo, S.A.U.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+##
+
+"""
+asyncio RO python client to interact with New Generation RO server
+"""
+
+import asyncio
+import aiohttp
+import yaml
+import logging
+
+__author__ = "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com"
+__date__ = "$09-Jan-2018 09:09:48$"
+__version__ = "0.1.2"
+version_date = "2020-05-08"
+
+
+class NgRoException(Exception):
+ def __init__(self, message, http_code=400):
+ """Common Exception for all RO client exceptions"""
+ self.http_code = http_code
+ Exception.__init__(self, message)
+
+
+class NgRoClient:
+ headers_req = {'Accept': 'application/yaml', 'content-type': 'application/yaml'}
+ client_to_RO = {'tenant': 'tenants', 'vim': 'datacenters', 'vim_account': 'datacenters', 'sdn': 'sdn_controllers',
+ 'vnfd': 'vnfs', 'nsd': 'scenarios', 'wim': 'wims', 'wim_account': 'wims',
+ 'ns': 'instances'}
+ mandatory_for_create = {
+ 'tenant': ("name", ),
+ 'vnfd': ("name", "id"),
+ 'nsd': ("name", "id"),
+ 'ns': ("name", "scenario", "datacenter"),
+ 'vim': ("name", "vim_url"),
+ 'wim': ("name", "wim_url"),
+ 'vim_account': (),
+ 'wim_account': (),
+ 'sdn': ("name", 'type'),
+ }
+ timeout_large = 120
+ timeout_short = 30
+
+ def __init__(self, loop, uri, **kwargs):
+ self.loop = loop
+ self.endpoint_url = uri
+ if not self.endpoint_url.endswith("/"):
+ self.endpoint_url += "/"
+ if not self.endpoint_url.startswith("http"):
+ self.endpoint_url = "http://" + self.endpoint_url
+
+ self.username = kwargs.get("username")
+ self.password = kwargs.get("password")
+ self.tenant_id_name = kwargs.get("tenant")
+ self.tenant = None
+ self.datacenter_id_name = kwargs.get("datacenter")
+ self.datacenter = None
+ logger_name = kwargs.get('logger_name', 'lcm.ro')
+ self.logger = logging.getLogger(logger_name)
+ if kwargs.get("loglevel"):
+ self.logger.setLevel(kwargs["loglevel"])
+
+ async def deploy(self, nsr_id, target):
+ """
+ Performs an action over an item
+ :param item: can be 'tenant', 'vnfd', 'nsd', 'ns', 'vim', 'vim_account', 'sdn'
+ :param item_id_name: RO id or name of the item. Raise and exception if more than one found
+ :param descriptor: can be a dict, or a yaml/json text. Autodetect unless descriptor_format is provided
+ :param descriptor_format: Can be 'json' or 'yaml'
+ :param kwargs: Overrides descriptor with values as name, description, vim_url, vim_url_admin, vim_type
+ keys can be a dot separated list to specify elements inside dict
+ :return: dictionary with the information or raises NgRoException on Error
+ """
+ try:
+ if isinstance(target, str):
+ target = self._parse_yaml(target)
+ payload_req = yaml.safe_dump(target)
+
+ url = "{}/ns/v1/deploy/{nsr_id}".format(self.endpoint_url, nsr_id=nsr_id)
+ async with aiohttp.ClientSession(loop=self.loop) as session:
+ self.logger.debug("NG-RO POST %s %s", url, payload_req)
+ # timeout = aiohttp.ClientTimeout(total=self.timeout_large)
+ async with session.post(url, headers=self.headers_req, data=payload_req) as response:
+ response_text = await response.read()
+ self.logger.debug("POST {} [{}] {}".format(url, response.status, response_text[:100]))
+ if response.status >= 300:
+ raise NgRoException(response_text, http_code=response.status)
+ return self._parse_yaml(response_text, response=True)
+ except (aiohttp.ClientOSError, aiohttp.ClientError) as e:
+ raise NgRoException(e, http_code=504)
+ except asyncio.TimeoutError:
+ raise NgRoException("Timeout", http_code=504)
+
+ async def status(self, nsr_id, action_id):
+ try:
+ url = "{}/ns/v1/deploy/{nsr_id}/{action_id}".format(self.endpoint_url, nsr_id=nsr_id, action_id=action_id)
+ async with aiohttp.ClientSession(loop=self.loop) as session:
+ self.logger.debug("GET %s", url)
+ # timeout = aiohttp.ClientTimeout(total=self.timeout_short)
+ async with session.get(url, headers=self.headers_req) as response:
+ response_text = await response.read()
+ self.logger.debug("GET {} [{}] {}".format(url, response.status, response_text[:100]))
+ if response.status >= 300:
+ raise NgRoException(response_text, http_code=response.status)
+ return self._parse_yaml(response_text, response=True)
+
+ except (aiohttp.ClientOSError, aiohttp.ClientError) as e:
+ raise NgRoException(e, http_code=504)
+ except asyncio.TimeoutError:
+ raise NgRoException("Timeout", http_code=504)
+
+ async def delete(self, nsr_id):
+ try:
+ url = "{}/ns/v1/deploy/{nsr_id}".format(self.endpoint_url, nsr_id=nsr_id)
+ async with aiohttp.ClientSession(loop=self.loop) as session:
+ self.logger.debug("DELETE %s", url)
+ # timeout = aiohttp.ClientTimeout(total=self.timeout_short)
+ async with session.delete(url, headers=self.headers_req) as response:
+ self.logger.debug("DELETE {} [{}]".format(url, response.status))
+ if response.status >= 300:
+ raise NgRoException("Delete {}".format(nsr_id), http_code=response.status)
+ return
+
+ except (aiohttp.ClientOSError, aiohttp.ClientError) as e:
+ raise NgRoException(e, http_code=504)
+ except asyncio.TimeoutError:
+ raise NgRoException("Timeout", http_code=504)
+
+ async def get_version(self):
+ """
+ Obtain RO server version.
+ :return: a list with integers ["major", "minor", "release"]. Raises NgRoException on Error,
+ """
+ try:
+ response_text = ""
+ async with aiohttp.ClientSession(loop=self.loop) as session:
+ url = "{}/version".format(self.endpoint_url)
+ self.logger.debug("RO GET %s", url)
+ # timeout = aiohttp.ClientTimeout(total=self.timeout_short)
+ async with session.get(url, headers=self.headers_req) as response:
+ response_text = await response.read()
+ self.logger.debug("GET {} [{}] {}".format(url, response.status, response_text[:100]))
+ if response.status >= 300:
+ raise NgRoException(response_text, http_code=response.status)
+
+ for word in str(response_text).split(" "):
+ if "." in word:
+ version_text, _, _ = word.partition("-")
+ return version_text
+ raise NgRoException("Got invalid version text: '{}'".format(response_text), http_code=500)
+ except (aiohttp.ClientOSError, aiohttp.ClientError) as e:
+ raise NgRoException(e, http_code=504)
+ except asyncio.TimeoutError:
+ raise NgRoException("Timeout", http_code=504)
+ except Exception as e:
+ raise NgRoException("Got invalid version text: '{}'; causing exception {}".format(response_text, e),
+ http_code=500)
+
+ @staticmethod
+ def _parse_yaml(descriptor, response=False):
+ try:
+ return yaml.safe_load(descriptor)
+ except yaml.YAMLError as exc:
+ error_pos = ""
+ if hasattr(exc, 'problem_mark'):
+ mark = exc.problem_mark
+ error_pos = " at line:{} column:{}s".format(mark.line + 1, mark.column + 1)
+ error_text = "yaml format error" + error_pos
+ if response:
+ raise NgRoException("reponse with " + error_text)
+ raise NgRoException(error_text)
from jinja2 import Environment, Template, meta, TemplateError, TemplateNotFound, TemplateSyntaxError
from osm_lcm import ROclient
+from osm_lcm.ng_ro import NgRoClient, NgRoException
from osm_lcm.lcm_utils import LcmException, LcmExceptionNoMgmtIP, LcmBase, deep_get, get_iterable, populate_dict
from n2vc.k8s_helm_conn import K8sHelmConnector
from n2vc.k8s_juju_conn import K8sJujuConnector
from uuid import uuid4
from functools import partial
-__author__ = "Alfonso Tierno"
+__author__ = "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com>"
class NsLcm(LcmBase):
self.lcm_tasks = lcm_tasks
self.timeout = config["timeout"]
self.ro_config = config["ro_config"]
+ self.ng_ro = config["ro_config"].get("ng")
self.vca_config = config["VCA"].copy()
# create N2VC connector
"juju": self.k8sclusterjuju,
}
# create RO client
- self.RO = ROclient.ROClient(self.loop, **self.ro_config)
+ if self.ng_ro:
+ self.RO = NgRoClient(self.loop, **self.ro_config)
+ else:
+ self.RO = ROclient.ROClient(self.loop, **self.ro_config)
def _on_update_ro_db(self, nsrs_id, ro_descriptor):
primitive_list.insert(config_position + 1, {"name": "verify-ssh-credentials", "parameter": []})
return primitive_list
+ async def _instantiate_ng_ro(self, logging_text, nsr_id, nsd, db_nsr, db_nslcmop, db_vnfrs, db_vnfds_ref,
+ n2vc_key_list, stage, start_deploy, timeout_ns_deploy):
+ nslcmop_id = db_nslcmop["_id"]
+ target = {
+ "name": db_nsr["name"],
+ "ns": {"vld": []},
+ "vnf": [],
+ "image": deepcopy(db_nsr["image"]),
+ "flavor": deepcopy(db_nsr["flavor"]),
+ "action_id": nslcmop_id,
+ }
+ for image in target["image"]:
+ image["vim_info"] = []
+ for flavor in target["flavor"]:
+ flavor["vim_info"] = []
+
+ ns_params = db_nslcmop.get("operationParams")
+ ssh_keys = []
+ if ns_params.get("ssh_keys"):
+ ssh_keys += ns_params.get("ssh_keys")
+ if n2vc_key_list:
+ ssh_keys += n2vc_key_list
+
+ cp2target = {}
+ for vld_index, vld in enumerate(nsd.get("vld")):
+ target_vld = {"id": vld["id"],
+ "name": vld["name"],
+ "mgmt-network": vld.get("mgmt-network", False),
+ "type": vld.get("type"),
+ "vim_info": [{"vim-network-name": vld.get("vim-network-name"),
+ "vim_account_id": ns_params["vimAccountId"]}],
+ }
+ for cp in vld["vnfd-connection-point-ref"]:
+ cp2target["member_vnf:{}.{}".format(cp["member-vnf-index-ref"], cp["vnfd-connection-point-ref"])] = \
+ "nsrs:{}:vld.{}".format(nsr_id, vld_index)
+ target["ns"]["vld"].append(target_vld)
+ for vnfr in db_vnfrs.values():
+ vnfd = db_vnfds_ref[vnfr["vnfd-ref"]]
+ target_vnf = deepcopy(vnfr)
+ for vld in target_vnf.get("vld", ()):
+ # check if connected to a ns.vld
+ vnf_cp = next((cp for cp in vnfd.get("connection-point", ()) if
+ cp.get("internal-vld-ref") == vld["id"]), None)
+ if vnf_cp:
+ ns_cp = "member_vnf:{}.{}".format(vnfr["member-vnf-index-ref"], vnf_cp["id"])
+ if cp2target.get(ns_cp):
+ vld["target"] = cp2target[ns_cp]
+ vld["vim_info"] = [{"vim-network-name": vld.get("vim-network-name"),
+ "vim_account_id": vnfr["vim-account-id"]}]
+
+ for vdur in target_vnf.get("vdur", ()):
+ vdur["vim_info"] = [{"vim_account_id": vnfr["vim-account-id"]}]
+ vdud_index, vdud = next(k for k in enumerate(vnfd["vdu"]) if k[1]["id"] == vdur["vdu-id-ref"])
+ # vdur["additionalParams"] = vnfr.get("additionalParamsForVnf") # TODO additional params for VDU
+
+ if ssh_keys:
+ if deep_get(vdud, ("vdu-configuration", "config-access", "ssh-access", "required")):
+ vdur["ssh-keys"] = ssh_keys
+ vdur["ssh-access-required"] = True
+ elif deep_get(vnfd, ("vnf-configuration", "config-access", "ssh-access", "required")) and \
+ any(iface.get("mgmt-vnf") for iface in vdur["interfaces"]):
+ vdur["ssh-keys"] = ssh_keys
+ vdur["ssh-access-required"] = True
+
+ # cloud-init
+ if vdud.get("cloud-init-file"):
+ vdur["cloud-init"] = "{}:file:{}".format(vnfd["_id"], vdud.get("cloud-init-file"))
+ elif vdud.get("cloud-init"):
+ vdur["cloud-init"] = "{}:vdu:{}".format(vnfd["_id"], vdud_index)
+
+ # flavor
+ ns_flavor = target["flavor"][int(vdur["ns-flavor-id"])]
+ if not next((vi for vi in ns_flavor["vim_info"] if
+ vi and vi.get("vim_account_id") == vnfr["vim-account-id"]), None):
+ ns_flavor["vim_info"].append({"vim_account_id": vnfr["vim-account-id"]})
+ # image
+ ns_image = target["image"][int(vdur["ns-image-id"])]
+ if not next((vi for vi in ns_image["vim_info"] if
+ vi and vi.get("vim_account_id") == vnfr["vim-account-id"]), None):
+ ns_image["vim_info"].append({"vim_account_id": vnfr["vim-account-id"]})
+
+ vdur["vim_info"] = [{"vim_account_id": vnfr["vim-account-id"]}]
+ target["vnf"].append(target_vnf)
+
+ desc = await self.RO.deploy(nsr_id, target)
+ action_id = desc["action_id"]
+ await self._wait_ng_ro(self, nsr_id, action_id, nslcmop_id, start_deploy, timeout_ns_deploy, stage)
+
+ # Updating NSR
+ db_nsr_update = {
+ "_admin.deployed.RO.operational-status": "running",
+ "detailed-status": " ".join(stage)
+ }
+ # db_nsr["_admin.deployed.RO.detailed-status"] = "Deployed at VIM"
+ self.update_db_2("nsrs", nsr_id, db_nsr_update)
+ self._write_op_status(nslcmop_id, stage)
+ self.logger.debug(logging_text + "ns deployed at RO. RO_id={}".format(action_id))
+ return
+
+ async def _wait_ng_ro(self, nsr_id, action_id, nslcmop_id, start_time, timeout, stage):
+ detailed_status_old = None
+ db_nsr_update = {}
+ while time() <= start_time + timeout:
+ desc_status = await self.RO.status(nsr_id, action_id)
+ if desc_status["status"] == "FAILED":
+ raise NgRoException(desc_status["details"])
+ elif desc_status["status"] == "BUILD":
+ stage[2] = "VIM: ({})".format(desc_status["details"])
+ elif desc_status["status"] == "DONE":
+ stage[2] = "Deployed at VIM"
+ break
+ else:
+ assert False, "ROclient.check_ns_status returns unknown {}".format(desc_status["status"])
+ if stage[2] != detailed_status_old:
+ detailed_status_old = stage[2]
+ db_nsr_update["detailed-status"] = " ".join(stage)
+ self.update_db_2("nsrs", nsr_id, db_nsr_update)
+ self._write_op_status(nslcmop_id, stage)
+ await asyncio.sleep(5, loop=self.loop)
+ else: # timeout_ns_deploy
+ raise NgRoException("Timeout waiting ns to deploy")
+
+ async def _terminate_ng_ro(self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage):
+ db_nsr_update = {}
+ failed_detail = []
+ action_id = None
+ start_deploy = time()
+ try:
+ target = {
+ "ns": {"vld": []},
+ "vnf": [],
+ "image": [],
+ "flavor": [],
+ }
+ desc = await self.RO.deploy(nsr_id, target)
+ action_id = desc["action_id"]
+ db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = action_id
+ db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETING"
+ self.logger.debug(logging_text + "ns terminate action at RO. action_id={}".format(action_id))
+
+ # wait until done
+ delete_timeout = 20 * 60 # 20 minutes
+ await self._wait_ng_ro(self, nsr_id, action_id, nslcmop_id, start_deploy, delete_timeout, stage)
+
+ db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
+ db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
+ # delete all nsr
+ await self.RO.delete(nsr_id)
+ except Exception as e:
+ if isinstance(e, NgRoException) and e.http_code == 404: # not found
+ db_nsr_update["_admin.deployed.RO.nsr_id"] = None
+ db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
+ db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
+ self.logger.debug(logging_text + "RO_action_id={} already deleted".format(action_id))
+ elif isinstance(e, NgRoException) and e.http_code == 409: # conflict
+ failed_detail.append("delete conflict: {}".format(e))
+ self.logger.debug(logging_text + "RO_action_id={} delete conflict: {}".format(action_id, e))
+ else:
+ failed_detail.append("delete error: {}".format(e))
+ self.logger.error(logging_text + "RO_action_id={} delete error: {}".format(action_id, e))
+
+ if failed_detail:
+ stage[2] = "Error deleting from VIM"
+ else:
+ stage[2] = "Deleted from VIM"
+ db_nsr_update["detailed-status"] = " ".join(stage)
+ self.update_db_2("nsrs", nsr_id, db_nsr_update)
+ self._write_op_status(nslcmop_id, stage)
+
+ if failed_detail:
+ raise LcmException("; ".join(failed_detail))
+ return
+
async def instantiate_RO(self, logging_text, nsr_id, nsd, db_nsr, db_nslcmop, db_vnfrs, db_vnfds_ref,
n2vc_key_list, stage):
"""
else:
ns_params["vimAccountId"] == vnfr["vim-account-id"]
+ if self.ng_ro:
+ return await self._instantiate_ng_ro(logging_text, nsr_id, nsd, db_nsr, db_nslcmop, db_vnfrs,
+ db_vnfds_ref, n2vc_key_list, stage, start_deploy,
+ timeout_ns_deploy)
# deploy RO
# get vnfds, instantiate at RO
for c_vnf in nsd.get("constituent-vnfd", ()):
self._write_op_status(nslcmop_id, stage)
# await self._on_update_n2vc_db("nsrs", {"_id": nsr_id}, "_admin.deployed", db_nsr_update)
# self.logger.debug(logging_text + "Deployed at VIM")
- except (ROclient.ROClientException, LcmException, DbException) as e:
+ except (ROclient.ROClientException, LcmException, DbException, NgRoException) as e:
stage[2] = "ERROR deploying at VIM"
self.set_vnfr_at_error(db_vnfrs, str(e))
raise
return ip_address
try:
ro_vm_id = "{}-{}".format(db_vnfr["member-vnf-index-ref"], target_vdu_id) # TODO add vdu_index
- result_dict = await self.RO.create_action(
- item="ns",
- item_id_name=ro_nsr_id,
- descriptor={"add_public_key": pub_key, "vms": [ro_vm_id], "user": user}
- )
- # result_dict contains the format {VM-id: {vim_result: 200, description: text}}
- if not result_dict or not isinstance(result_dict, dict):
- raise LcmException("Unknown response from RO when injecting key")
- for result in result_dict.values():
- if result.get("vim_result") == 200:
- break
- else:
- raise ROclient.ROClientException("error injecting key: {}".format(
- result.get("description")))
- break
+ if self.ng_ro:
+ target = {"action": "inject_ssh_key", "key": pub_key, "user": user,
+ "vnf": [{"_id": vnfr_id, "vdur": [{"id": vdu_id}]}],
+ }
+ await self.RO.deploy(nsr_id, target)
+ else:
+ result_dict = await self.RO.create_action(
+ item="ns",
+ item_id_name=ro_nsr_id,
+ descriptor={"add_public_key": pub_key, "vms": [ro_vm_id], "user": user}
+ )
+ # result_dict contains the format {VM-id: {vim_result: 200, description: text}}
+ if not result_dict or not isinstance(result_dict, dict):
+ raise LcmException("Unknown response from RO when injecting key")
+ for result in result_dict.values():
+ if result.get("vim_result") == 200:
+ break
+ else:
+ raise ROclient.ROClientException("error injecting key: {}".format(
+ result.get("description")))
+ break
+ except NgRoException as e:
+ raise LcmException("Reaching max tries injecting key. Error: {}".format(e))
except ROclient.ROClientException as e:
if not nb_tries:
self.logger.debug(logging_text + "error injecting key: {}. Retrying until {} seconds".
# remove from RO
stage[1] = "Deleting ns from VIM."
- task_delete_ro = asyncio.ensure_future(
- self._terminate_RO(logging_text, nsr_deployed, nsr_id, nslcmop_id, stage))
+ if self.ng_ro:
+ task_delete_ro = asyncio.ensure_future(
+ self._terminate_ng_ro(logging_text, nsr_deployed, nsr_id, nslcmop_id, stage))
+ else:
+ task_delete_ro = asyncio.ensure_future(
+ self._terminate_RO(logging_text, nsr_deployed, nsr_id, nslcmop_id, stage))
tasks_dict_info[task_delete_ro] = "Removing deployment from VIM"
# rest of staff will be done at finally
'ca_cert': getenv("OSMLCM_VCA_CACERT", None)
},
"ro_config": {
- "endpoint_url": "http://{}:{}/openmano".format(getenv("OSMLCM_RO_HOST", "ro"),
- getenv("OSMLCM_RO_PORT", "9090")),
+ "uri": "http://{}:{}/openmano".format(getenv("OSMLCM_RO_HOST", "ro"),
+ getenv("OSMLCM_RO_PORT", "9090")),
"tenant": getenv("OSMLCM_RO_TENANT", "osm"),
"logger_name": "lcm.ROclient",
"loglevel": "DEBUG",