from osm_nbi.auth import Authenticator
from osm_nbi.engine import Engine, EngineException
from osm_nbi.subscriptions import SubscriptionThread
+from osm_nbi.utils import cef_event, cef_event_builder
from osm_nbi.validation import ValidationError
from osm_common.dbbase import DbException
from osm_common.fsbase import FsException
auth_database_version = "1.0"
nbi_server = None # instance of Server class
subscription_thread = None # instance of SubscriptionThread class
+cef_logger = None
+logger = logging.getLogger("nbi.nbi")
"""
North Bound Interface (O: OSM specific; 5,X: SOL005 not implemented yet; O5: SOL005 implemented)
/nsd_content O5 O5
/nsd O
/artifacts[/<artifactPath>] O
+ /ns_config_template O O
+ /<nsConfigTemplateId> O O
+ /template_content O O
/pnf_descriptors 5 5
/<pnfdInfoId> 5 5 5
/pnfd_content 5 5
terminate O5
action O
scale O5
- heal 5
+ migrate O
update 05
+ heal O5
/ns_lcm_op_occs 5 5
/<nsLcmOpOccId> 5 5 5
- TO BE COMPLETED 5 5
+ cancel 05
/vnf_instances (also vnfrs for compatibility) O
/<vnfInstanceId> O
/subscriptions 5 5
/subscriptions X X
/<subscriptionId> X X
+ /k8scluster/v1
+ /clusters O O
+ /<clustersId> O O
+ app_profiles O O
+ infra_controller_profiles O O
+ infra_config_profiles O O
+ resource_profiles O O
+ deregister O
+ /register O
+ /app_profiles O O
+ /<app_profilesId> O O O
+ /infra_controller_profiles O O
+ /<infra_controller_profilesId> O O O
+ /infra_config_profiles O O
+ /<infra_config_profilesId> O O O
+ /resource_profiles O O
+ /<resource_profilesID> O O O
+
query string:
Follows SOL005 section 4.3.2 It contains extra METHOD to override http method, FORCE to force.
simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
ADMIN: To act as an administrator or a different project
PUBLIC: To get public descriptors or set a descriptor as public
SET_PROJECT: To make a descriptor available for other project
-
+
Header field name Reference Example Descriptions
Accept IETF RFC 7231 [19] application/json Content-Types that are acceptable for the response.
This header field shall be present if the response is expected to have a non-empty message body.
},
},
},
+ "ns_config_template": {
+ "METHODS": ("GET", "POST"),
+ "ROLE_PERMISSION": "ns_config_template:content:",
+ "<ID>": {
+ "METHODS": ("GET", "DELETE"),
+ "ROLE_PERMISSION": "ns_config_template:id:",
+ "template_content": {
+ "METHODS": ("GET", "PUT"),
+ "ROLE_PERMISSION": "ns_config_template:id:content:",
+ },
+ },
+ },
"pnf_descriptors": {
"TODO": ("GET", "POST"),
"<ID>": {
},
"nslcm": {
"v1": {
+ "ns_instances_terminate": {
+ "METHODS": ("POST"),
+ "ROLE_PERMISSION": "ns_instances:",
+ },
"ns_instances_content": {
"METHODS": ("GET", "POST"),
"ROLE_PERMISSION": "ns_instances:",
"<ID>": {
"METHODS": ("GET", "DELETE"),
"ROLE_PERMISSION": "ns_instances:id:",
+ "heal": {
+ "METHODS": ("POST",),
+ "ROLE_PERMISSION": "ns_instances:id:heal:",
+ },
"scale": {
"METHODS": ("POST",),
"ROLE_PERMISSION": "ns_instances:id:scale:",
"METHODS": ("POST",),
"ROLE_PERMISSION": "ns_instances:id:instantiate:",
},
+ "migrate": {
+ "METHODS": ("POST",),
+ "ROLE_PERMISSION": "ns_instances:id:migrate:",
+ },
"action": {
"METHODS": ("POST",),
"ROLE_PERMISSION": "ns_instances:id:action:",
"<ID>": {
"METHODS": ("GET",),
"ROLE_PERMISSION": "ns_instances:opps:id:",
+ "cancel": {
+ "METHODS": ("POST",),
+ "ROLE_PERMISSION": "ns_instances:opps:cancel:",
+ },
},
},
"vnfrs": {
},
"vnflcm": {
"v1": {
- "vnf_instances": {"METHODS": ("GET", "POST"),
- "ROLE_PERMISSION": "vnflcm_instances:",
- "<ID>": {"METHODS": ("GET", "DELETE"),
- "ROLE_PERMISSION": "vnflcm_instances:id:",
- "scale": {"METHODS": ("POST",),
- "ROLE_PERMISSION": "vnflcm_instances:id:scale:"
- },
- "terminate": {"METHODS": ("POST",),
- "ROLE_PERMISSION": "vnflcm_instances:id:terminate:"
- },
- "instantiate": {"METHODS": ("POST",),
- "ROLE_PERMISSION": "vnflcm_instances:id:instantiate:"
- },
- }
- },
- "vnf_lcm_op_occs": {"METHODS": ("GET",),
- "ROLE_PERMISSION": "vnf_instances:opps:",
- "<ID>": {"METHODS": ("GET",),
- "ROLE_PERMISSION": "vnf_instances:opps:id:"
- },
- },
+ "vnf_instances": {
+ "METHODS": ("GET", "POST"),
+ "ROLE_PERMISSION": "vnflcm_instances:",
+ "<ID>": {
+ "METHODS": ("GET", "DELETE"),
+ "ROLE_PERMISSION": "vnflcm_instances:id:",
+ "scale": {
+ "METHODS": ("POST",),
+ "ROLE_PERMISSION": "vnflcm_instances:id:scale:",
+ },
+ "terminate": {
+ "METHODS": ("POST",),
+ "ROLE_PERMISSION": "vnflcm_instances:id:terminate:",
+ },
+ "instantiate": {
+ "METHODS": ("POST",),
+ "ROLE_PERMISSION": "vnflcm_instances:id:instantiate:",
+ },
+ },
+ },
+ "vnf_lcm_op_occs": {
+ "METHODS": ("GET",),
+ "ROLE_PERMISSION": "vnf_instances:opps:",
+ "<ID>": {
+ "METHODS": ("GET",),
+ "ROLE_PERMISSION": "vnf_instances:opps:id:",
+ },
+ },
+ "subscriptions": {
+ "METHODS": ("GET", "POST"),
+ "ROLE_PERMISSION": "vnflcm_subscriptions:",
+ "<ID>": {
+ "METHODS": ("GET", "DELETE"),
+ "ROLE_PERMISSION": "vnflcm_subscriptions:id:",
+ },
+ },
}
},
"nst": {
},
"nsfm": {
"v1": {
- "alarms": {"METHODS": ("GET", "PATCH"),
- "ROLE_PERMISSION": "alarms:",
- "<ID>": {"METHODS": ("GET", "PATCH"),
- "ROLE_PERMISSION": "alarms:id:",
- },
- }
+ "alarms": {
+ "METHODS": ("GET", "PATCH"),
+ "ROLE_PERMISSION": "alarms:",
+ "<ID>": {
+ "METHODS": ("GET", "PATCH"),
+ "ROLE_PERMISSION": "alarms:id:",
+ },
+ }
},
},
+ "k8scluster": {
+ "v1": {
+ "clusters": {
+ "METHODS": ("GET", "POST"),
+ "ROLE_PERMISSION": "k8scluster:",
+ "<ID>": {
+ "METHODS": ("GET", "DELETE"),
+ "ROLE_PERMISSION": "k8scluster:id:",
+ "app_profiles": {
+ "METHODS": ("PATCH", "GET"),
+ "ROLE_PERMISSION": "k8scluster:id:app_profiles:",
+ },
+ "infra_controller_profiles": {
+ "METHODS": ("PATCH", "GET"),
+ "ROLE_PERMISSION": "k8scluster:id:infra_profiles:",
+ },
+ "infra_config_profiles": {
+ "METHODS": ("PATCH", "GET"),
+ "ROLE_PERMISSION": "k8scluster:id:infra_profiles:",
+ },
+ "resource_profiles": {
+ "METHODS": ("PATCH", "GET"),
+ "ROLE_PERMISSION": "k8scluster:id:infra_profiles:",
+ },
+ "deregister": {
+ "METHODS": ("DELETE",),
+ "ROLE_PERMISSION": "k8scluster:id:deregister:",
+ },
+ "get_creds": {
+ "METHODS": ("GET",),
+ "ROLE_PERMISSION": "k8scluster:id:get_creds:",
+ },
+ "scale": {
+ "METHODS": ("POST",),
+ "ROLE_PERMISSION": "k8scluster:id:scale:",
+ },
+ "upgrade": {
+ "METHODS": ("POST",),
+ "ROLE_PERMISSION": "k8scluster:id:upgrade:",
+ },
+ },
+ "register": {
+ "METHODS": ("POST",),
+ "ROLE_PERMISSION": "k8scluster:register:",
+ },
+ },
+ "app_profiles": {
+ "METHODS": ("POST", "GET"),
+ "ROLE_PERMISSION": "k8scluster:app_profiles:",
+ "<ID>": {
+ "METHODS": ("GET", "PATCH", "DELETE"),
+ "ROLE_PERMISSION": "k8scluster:app_profiles:id:",
+ },
+ },
+ "infra_controller_profiles": {
+ "METHODS": ("POST", "GET"),
+ "ROLE_PERMISSION": "k8scluster:infra_controller_profiles:",
+ "<ID>": {
+ "METHODS": ("GET", "PATCH", "DELETE"),
+ "ROLE_PERMISSION": "k8scluster:infra_controller_profiles:id:",
+ },
+ },
+ "infra_config_profiles": {
+ "METHODS": ("POST", "GET"),
+ "ROLE_PERMISSION": "k8scluster:infra_config_profiles:",
+ "<ID>": {
+ "METHODS": ("GET", "PATCH", "DELETE"),
+ "ROLE_PERMISSION": "k8scluster:infra_config_profiles:id:",
+ },
+ },
+ "resource_profiles": {
+ "METHODS": ("POST", "GET"),
+ "ROLE_PERMISSION": "k8scluster:resource_profiles:",
+ "<ID>": {
+ "METHODS": ("GET", "PATCH", "DELETE"),
+ "ROLE_PERMISSION": "k8scluster:resource_profiles:id:",
+ },
+ },
+ }
+ },
+ "ksu": {
+ "v1": {
+ "ksus": {
+ "METHODS": ("GET", "POST"),
+ "ROLE_PERMISSION": "ksu:",
+ "<ID>": {
+ "METHODS": ("GET", "PATCH", "DELETE"),
+ "ROLE_PERMISSION": "ksu:id:",
+ "clone": {
+ "METHODS": ("POST",),
+ "ROLE_PERMISSION": "ksu:id:clone:",
+ },
+ "move": {
+ "METHODS": ("POST",),
+ "ROLE_PERMISSION": "ksu:id:move:",
+ },
+ },
+ "update": {
+ "METHODS": ("POST",),
+ "ROLE_PERMISSION": "ksu:",
+ },
+ "delete": {
+ "METHODS": ("POST",),
+ "ROLE_PERMISSION": "ksu:",
+ },
+ },
+ }
+ },
+ "oka": {
+ "v1": {
+ "oka_packages": {
+ "METHODS": ("GET", "POST"),
+ "ROLE_PERMISSION": "oka_pkg:",
+ "<ID>": {
+ "METHODS": ("GET", "PATCH", "DELETE", "PUT"),
+ "ROLE_PERMISSION": "oka_pkg:id:",
+ },
+ }
+ }
+ },
}
self.instance += 1
self.authenticator = Authenticator(valid_url_methods, valid_query_string)
self.engine = Engine(self.authenticator)
+ self.logger = logging.getLogger("nbi.server")
def _format_in(self, kwargs):
+ error_text = "" # error_text must be initialized outside try
try:
indata = None
if cherrypy.request.body.length:
cherrypy.request.headers.pop("Content-File-MD5", None)
elif "application/yaml" in cherrypy.request.headers["Content-Type"]:
error_text = "Invalid yaml format "
- indata = yaml.load(
- cherrypy.request.body, Loader=yaml.SafeLoader
- )
+ indata = yaml.safe_load(cherrypy.request.body)
cherrypy.request.headers.pop("Content-File-MD5", None)
elif (
"application/binary" in cherrypy.request.headers["Content-Type"]
"multipart/form-data"
in cherrypy.request.headers["Content-Type"]
):
- if "descriptor_file" in kwargs:
- filecontent = kwargs.pop("descriptor_file")
+ if (
+ "descriptor_file" in kwargs
+ or "package" in kwargs
+ and "name" in kwargs
+ ):
+ filecontent = ""
+ if "descriptor_file" in kwargs:
+ filecontent = kwargs.pop("descriptor_file")
+ if "package" in kwargs:
+ filecontent = kwargs.pop("package")
+ if not filecontent.file:
+ raise NbiException(
+ "empty file or content", HTTPStatus.BAD_REQUEST
+ )
+ indata = filecontent
+ if filecontent.content_type.value:
+ cherrypy.request.headers[
+ "Content-Type"
+ ] = filecontent.content_type.value
+ elif "package" in kwargs:
+ filecontent = kwargs.pop("package")
if not filecontent.file:
raise NbiException(
"empty file or content", HTTPStatus.BAD_REQUEST
)
- indata = filecontent.file # .read()
+ indata = filecontent
if filecontent.content_type.value:
cherrypy.request.headers[
"Content-Type"
# "Only 'Content-Type' of type 'application/json' or
# 'application/yaml' for input format are available")
error_text = "Invalid yaml format "
- indata = yaml.load(
- cherrypy.request.body, Loader=yaml.SafeLoader
- )
+ indata = yaml.safe_load(cherrypy.request.body)
cherrypy.request.headers.pop("Content-File-MD5", None)
else:
error_text = "Invalid yaml format "
- indata = yaml.load(cherrypy.request.body, Loader=yaml.SafeLoader)
+ indata = yaml.safe_load(cherrypy.request.body)
cherrypy.request.headers.pop("Content-File-MD5", None)
if not indata:
indata = {}
-
format_yaml = False
if cherrypy.request.headers.get("Query-String-Format") == "yaml":
format_yaml = True
kwargs[k] = None
elif format_yaml:
try:
- kwargs[k] = yaml.load(v, Loader=yaml.SafeLoader)
+ kwargs[k] = yaml.safe_load(v)
except Exception:
pass
elif (
v[index] = None
elif format_yaml:
try:
- v[index] = yaml.load(v[index], Loader=yaml.SafeLoader)
+ v[index] = yaml.safe_load(v[index])
except Exception:
pass
# NS Fault Management
@cherrypy.expose
- def nsfm(self, version=None, topic=None, uuid=None, project_name=None, ns_id=None, *args, **kwargs):
- if topic == 'alarms':
+ def nsfm(
+ self,
+ version=None,
+ topic=None,
+ uuid=None,
+ project_name=None,
+ ns_id=None,
+ *args,
+ **kwargs
+ ):
+ if topic == "alarms":
try:
method = cherrypy.request.method
- role_permission = self._check_valid_url_method(method, "nsfm", version, topic, None, None, *args)
- query_string_operations = self._extract_query_string_operations(kwargs, method)
+ role_permission = self._check_valid_url_method(
+ method, "nsfm", version, topic, None, None, *args
+ )
+ query_string_operations = self._extract_query_string_operations(
+ kwargs, method
+ )
- self.authenticator.authorize(role_permission, query_string_operations, None)
+ self.authenticator.authorize(
+ role_permission, query_string_operations, None
+ )
# to handle get request
- if cherrypy.request.method == 'GET':
+ if cherrypy.request.method == "GET":
# if request is on basis of uuid
- if uuid and uuid != 'None':
+ if uuid and uuid != "None":
try:
alarm = self.engine.db.get_one("alarms", {"uuid": uuid})
- alarm_action = self.engine.db.get_one("alarms_action", {"uuid": uuid})
+ alarm_action = self.engine.db.get_one(
+ "alarms_action", {"uuid": uuid}
+ )
alarm.update(alarm_action)
- vnf = self.engine.db.get_one("vnfrs", {"nsr-id-ref": alarm["tags"]["ns_id"]})
+ vnf = self.engine.db.get_one(
+ "vnfrs", {"nsr-id-ref": alarm["tags"]["ns_id"]}
+ )
alarm["vnf-id"] = vnf["_id"]
return self._format_out(str(alarm))
except Exception:
return self._format_out("Please provide valid alarm uuid")
- elif ns_id and ns_id != 'None':
+ elif ns_id and ns_id != "None":
# if request is on basis of ns_id
try:
- alarms = self.engine.db.get_list("alarms", {"tags.ns_id": ns_id})
+ alarms = self.engine.db.get_list(
+ "alarms", {"tags.ns_id": ns_id}
+ )
for alarm in alarms:
- alarm_action = self.engine.db.get_one("alarms_action", {"uuid": alarm['uuid']})
+ alarm_action = self.engine.db.get_one(
+ "alarms_action", {"uuid": alarm["uuid"]}
+ )
alarm.update(alarm_action)
return self._format_out(str(alarms))
except Exception:
return self._format_out("Please provide valid ns id")
else:
# to return only alarm which are related to given project
- project = self.engine.db.get_one("projects", {"name": project_name})
- project_id = project.get('_id')
- ns_list = self.engine.db.get_list("nsrs", {"_admin.projects_read": project_id})
+ project = self.engine.db.get_one(
+ "projects", {"name": project_name}
+ )
+ project_id = project.get("_id")
+ ns_list = self.engine.db.get_list(
+ "nsrs", {"_admin.projects_read": project_id}
+ )
ns_ids = []
for ns in ns_list:
ns_ids.append(ns.get("_id"))
alarms = self.engine.db.get_list("alarms")
- alarm_list = [alarm for alarm in alarms if alarm["tags"]["ns_id"] in ns_ids]
+ alarm_list = [
+ alarm
+ for alarm in alarms
+ if alarm["tags"]["ns_id"] in ns_ids
+ ]
for alrm in alarm_list:
- action = self.engine.db.get_one("alarms_action", {"uuid": alrm.get("uuid")})
+ action = self.engine.db.get_one(
+ "alarms_action", {"uuid": alrm.get("uuid")}
+ )
alrm.update(action)
return self._format_out(str(alarm_list))
# to handle patch request for alarm update
- elif cherrypy.request.method == 'PATCH':
- data = yaml.load(cherrypy.request.body, Loader=yaml.SafeLoader)
+ elif cherrypy.request.method == "PATCH":
+ data = yaml.safe_load(cherrypy.request.body)
try:
# check if uuid is valid
self.engine.db.get_one("alarms", {"uuid": data.get("uuid")})
return self._format_out("Please provide valid alarm uuid.")
if data.get("is_enable") is not None:
if data.get("is_enable"):
- alarm_status = 'ok'
+ alarm_status = "ok"
else:
- alarm_status = 'disabled'
- self.engine.db.set_one("alarms", {"uuid": data.get("uuid")},
- {"alarm_status": alarm_status})
+ alarm_status = "disabled"
+ self.engine.db.set_one(
+ "alarms",
+ {"uuid": data.get("uuid")},
+ {"alarm_status": alarm_status},
+ )
else:
- self.engine.db.set_one("alarms", {"uuid": data.get("uuid")},
- {"threshold": data.get("threshold")})
+ self.engine.db.set_one(
+ "alarms",
+ {"uuid": data.get("uuid")},
+ {"threshold": data.get("threshold")},
+ )
return self._format_out("Alarm updated")
except Exception as e:
- cherrypy.response.status = e.http_code.value
- if isinstance(e, (NbiException, EngineException, DbException, FsException, MsgException, AuthException,
- ValidationError, AuthconnException)):
+ if isinstance(
+ e,
+ (
+ NbiException,
+ EngineException,
+ DbException,
+ FsException,
+ MsgException,
+ AuthException,
+ ValidationError,
+ AuthconnException,
+ ),
+ ):
http_code_value = cherrypy.response.status = e.http_code.value
http_code_name = e.http_code.name
cherrypy.log("Exception {}".format(e))
else:
- http_code_value = cherrypy.response.status = HTTPStatus.BAD_REQUEST.value # INTERNAL_SERVER_ERROR
+ http_code_value = (
+ cherrypy.response.status
+ ) = HTTPStatus.BAD_REQUEST.value # INTERNAL_SERVER_ERROR
cherrypy.log("CRITICAL: Exception {}".format(e), traceback=True)
http_code_name = HTTPStatus.BAD_REQUEST.name
problem_details = {
outdata = token_info = self.authenticator.new_token(
token_info, indata, cherrypy.request.remote
)
- cherrypy.session["Authorization"] = outdata["_id"]
+ cherrypy.session["Authorization"] = outdata["_id"] # pylint: disable=E1101
self._set_location_header("admin", "v1", "tokens", outdata["_id"])
# for logging
self._format_login(token_info)
# password expiry check
if self.authenticator.check_password_expiry(outdata):
- outdata = {"id": outdata["id"],
- "message": "change_password",
- "user_id": outdata["user_id"]
- }
+ outdata = {
+ "id": outdata["id"],
+ "message": "change_password",
+ "user_id": outdata["user_id"],
+ }
# cherrypy.response.cookie["Authorization"] = outdata["id"]
# cherrypy.response.cookie["Authorization"]['expires'] = 3600
+ cef_event(
+ cef_logger,
+ {
+ "name": "User Login",
+ "sourceUserName": token_info.get("username"),
+ "message": "User Logged In, Project={} Outcome=Success".format(
+ token_info.get("project_name")
+ ),
+ },
+ )
+ cherrypy.log("{}".format(cef_logger))
elif method == "DELETE":
if not token_id and "id" in kwargs:
token_id = kwargs["id"]
# for logging
self._format_login(token_info)
token_id = token_info["_id"]
+ if current_backend != "keystone":
+ token_details = self.engine.db.get_one("tokens", {"_id": token_id})
+ current_user = token_details.get("username")
+ current_project = token_details.get("project_name")
+ else:
+ current_user = "keystone backend"
+ current_project = "keystone backend"
outdata = self.authenticator.del_token(token_id)
token_info = None
- cherrypy.session["Authorization"] = "logout"
+ cherrypy.session["Authorization"] = "logout" # pylint: disable=E1101
+ cef_event(
+ cef_logger,
+ {
+ "name": "User Logout",
+ "sourceUserName": current_user,
+ "message": "User Logged Out, Project={} Outcome=Success".format(
+ current_project
+ ),
+ },
+ )
+ cherrypy.log("{}".format(cef_logger))
# cherrypy.response.cookie["Authorization"] = token_id
# cherrypy.response.cookie["Authorization"]['expires'] = 0
else:
elif args and args[0] == "init":
try:
# self.engine.load_dbase(cherrypy.request.app.config)
- self.engine.create_admin()
+ pid = self.authenticator.create_admin_project()
+ self.authenticator.create_admin_user(pid)
return "Done. User 'admin', password 'admin' created"
except Exception:
cherrypy.response.status = HTTPStatus.FORBIDDEN.value
return_text = "<html><pre>{} ->\n".format(main_topic)
try:
if cherrypy.request.method == "POST":
- to_send = yaml.load(cherrypy.request.body, Loader=yaml.SafeLoader)
+ to_send = yaml.safe_load(cherrypy.request.body)
for k, v in to_send.items():
self.engine.msg.write(main_topic, k, v)
return_text += " {}: {}\n".format(k, v)
elif cherrypy.request.method == "GET":
for k, v in kwargs.items():
- v_dict = yaml.load(v, Loader=yaml.SafeLoader)
+ v_dict = yaml.safe_load(v)
self.engine.msg.write(main_topic, k, v_dict)
return_text += " {}: {}\n".format(k, v_dict)
except Exception as e:
+ " headers: {}\n".format(cherrypy.request.headers)
+ " path_info: {}\n".format(cherrypy.request.path_info)
+ " query_string: {}\n".format(cherrypy.request.query_string)
- + " session: {}\n".format(cherrypy.session)
+ + " session: {}\n".format(cherrypy.session) # pylint: disable=E1101
+ " cookie: {}\n".format(cherrypy.request.cookie)
+ " method: {}\n".format(cherrypy.request.method)
- + " session: {}\n".format(cherrypy.session.get("fieldname"))
+ + " session: {}\n".format(
+ cherrypy.session.get("fieldname") # pylint: disable=E1101
+ )
+ " body:\n"
)
return_text += " length: {}\n".format(cherrypy.request.body.length)
**kwargs
):
token_info = None
- outdata = None
+ outdata = {}
_format = None
method = "DONE"
engine_topic = None
rollback = []
engine_session = None
+ url_id = ""
+ log_mapping = {
+ "POST": "Creating",
+ "GET": "Fetching",
+ "DELETE": "Deleting",
+ "PUT": "Updating",
+ "PATCH": "Updating",
+ }
try:
if not main_topic or not version or not topic:
raise NbiException(
"nsilcm",
"nspm",
"vnflcm",
+ "k8scluster",
+ "ksu",
+ "oka",
):
raise NbiException(
"URL main_topic '{}' not supported".format(main_topic),
"URL version '{}' not supported".format(version),
HTTPStatus.METHOD_NOT_ALLOWED,
)
+ if _id is not None:
+ url_id = _id
if (
kwargs
if main_topic == "nsd":
engine_topic = "nsds"
+ if topic == "ns_config_template":
+ engine_topic = "nsconfigtemps"
elif main_topic == "vnfpkgm":
engine_topic = "vnfds"
if topic == "vnfpkg_op_occs":
engine_topic = "nsilcmops"
elif main_topic == "pdu":
engine_topic = "pdus"
+ elif main_topic == "k8scluster":
+ engine_topic = "k8s"
+ if topic == "clusters" and _id == "register" or item == "deregister":
+ engine_topic = "k8sops"
+ elif topic == "infra_controller_profiles":
+ engine_topic = "infras_cont"
+ elif topic == "infra_config_profiles":
+ engine_topic = "infras_conf"
+ elif topic == "resource_profiles":
+ engine_topic = "resources"
+ elif topic == "app_profiles":
+ engine_topic = "apps"
+ elif main_topic == "k8scluster" and item in (
+ "upgrade",
+ "get_creds",
+ "scale",
+ ):
+ engine_topic = "k8s"
+ elif main_topic == "ksu" and engine_topic in ("ksus", "clone", "move"):
+ engine_topic = "ksus"
if (
engine_topic == "vims"
): # TODO this is for backward compatibility, it will be removed in the future
"nsd",
"nst",
"nst_content",
+ "ns_config_template",
):
if item in ("vnfd", "nsd", "nst"):
path = "$DESCRIPTOR"
outdata = self.engine.get_item_list(
engine_session, engine_topic, kwargs, api_req=True
)
+ elif topic == "clusters" and item in (
+ "infra_controller_profiles",
+ "infra_config_profiles",
+ "app_profiles",
+ "resource_profiles",
+ ):
+ profile = item
+ filter_q = None
+ outdata = self.engine.get_one_item(
+ engine_session,
+ engine_topic,
+ _id,
+ profile,
+ filter_q,
+ api_req=True,
+ )
+ elif topic == "clusters" and item == "get_creds":
+ outdata = self.engine.get_cluster_info(
+ engine_session, engine_topic, _id, item
+ )
else:
if item == "reports":
# TODO check that project_id (_id in this context) has permissions
filter_q = None
if "vcaStatusRefresh" in kwargs:
filter_q = {"vcaStatusRefresh": kwargs["vcaStatusRefresh"]}
- outdata = self.engine.get_item(engine_session, engine_topic, _id, filter_q, True)
+ outdata = self.engine.get_item(
+ engine_session, engine_topic, _id, filter_q, True
+ )
elif method == "POST":
cherrypy.response.status = HTTPStatus.CREATED.value
"ns_descriptors_content",
"vnf_packages_content",
"netslice_templates_content",
+ "ns_config_template",
):
_id = cherrypy.request.headers.get("Transaction-Id")
+
if not _id:
_id, _ = self.engine.new_item(
rollback,
else:
cherrypy.response.headers["Transaction-Id"] = _id
outdata = {"id": _id}
+ elif topic == "oka_packages":
+ _id = cherrypy.request.headers.get("Transaction-Id")
+
+ if not _id:
+ _id, _ = self.engine.new_item(
+ rollback,
+ engine_session,
+ engine_topic,
+ {},
+ kwargs,
+ cherrypy.request.headers,
+ )
+ cherrypy.request.headers["method"] = cherrypy.request.method
+ if indata:
+ completed = self.engine.upload_content(
+ engine_session,
+ engine_topic,
+ _id,
+ indata,
+ None,
+ cherrypy.request.headers,
+ )
+ if completed:
+ self._set_location_header(main_topic, version, topic, _id)
+ else:
+ cherrypy.response.headers["Transaction-Id"] = _id
+ outdata = {"_id": _id}
elif topic == "ns_instances_content":
# creates NSR
_id, _ = self.engine.new_item(
# creates nslcmop
indata["lcmOperationType"] = "instantiate"
indata["nsInstanceId"] = _id
- nslcmop_id, _ = self.engine.new_item(
+ nslcmop_id, nsName, _ = self.engine.new_item(
rollback, engine_session, "nslcmops", indata, None
)
self._set_location_header(main_topic, version, topic, _id)
- outdata = {"id": _id, "nslcmop_id": nslcmop_id}
+ outdata = {"id": _id, "nslcmop_id": nslcmop_id, "nsName": nsName}
+ elif topic == "ns_instances_terminate":
+ if indata.get("ns_ids"):
+ for ns_id in indata.get("ns_ids"):
+ nslcmop_desc = {
+ "lcmOperationType": "terminate",
+ "nsInstanceId": ns_id,
+ "autoremove": indata.get("autoremove")
+ if "autoremove" in indata
+ else True,
+ }
+ op_id, _, _ = self.engine.new_item(
+ rollback,
+ engine_session,
+ "nslcmops",
+ nslcmop_desc,
+ kwargs,
+ )
+ if not op_id:
+ _ = self.engine.del_item(
+ engine_session, engine_topic, ns_id
+ )
+ outdata = {"ns_ids": indata.get("ns_ids")}
+ cherrypy.response.status = HTTPStatus.ACCEPTED.value
elif topic == "ns_instances" and item:
indata["lcmOperationType"] = item
indata["nsInstanceId"] = _id
- _id, _ = self.engine.new_item(
+ _id, nsName, _ = self.engine.new_item(
rollback, engine_session, "nslcmops", indata, kwargs
)
self._set_location_header(
main_topic, version, "ns_lcm_op_occs", _id
)
- outdata = {"id": _id}
+ outdata = {"id": _id, "nsName": nsName}
cherrypy.response.status = HTTPStatus.ACCEPTED.value
elif topic == "netslice_instances_content":
# creates NetSlice_Instance_record (NSIR)
elif topic == "vnf_instances" and item:
indata["lcmOperationType"] = item
indata["vnfInstanceId"] = _id
- _id, _ = self.engine.new_item(rollback, engine_session, "vnflcmops", indata, kwargs)
- self._set_location_header(main_topic, version, "vnf_lcm_op_occs", _id)
- outdata = {"id": _id}
+ _id, nsName, _ = self.engine.new_item(
+ rollback, engine_session, "vnflcmops", indata, kwargs
+ )
+ self._set_location_header(
+ main_topic, version, "vnf_lcm_op_occs", _id
+ )
+ outdata = {"id": _id, "nsName": nsName}
cherrypy.response.status = HTTPStatus.ACCEPTED.value
+ elif topic == "ns_lcm_op_occs" and item == "cancel":
+ indata["nsLcmOpOccId"] = _id
+ self.engine.cancel_item(
+ rollback, engine_session, "nslcmops", indata, None
+ )
+ self._set_location_header(main_topic, version, topic, _id)
+ cherrypy.response.status = HTTPStatus.ACCEPTED.value
+ elif topic == "clusters" and _id == "register":
+ # To register a cluster
+ _id, _ = self.engine.add_item(
+ rollback, engine_session, engine_topic, indata, kwargs
+ )
+ self._set_location_header(main_topic, version, topic, _id)
+ outdata = {"id": _id}
+ elif (
+ topic
+ in (
+ "clusters",
+ "infra_controller_profiles",
+ "infra_config_profiles",
+ "app_profiles",
+ "resource_profiles",
+ )
+ and item is None
+ ):
+ # creates cluster, infra_controller_profiles, app_profiles, infra_config_profiles, and resource_profiles
+ _id, _ = self.engine.new_item(
+ rollback, engine_session, engine_topic, indata, kwargs
+ )
+ self._set_location_header(main_topic, version, topic, _id)
+ outdata = {"_id": _id}
+ elif topic == "ksus" and item:
+ if item == "clone":
+ _id = self.engine.clone(
+ rollback,
+ engine_session,
+ engine_topic,
+ _id,
+ indata,
+ kwargs,
+ cherrypy.request.headers,
+ )
+ self._set_location_header(main_topic, version, topic, _id)
+ outdata = {"id": _id}
+ if item == "move":
+ op_id = self.engine.move_ksu(
+ engine_session, engine_topic, _id, indata, kwargs
+ )
+ outdata = {"op_id": op_id}
+ elif topic == "ksus" and _id == "delete":
+ op_id = self.engine.delete_ksu(
+ engine_session, engine_topic, _id, indata
+ )
+ outdata = {"op_id": op_id}
+ elif topic == "ksus" and _id == "update":
+ op_id = self.engine.edit_item(
+ engine_session, engine_topic, _id, indata, kwargs
+ )
+ outdata = {"op_id": op_id}
+ elif topic == "clusters" and item in ("upgrade", "scale"):
+ op_id = self.engine.update_cluster(
+ engine_session, engine_topic, _id, item, indata
+ )
+ outdata = {"op_id": op_id}
else:
_id, op_id = self.engine.new_item(
rollback,
"nsInstanceId": _id,
"autoremove": True,
}
- op_id, _ = self.engine.new_item(
+ op_id, nsName, _ = self.engine.new_item(
rollback, engine_session, "nslcmops", nslcmop_desc, kwargs
)
if op_id:
- outdata = {"_id": op_id}
+ outdata = {"_id": op_id, "nsName": nsName}
elif (
topic == "netslice_instances_content"
and not engine_session["force"]
)
if op_id:
outdata = {"_id": op_id}
+ elif topic == "clusters" and item == "deregister":
+ if not op_id:
+ op_id = self.engine.remove(
+ engine_session, engine_topic, _id
+ )
+ if op_id:
+ outdata = {"_id": op_id}
+ cherrypy.response.status = (
+ HTTPStatus.ACCEPTED.value
+ if op_id
+ else HTTPStatus.NO_CONTENT.value
+ )
+ elif topic == "ksus":
+ op_id = self.engine.delete_ksu(
+ engine_session, engine_topic, _id, indata
+ )
+ outdata = {"op_id": op_id}
# if there is not any deletion in process, delete
- if not op_id:
+ elif not op_id:
op_id = self.engine.del_item(engine_session, engine_topic, _id)
if op_id:
- outdata = {"op_id": op_id}
+ outdata = {"_id": op_id}
cherrypy.response.status = (
HTTPStatus.ACCEPTED.value
if op_id
HTTPStatus.BAD_REQUEST,
)
if (
- item in ("nsd_content", "package_content", "nst_content")
+ item
+ in (
+ "nsd_content",
+ "package_content",
+ "nst_content",
+ "template_content",
+ )
and method == "PUT"
):
completed = self.engine.upload_content(
)
if not completed:
cherrypy.response.headers["Transaction-Id"] = id
+ elif item in (
+ "app_profiles",
+ "resource_profiles",
+ "infra_controller_profiles",
+ "infra_config_profiles",
+ ):
+ op_id = self.engine.edit(
+ engine_session, engine_topic, _id, item, indata, kwargs
+ )
+ elif topic == "oka_packages" and method == "PATCH":
+ if kwargs:
+ op_id = self.engine.edit_item(
+ engine_session, engine_topic, _id, None, kwargs
+ )
+ if indata:
+ if isinstance(indata, dict):
+ op_id = self.engine.edit_item(
+ engine_session, engine_topic, _id, indata, kwargs
+ )
+ else:
+ cherrypy.request.headers["method"] = cherrypy.request.method
+ completed = self.engine.upload_content(
+ engine_session,
+ engine_topic,
+ _id,
+ indata,
+ {},
+ cherrypy.request.headers,
+ )
+ if not completed:
+ cherrypy.response.headers["Transaction-Id"] = id
+ elif topic == "oka_packages" and method == "PUT":
+ if indata:
+ cherrypy.request.headers["method"] = cherrypy.request.method
+ completed = self.engine.upload_content(
+ engine_session,
+ engine_topic,
+ _id,
+ indata,
+ {},
+ cherrypy.request.headers,
+ )
+ if not completed:
+ cherrypy.response.headers["Transaction-Id"] = id
else:
op_id = self.engine.edit_item(
engine_session, engine_topic, _id, indata, kwargs
):
self.authenticator.remove_token_from_cache()
+ cef_event(
+ cef_logger,
+ {
+ "name": "User Operation",
+ "sourceUserName": token_info.get("username"),
+ },
+ )
+ if topic == "ns_instances_content" and url_id:
+ nsName = (
+ outdata.get("name") if method == "GET" else outdata.get("nsName")
+ )
+ cef_event(
+ cef_logger,
+ {
+ "message": "{} {}, nsName={}, nsdId={}, Project={} Outcome=Success".format(
+ log_mapping[method],
+ topic,
+ nsName,
+ outdata.get("id"),
+ token_info.get("project_name"),
+ ),
+ },
+ )
+ cherrypy.log("{}".format(cef_logger))
+ elif topic == "ns_instances_content" and method == "POST":
+ cef_event(
+ cef_logger,
+ {
+ "message": "{} {}, nsName={}, nsdId={}, Project={} Outcome=Success".format(
+ log_mapping[method],
+ topic,
+ outdata.get("nsName"),
+ outdata.get("id"),
+ token_info.get("project_name"),
+ ),
+ },
+ )
+ cherrypy.log("{}".format(cef_logger))
+ elif topic in ("ns_instances", "vnf_instances") and item:
+ cef_event(
+ cef_logger,
+ {
+ "message": "{} {}, nsName={}, nsdId={}, Project={} Outcome=Success".format(
+ log_mapping[method],
+ topic,
+ outdata.get("nsName"),
+ url_id,
+ token_info.get("project_name"),
+ ),
+ },
+ )
+ cherrypy.log("{}".format(cef_logger))
+ elif item is not None:
+ cef_event(
+ cef_logger,
+ {
+ "message": "Performing {} operation on {} {}, Project={} Outcome=Success".format(
+ item,
+ topic,
+ url_id,
+ token_info.get("project_name"),
+ ),
+ },
+ )
+ cherrypy.log("{}".format(cef_logger))
+ else:
+ cef_event(
+ cef_logger,
+ {
+ "message": "{} {} {}, Project={} Outcome=Success".format(
+ log_mapping[method],
+ topic,
+ url_id,
+ token_info.get("project_name"),
+ ),
+ },
+ )
+ cherrypy.log("{}".format(cef_logger))
return self._format_out(outdata, token_info, _format)
except Exception as e:
if isinstance(
self.engine.db.del_list(
rollback_item["topic"],
rollback_item["filter"],
- fail_on_empty=False,
)
else:
self.engine.db.del_one(
"status": http_code_value,
"detail": error_text,
}
+ if item is not None and token_info is not None:
+ cef_event(
+ cef_logger,
+ {
+ "name": "User Operation",
+ "sourceUserName": token_info.get("username", None),
+ "message": "Performing {} operation on {} {}, Project={} Outcome=Failure".format(
+ item,
+ topic,
+ url_id,
+ token_info.get("project_name", None),
+ ),
+ "severity": "2",
+ },
+ )
+ cherrypy.log("{}".format(cef_logger))
+ elif token_info is not None:
+ cef_event(
+ cef_logger,
+ {
+ "name": "User Operation",
+ "sourceUserName": token_info.get("username", None),
+ "message": "{} {} {}, Project={} Outcome=Failure".format(
+ item,
+ topic,
+ url_id,
+ token_info.get("project_name", None),
+ ),
+ "severity": "2",
+ },
+ )
+ cherrypy.log("{}".format(cef_logger))
return self._format_out(problem_details, token_info)
# raise cherrypy.HTTPError(e.http_code.value, str(e))
finally:
"""
global nbi_server
global subscription_thread
+ global cef_logger
+ global current_backend
cherrypy.log.error("Starting osm_nbi")
# update general cherrypy configuration
update_dict = {}
engine_config = cherrypy.tree.apps["/osm"].config
for k, v in environ.items():
+ if k == "OSMNBI_USER_MANAGEMENT":
+ feature_state = eval(v.title())
+ engine_config["authentication"]["user_management"] = feature_state
+ elif k == "OSMNBI_PWD_EXPIRE_DAYS":
+ pwd_expire_days = int(v)
+ engine_config["authentication"]["pwd_expire_days"] = pwd_expire_days
+ elif k == "OSMNBI_MAX_PWD_ATTEMPT":
+ max_pwd_attempt = int(v)
+ engine_config["authentication"]["max_pwd_attempt"] = max_pwd_attempt
+ elif k == "OSMNBI_ACCOUNT_EXPIRE_DAYS":
+ account_expire_days = int(v)
+ engine_config["authentication"]["account_expire_days"] = account_expire_days
if not k.startswith("OSMNBI_"):
continue
k1, _, k2 = k[7:].lower().partition("_")
except ValueError as e:
cherrypy.log.error("Ignoring environ '{}': " + str(e))
except Exception as e:
- cherrypy.log.warn("skipping environ '{}' on exception '{}'".format(k, e))
+ cherrypy.log(
+ "WARNING: skipping environ '{}' on exception '{}'".format(k, e)
+ )
if update_dict:
cherrypy.config.update(update_dict)
target_version=auth_database_version
)
+ cef_logger = cef_event_builder(engine_config["authentication"])
+
# start subscriptions thread:
subscription_thread = SubscriptionThread(
config=engine_config, engine=nbi_server.engine
# Do not capture except SubscriptionException
backend = engine_config["authentication"]["backend"]
+ current_backend = backend
cherrypy.log.error(
"Starting OSM NBI Version '{} {}' with '{}' authentication backend".format(
nbi_version, nbi_version_date, backend