New version of NearRT-RIC simulator

Change-Id: I9b14b8e6a32974e92a57af994762be064b04b7a7
Issue-ID: NONRTRIC-78
Signed-off-by: maximesson <maxime.bonneau@est.tech>
diff --git a/near-rt-ric-simulator/ric-plt/a1/Dockerfile b/near-rt-ric-simulator/ric-plt/a1/Dockerfile
new file mode 100644
index 0000000..db06a21
--- /dev/null
+++ b/near-rt-ric-simulator/ric-plt/a1/Dockerfile
@@ -0,0 +1,21 @@
+FROM python:3
+
+WORKDIR /usr/src/app
+
+RUN pip install connexion[swagger-ui]
+
+COPY policy_instance_1_STD_QoSNudging_0.1.0.json policy_instance_1_STD_QoSNudging_0.1.0.json
+COPY policy_instance_1_bis_STD_QoSNudging_0.1.0.json policy_instance_1_bis_STD_QoSNudging_0.1.0.json
+COPY policy_instance_2_STD_QoSNudging_0.1.0.json policy_instance_2_STD_QoSNudging_0.1.0.json
+COPY policy_type_STD_QoSNudging_0.1.0.json policy_type_STD_QoSNudging_0.1.0.json
+
+COPY a1.py a1.py
+COPY main.py main.py
+COPY var_declaration.py var_declaration.py
+
+COPY commands.sh commands.sh
+COPY run_me.sh run_me.sh
+
+COPY a1-openapi.yaml a1-openapi.yaml
+
+CMD ["/bin/bash", "./run_me.sh"]
diff --git a/near-rt-ric-simulator/ric-plt/a1/a1-openapi.yaml b/near-rt-ric-simulator/ric-plt/a1/a1-openapi.yaml
new file mode 100644
index 0000000..c98d2b0
--- /dev/null
+++ b/near-rt-ric-simulator/ric-plt/a1/a1-openapi.yaml
@@ -0,0 +1,466 @@
+openapi: 3.0.0
+info:
+  title: 'A1-P Policy Management Service'
+  version: 1.1.x
+  description: |
+    API for Policy Management Service.
+    © 2019, O-RAN Alliance.
+    All rights reserved.
+externalDocs:
+  description: 'ORAN-WG2.A1.AP-v01.01 A1 interface: Application protocol'
+  url: 'https://www.o-ran.org/specifications'
+servers:
+  - url: '{apiRoot}/A1-P/v1'
+    variables:
+      apiRoot:
+        default: 'https://example.com'
+        description: 'apiRoot as defined in clause 4.2.1 in ORAN-WG2.A1.AP'
+paths:
+  '/policies':
+    get:
+      operationId: a1.get_all_policies
+      description: 'Get all policies including their enforcement status'
+      tags:
+      - All Policy Objects
+      responses:
+        200:
+          description: 'Array of all policies and their enforcement status'
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  "$ref": "#/components/schemas/PolicyObject"
+                minItems: 0
+
+  '/policies/identities':
+    get:
+      operationId: a1.get_all_policy_identities
+      description: 'Get all policy identities'
+      tags:
+      - All Policy Identities
+      responses:
+        200:
+          description: 'Array of all policy identities'
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  "$ref": "#/components/schemas/PolicyId"
+                minItems: 0
+
+  '/policies/status':
+    get:
+      operationId: a1.get_all_policy_status
+      description: 'Get enforcement status for all policy instances'
+      tags:
+      - All Policy Status Objects
+      responses:
+        200:
+          description: 'Array of all policy identities and their related enforcement status'
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  "$ref": "#/components/schemas/PolicyStatusObject"
+                minItems: 0
+
+  '/policies/{policyId}':
+    parameters:
+      - name: policyId
+        in: path
+        required: true
+        schema:
+          "$ref": "#/components/schemas/PolicyId"
+    put:
+      operationId: a1.put_policy
+      description: 'Create, or update, a policy'
+      tags:
+      - Individual Policy Object
+      requestBody:
+        content:
+          application/json:
+            schema:
+              "$ref": "#/components/schemas/PolicyObject"
+      responses:
+        200:
+          description: 'The policy was updated'
+          content:
+            application/json:
+              schema:
+                "$ref": "#/components/schemas/PolicyObject"
+        201:
+          description: 'The policy was created'
+          content:
+            application/json:
+              schema:
+                "$ref": "#/components/schemas/PolicyObject"
+          headers:
+            Location:
+              description: 'Contains the URI of the created policy'
+              required: true
+              schema:
+                type: string
+        400:
+          "$ref": "#/components/responses/400-BadRequest"
+      callbacks:
+        policyNotification:
+          '$request.body#/notificationDestination':
+            post:
+              description: 'Notify about enforcement status changes for this policy'
+              requestBody:
+                required: true
+                content:
+                  application/json:
+                    schema:
+                      "$ref": "#/components/schemas/PolicyStatusObject"
+              responses:
+                204:
+                  description: 'Notification received'
+    get:
+      operationId: a1.get_policy
+      description: 'Query single policy'
+      tags:
+      - Individual Policy Object
+      responses:
+        200:
+          description: 'The requested policy'
+          content:
+            application/json:
+              schema:
+                "$ref": "#/components/schemas/PolicyObject"
+        404:
+          "$ref": "#/components/responses/404-NotFound"
+    delete:
+      operationId: a1.delete_policy
+      description: 'Delete policy'
+      tags:
+      - Individual Policy Object
+      responses:
+        204:
+          description: 'The policy was deleted'
+        404:
+          "$ref": "#/components/responses/404-NotFound"
+
+  '/policies/{policyId}/status':
+    parameters:
+      - name: policyId
+        in: path
+        required: true
+        schema:
+          "$ref": "#/components/schemas/PolicyId"
+    get:
+      operationId: a1.get_policy_status
+      description: 'Get the enforcement status of a policy'
+      tags:
+      - Individual Policy Status Object
+      responses:
+        200:
+          description: 'The requested enforcement status'
+          content:
+            application/json:
+              schema:
+                "$ref": "#/components/schemas/PolicyStatusObject"
+        404:
+          "$ref": "#/components/responses/404-NotFound"
+
+  '/policytypes':
+    get:
+      operationId: a1.get_all_policytypes
+      description: 'Get all policy type schemas'
+      tags:
+      - All Policy Types
+      responses:
+        200:
+          description: 'Array of all policy type schemas'
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  "$ref": "#/components/schemas/PolicyTypeSchema"
+                minItems: 0
+
+  '/policytypes/identities':
+    get:
+      operationId: a1.get_all_policytypes_identities
+      description: 'Get all policy type identities'
+      tags:
+      - All Policy Type Identities
+      responses:
+        200:
+          description: 'Array of all policy type identities'
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  "$ref": "#/components/schemas/PolicyTypeId"
+                minItems: 0
+
+  '/policytypes/{policyTypeId}':
+    parameters:
+      - name: policyTypeId
+        in: path
+        required: true
+        schema:
+          "$ref": "#/components/schemas/PolicyTypeId"
+    get:
+      operationId: a1.get_policytypes
+      description: 'Get the schema for a policy type'
+      tags:
+      - Individual Policy Type
+      responses:
+        200:
+          description: 'The policy type schema'
+          content:
+            application/json:
+              schema:
+                "$ref": "#/components/schemas/PolicyTypeSchema"
+        404:
+          "$ref": "#/components/responses/404-NotFound"
+
+  '/policytypes/subscription':
+    put:
+      operationId: a1.put_policytypes_subscription
+      description: 'Subscribe to notification when any change is made to supported policy types'
+      tags:
+      - Policy Types Subscription Object
+      requestBody:
+        content:
+          application/json:
+            schema:
+              "$ref": "#/components/schemas/SubscriptionObject"
+      responses:
+        200:
+          description: 'The subscription was updated'
+        201:
+          description: 'The subscription was created'
+      callbacks:
+        policyTypesNotification:
+          '$request.body#/notificationDestination':
+            post:
+              description: 'Notify about any change in supported policy types'
+              responses:
+                204:
+                  description: 'Notification received'
+    get:
+      operationId: a1.get_policytypes_subscription
+      description: 'Get current notification destination'
+      tags:
+      - Policy Types Subscription Object
+      responses:
+        200:
+          description: 'The current notification destination'
+          content:
+            application/json:
+              schema:
+                "$ref": "#/components/schemas/SubscriptionObject"
+        404:
+          "$ref": "#/components/responses/404-NotFound"
+
+components:
+  schemas:
+    #
+    # Representation objects
+    #
+    PolicyStatusObject:
+      type: object
+      properties:
+        policyId:
+          "$ref": "#/components/schemas/PolicyId"
+        enforceStatus:
+          "$ref": "#/components/schemas/EnforcementStatusType"
+        enforceReason:
+          "$ref": "#/components/schemas/EnforcementReasonType"
+      required:
+      - policyId
+      - enforceStatus
+
+    PolicyObject:
+      description: 'A policy object, including its identification, type information, its notification destination, and optionally its enforcement status.'
+      type: object
+      properties:
+        policyId:
+          "$ref": "#/components/schemas/PolicyId"
+        policyTypeId:
+          "$ref": "#/components/schemas/PolicyTypeId"
+        policyClause:
+          "$ref": "#/components/schemas/PolicyClause"
+        notificationDestination:
+          "$ref": "#/components/schemas/NotificationDestination"
+        enforceStatus:
+          "$ref": "#/components/schemas/EnforcementStatusType"
+      required:
+      - policyId
+      - policyTypeId
+      - policyClause
+      - notificationDestination
+
+    PolicyTypeSchema:
+      description: 'The JSON Schema for a policy type. All policies of a policy type shall validate against this schema.'
+      type: object
+      properties:
+        description:
+          type: string
+        properties:
+          type: object
+        title:
+          type: string
+        type:
+          type: string
+      required:
+      - description
+      - properties
+      - title
+      - type
+
+    ProblemDetails:
+      description: 'A problem detail to carry details in a HTTP response according to RFC 7807 extended with A1 specific attributes'
+      type: object
+      properties:
+        type:
+          type: string
+        title:
+          type: string
+        status:
+          type: number
+        detail:
+          type: string
+        instance:
+          type: string
+        policyErrorCode:
+          "$ref": "#/components/schemas/PolicyErrorType"
+        invalidParams:
+          type: array
+          items:
+            "$ref": "#/components/schemas/InvalidParam"
+          minItems: 1
+
+    SubscriptionObject:
+      description: 'A subscription object used for specifying the destination where to send notifications.'
+      type: object
+      properties:
+        notificationDestination:
+          "$ref": "#/components/schemas/NotificationDestination"
+      required:
+      - notificationDestination
+
+    #
+    # Structured data types
+    #
+    InvalidParam:
+      description: 'Used in a ProblemDetails to indicate a specific invalid parameter'
+      type: object
+      properties:
+        param:
+          type: string
+        reason:
+          type: string
+      required:
+        - param
+
+    PolicyClause:
+      description: 'The schema for a generic policy clause that shall be valid for all different specific policy types.'
+      type: object
+      properties:
+        scope:
+          "$ref": "#/components/schemas/ScopeIdentifier"
+        statement:
+          description: 'The statement for a specific policy type. The schema is specified by a specific policy type.'
+          type: object
+      required:
+      - scope
+      - statement
+
+    ScopeIdentifier:
+      description: 'The schema for a generic scope identifier that shall be valid for all different specific policy types.'
+      type: object
+      properties:
+        ueId:
+          description: 'UE identifier based on RAN UE Id'
+          type: string
+        groupId:
+          description: 'Identifier of a pre-defined group of UEs, SPID'
+          type: string
+        sliceId:
+          description: 'Network slice identifie, NSSAI'
+          type: string
+        qosId:
+          description: 'QoS identifer, 5QI'
+          type: string
+        cellId:
+          description: 'Network resource identifier for a cell'
+          type: string
+
+    #
+    # Simple data types
+    #
+    PolicyId:
+      description: 'Policy identifier assigned by the A1-P Consumer when a policy is created'
+      type: string
+
+    PolicyTypeId:
+      description: 'Policy type identifier assigned by the A1-P Provider'
+      pattern: "^(STD|EXT)_[a-zA-Z]+_(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$"
+      type: string
+
+    NotificationDestination:
+      description: 'A complete URI defined according to IETF RFC 3986 where to send notifications'
+      type: string
+      nullable: true
+
+    #
+    # Enumerations
+    #
+    EnforcementStatusType:
+      description: 'Indicating if a policy is being enforced or not'
+      type: string
+      enum:
+       - "ENFORCED"
+       - "NOT_ENFORCED"
+       - "UNDEFINED"
+
+    EnforcementReasonType:
+      description: 'Indicating the reason why a policy is not being enforced'
+      anyOf:
+      - type: string
+        enum:
+        - "100"
+        - "200"
+        - "300"
+        - "800"
+      - type: string
+
+    PolicyErrorType:
+      description: 'Represents information that can be provided in addition to the HTTP response error code. Corresponds to the "cause" attribute defined in 3GPP specification 29.501.'
+      anyOf:
+      - type: string
+        enum:
+        - "CONF_POLICY_ID"
+        - "BAD_REQ_MISSING_PARAM"
+      - type: string
+
+  responses:
+    400-BadRequest:
+      description: 'Object in payload not properly formulated or not related to the method'
+      content:
+        application/problem+json:
+          schema:
+            "$ref": "#/components/schemas/ProblemDetails"
+
+    404-NotFound:
+      description: 'No resource found at the URI'
+      content:
+        application/problem+json:
+          schema:
+            "$ref": "#/components/schemas/ProblemDetails"
+
+    405-MethodNotAllowed:
+      description: 'Method not allowed for the URI'
+      content:
+        application/problem+json:
+          schema:
+            "$ref": "#/components/schemas/ProblemDetails"
diff --git a/near-rt-ric-simulator/ric-plt/a1/a1.py b/near-rt-ric-simulator/ric-plt/a1/a1.py
new file mode 100644
index 0000000..1b1225b
--- /dev/null
+++ b/near-rt-ric-simulator/ric-plt/a1/a1.py
@@ -0,0 +1,177 @@
+#!/u:sr/bin/env python3
+import copy
+import datetime
+import json
+import logging
+import requests
+
+from connexion import NoContent
+from flask import Flask, escape, request
+from jsonschema import validate
+from random import random, choice
+from var_declaration import policy_instances, policy_types, policy_status, notification_destination, notificationDestination
+
+def get_all_policies():
+  all_p = copy.deepcopy(policy_instances)
+  all_policies = []
+  for i in all_p.keys():
+    all_p[i]["enforceStatus"] = policy_status[i]["enforceStatus"]
+    all_policies.insert(len(all_policies)-1, all_p[i])
+  return(all_policies, 200)
+
+def put_policy(policyId):
+  data = request.data.decode("utf-8")
+  data = data.replace("'", "\"")
+  data = json.loads(data)
+  ps = {}
+
+  if data["policyTypeId"] not in list(policy_types.keys()):
+    return(set_error(None, "The policy type provided does not exist.", 404, "The policy type " + data["policyTypeId"] + " is not defined as a policy type.", None, "policyTypeId", None))
+
+  pt = data["policyTypeId"]
+  schema = policy_types[pt]
+  try:
+    validate(instance=data["policyClause"], schema=schema)
+  except:
+    return(set_error(None, "The json does not validate against the schema.", 400, None, None, None, None))
+
+  if data["policyId"] in list(policy_instances.keys()):
+    if data["policyClause"]["scope"] != policy_instances[data["policyId"]]["policyClause"]["scope"]:
+      return(set_error(None, "The policy already exists with a different scope.", 404, "The policy put involves a modification of the existing scope, which is not allowed.", None, "scope", None))
+
+  if data["policyId"] != policyId:
+    return(set_error(None, "Wrong policy identity.", 400, "The policy instance's identity does not match with the one specified in the address.", None, "policyId", "The policy identity " + data["policyId"] + " is different from the address: " + policyId))
+
+  for i in list(policy_instances.keys()):
+    if data["policyId"] != i and \
+       data["policyClause"] == policy_instances[i]["policyClause"] and \
+       data["policyTypeId"] == policy_instances[i]["policyTypeId"] and \
+       data["notificationDestination"] == policy_instances[i]["notificationDestination"]:
+      return(set_error(None, "The policy already exists with a different id.", 404, "No action has been taken. The id of the existing policy instance is: " + i + ".", None, None, None))
+
+  if policyId in policy_instances.keys():
+    code = 201
+  else:
+    code = 200
+  policy_instances[policyId] = data
+  policy_status[policyId] = set_status("UNDEFINED")
+  notification_destination[policyId] = data["notificationDestination"]
+  return(policy_instances[policyId], code)
+
+def set_status(*args):
+  ps = {}
+  if len(args) == 0:
+    rand_status = randomise_status()
+    ps["policyId"] = policyId
+    ps["enforceStatus"] = rand_status
+    if rand_status == "NOT_ENFORCED":
+      rand_reason = randomise_reason()
+      ps["enforceReason"] = rand_reason
+  if args[0] in ["UNDEFINED", "ENFORCED", "NOT_ENFORCED"]:
+    ps["enforceStatus"] = args[0]
+  else:
+    return(set_error(None, "Wrong enforceStatus.", 400, None, None, "enforceStatus", "enforceStatus should be one of \"UNDEFINED\", \"ENFORCED\" or \"NOT_ENFORCED\""))
+  if args[0] == "NOT_ENFORCED":
+    if args[1] in ["100", "200", "300", "800"]:
+      ps["enforceReason"] = args[1]
+    else:
+      return(set_error(None, "Wrong enforceReason.", 400, None, None, "enforceReason", "enforceReason should be one of \"100\", \"200\", \"300\" or \"800\""))
+  return ps
+
+def get_policy(policyId):
+  if policyId in policy_instances.keys():
+    res = policy_instances[policyId]
+    res["enforceStatus"] = policy_status[policyId]["enforceStatus"]
+    return(res, 200)
+  else:
+    return(set_error(None, "The requested policy does not exist.", 404, None, None, "policyId", None))
+
+def delete_policy(policyId):
+  if policyId in policy_instances.keys():
+    policy_instances.pop(policyId)
+    policy_status.pop(policyId)
+    return(None, 204)
+  else:
+    return(set_error(None, "The policy identity does not exist.", 404, "No policy instance has been deleted.", None, "policyId", None))
+
+def get_all_policy_identities():
+  return(list(policy_instances.keys()), 200)
+
+def randomise_status():
+  x = random()
+  if x > 0.5001:
+    res = "ENFORCED"
+  elif x < 0.4999:
+    res = "NOT_ENFORCED"
+  else:
+    res = "UNDEFINED"
+  return res
+
+def randomise_reason():
+  options = ["100", "200", "300", "800"]
+  return choice(options)
+
+def get_all_policy_status():
+  all_s = copy.deepcopy(policy_status)
+  all_status = []
+  for i in all_s.keys():
+    all_s[i]["policyId"] = i
+    all_status.insert(len(all_status)-1, all_s[i])
+  return(all_status, 200)
+
+def get_policy_status(policyId):
+  return(policy_status[policyId], 200)
+
+def get_all_policytypes():
+  all_policytypes = []
+  for i in policy_types.keys():
+    all_policytypes.insert(len(all_policytypes)-1, policy_types[i])
+  return(all_policytypes, 200)
+
+def get_all_policytypes_identities():
+  return(list(policy_types.keys()), 200)
+
+def get_policytypes(policyTypeId):
+  if policyTypeId in policy_types.keys():
+    return(policy_types[policyTypeId], 200)
+  else:
+    return(set_error(None, "The requested policy type does not exist.", 404, None, None, "policyTypeId", None))
+
+def put_policytypes_subscription():
+  global notificationDestination
+  data = request.data.decode("utf-8")
+  data = data.replace("'", "\"")
+  data = json.loads(data)
+  if not notificationDestination:
+    notificationDestination["notificationDestionation"] = data
+    return(None, 201)
+  else:
+    notificationDestination["notificationDestionation"] = data
+    return(None, 200)
+
+def get_policytypes_subscription():
+  if not notificationDestination:
+    return(set_error(None, "The notification destination has not been defined.", 404, None, None, "notificationDestination", None))
+  else:
+    return(notificationDestination["notificationDestionation"], 200)
+
+def set_error(type_of, title, status, detail, instance, param, reason):
+  error = {}
+  params = {}
+  if type_of is not None:
+    error["type"] = type_of
+  if title is not None:
+    error["title"] = title
+  if status is not None:
+    error["status"] = status
+  if detail is not None:
+    error["detail"] = detail
+  if instance is not None:
+    error["instance"] = instance
+  if param is not None:
+    params["param"] = param
+  if reason is not None:
+    params["reason"] = reason
+  if params:
+    error["invalidParams"] = params
+  return(error, error["status"])
diff --git a/near-rt-ric-simulator/ric-plt/a1/commands.sh b/near-rt-ric-simulator/ric-plt/a1/commands.sh
new file mode 100755
index 0000000..f2f8bb5
--- /dev/null
+++ b/near-rt-ric-simulator/ric-plt/a1/commands.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+# Different commands for the simulator.
+# By running this, nothing should return an error.
+
+# Make a test
+curl -v "http://localhost:8085/"
+
+# PUT a policy type STD_QoSNudging_0.1.0
+curl -X PUT -v "http://localhost:8085/policytypes/STD_QoSNudging_0.1.0" -H "accept: application/json" -H "Content-Type: application/json" --data-binary @policy_type_STD_QoSNudging_0.1.0.json.json
+
+# GET policy types
+curl -v "http://localhost:8085/A1-P/v1/policytypes"
+
+# GET policy type identities
+curl -v "http://localhost:8085/A1-P/v1/policytypes/identities"
+
+# GET policy type STD_QoSNudging_0.1.0
+curl -v "http://localhost:8085/A1-P/v1/policytypes/STD_QoSNudging_0.1.0"
+
+# PUT a policy instance pi1
+curl -X PUT -v "http://localhost:8085/A1-P/v1/policies/pi1" -H "accept: application/json" -H "Content-Type: application/json" --data-binary @policy_instance_1_STD_QoSNudging_0.1.0.json
+
+# PUT a policy instance pi2
+curl -X PUT -v "http://localhost:8085/A1-P/v1/policies/pi2" -H "accept: application/json" -H "Content-Type: application/json" --data-binary @policy_instance_2_STD_QoSNudging_0.1.0.json
+
+# SET status for pi1 and pi2
+curl -X PUT "http://localhost:8085/pi1/NOT_ENFORCED/300"
+curl -X PUT "http://localhost:8085/pi2/ENFORCED"
+
+# GET policy status
+curl -v "http://localhost:8085/A1-P/v1/policies/status"
+
+# GET policies
+curl -v "http://localhost:8085/A1-P/v1/policies"
+
+# GET policy identities
+curl -v "http://localhost:8085/A1-P/v1/policies/identities"
+
+# DELETE policy instance pi2
+curl -X DELETE -v "http://localhost:8085/A1-P/v1/policies/pi2"
+
+# PUT a different policy instance pi1 (i.e. update it)
+curl -X PUT -v "http://localhost:8085/A1-P/v1/policies/pi1" -H "accept: application/json" -H "Content-Type: application/json" --data-binary @policy_instance_1_bis_STD_QoSNudging_0.1.0.json
+
+# GET policy instance pi1
+curl -v "http://localhost:8085/A1-P/v1/policies/pi1"
+
+# GET policy status for pi1
+curl -v "http://localhost:8085/A1-P/v1/policies/pi1/status"
+
+# PUT policy type subscription
+curl -X PUT -v "http://localhost:8085/A1-P/v1/policytypes/subscription" -H "accept: application/json" -H "Content-Type: application/json" -d  "{\"notificationDestination\": \"http://localhost:8085/subscription/address\"}"
+
+# GET policy type subscription
+curl -v "http://localhost:8085/A1-P/v1/policytypes/subscription"
diff --git a/near-rt-ric-simulator/ric-plt/a1/main.py b/near-rt-ric-simulator/ric-plt/a1/main.py
new file mode 100644
index 0000000..e1f2d56
--- /dev/null
+++ b/near-rt-ric-simulator/ric-plt/a1/main.py
@@ -0,0 +1,89 @@
+import connexion
+import fileinput
+import json
+import sys
+
+from flask import Flask, escape, request, make_response
+from var_declaration import policy_instances, policy_types, policy_status
+
+app = connexion.App(__name__, specification_dir='.')
+
+@app.route('/policytypes/<string:policyTypeId>', methods=['PUT','DELETE'])
+def policy_type(policyTypeId):
+  if request.method == 'PUT':
+    data = request.data.decode("utf-8")
+    data = data.replace("'", "\"")
+    data = json.loads(data)
+    policy_types[policyTypeId] = data
+    return ('The policy type was either created or updated for policy type id: ' + policyTypeId)
+  elif request.method == 'DELETE':
+    if policyTypeId in policy_types.keys():
+      policy_types.pop(policyTypeId)
+      return make_response("policy type successfully deleted for policy type id: " + policyTypeId, 200)
+    else:
+      return make_response("No policy type defined for the specified id", 404)
+
+@app.route('/', methods=['GET'])
+def test():
+  if "STD_QoSNud_0.1.0" in policy_types.keys():
+    return("Something fishy!", 200)
+  else:
+    return(str(list(policy_types.keys())), 200)
+
+@app.route('/deleteinstances', methods=['DELETE'])
+def delete_instances():
+  global policy_instances
+  global policy_status
+  policy_instances.clear()
+  policy_status.clear()
+  return("All policy instances deleted", 200)
+
+@app.route('/deletetypes', methods=['DELETE'])
+def delete_types():
+  global policy_types
+  policy_types.clear()
+  return("All policy types deleted", 200)
+
+@app.route('/<string:policyId>/<string:enforceStatus>', methods=['PUT'])
+def set_status(policyId, enforceStatus):
+  if policyId in policy_instances.keys():
+    if enforceStatus in ["UNDEFINED", "ENFORCED", "NOT_ENFORCED"]:
+      policy_status.pop(policyId)
+      ps = {}
+      ps["policyId"] = policyId
+      ps["enforceStatus"] = enforceStatus
+      policy_status[policyId] = ps
+      return("Status updated for policy: " + policyId, 200)
+    else:
+      return("enforceStatus should be one of \"UNDEFINED\", \"ENFORCED\" or \"NOT_ENFORCED\"", 400)
+  else:
+    return("The policy id does not correspond to any existing policy instance", 400)
+
+@app.route('/<string:policyId>/<string:enforceStatus>/<string:enforceReason>', methods=['PUT'])
+def set_status_with_reason(policyId, enforceStatus, enforceReason):
+  if policyId in policy_instances.keys():
+    if enforceStatus == "NOT_ENFORCED":
+      if enforceReason in ["100", "200", "300", "800"]:
+        policy_status.pop(policyId)
+        ps = {}
+        ps["policyId"] = policyId
+        ps["enforceStatus"] = enforceStatus
+        ps["enforceReason"] = enforceReason
+        policy_status[policyId] = ps
+        return("Status updated for policy: " + policyId, 200)
+      else:
+        return("enforceReason should be one of \"100\", \"200\", \"300\" or \"800\"", 400)
+    else:
+      return("A status provided together with an enforcement reason should be \"NOT_ENFORCED\"", 400)
+  else:
+    return("The policy id does not correspond to any existing policy instance", 404)
+
+
+port_number = 8085
+if len(sys.argv) >= 2:
+  if isinstance(sys.argv[1], int):
+    port_number = sys.argv[1]
+
+app.add_api('a1-openapi.yaml')
+app.run(port=port_number)
+
diff --git a/near-rt-ric-simulator/ric-plt/a1/policy_instance_1_STD_QoSNudging_0.1.0.json b/near-rt-ric-simulator/ric-plt/a1/policy_instance_1_STD_QoSNudging_0.1.0.json
new file mode 100644
index 0000000..8d1cdd6
--- /dev/null
+++ b/near-rt-ric-simulator/ric-plt/a1/policy_instance_1_STD_QoSNudging_0.1.0.json
@@ -0,0 +1,18 @@
+{
+  "policyId": "pi1",
+  "policyTypeId": "STD_QoSNudging_0.1.0",
+  "policyClause": {
+    "scope": {
+      "ueId": "ue1",
+      "groupId": "group1",
+      "sliceId": "slice1",
+      "qosId": "qos1",
+      "cellId": "cell1"
+    },
+    "statement": {
+      "priorityLevel": 5
+    }
+  },
+  "notificationDestination": "http://localhost:8085/policynotifications"
+}
+
diff --git a/near-rt-ric-simulator/ric-plt/a1/policy_instance_1_bis_STD_QoSNudging_0.1.0.json b/near-rt-ric-simulator/ric-plt/a1/policy_instance_1_bis_STD_QoSNudging_0.1.0.json
new file mode 100644
index 0000000..f43ca1a
--- /dev/null
+++ b/near-rt-ric-simulator/ric-plt/a1/policy_instance_1_bis_STD_QoSNudging_0.1.0.json
@@ -0,0 +1,16 @@
+{
+  "policyId": "pi1",
+  "policyTypeId": "STD_QoSNudging_0.1.0",
+  "policyClause": {
+    "scope": {
+      "ueId": "ue1",
+      "groupId": "group1",
+      "sliceId": "slice1",
+      "qosId": "qos1",
+      "cellId": "cell1"},
+    "statement": {
+      "priorityLevel": 4
+    }
+  },
+  "notificationDestination": "http://localhost:8085/policynotifications"
+}
diff --git a/near-rt-ric-simulator/ric-plt/a1/policy_instance_2_STD_QoSNudging_0.1.0.json b/near-rt-ric-simulator/ric-plt/a1/policy_instance_2_STD_QoSNudging_0.1.0.json
new file mode 100644
index 0000000..6890d05
--- /dev/null
+++ b/near-rt-ric-simulator/ric-plt/a1/policy_instance_2_STD_QoSNudging_0.1.0.json
@@ -0,0 +1,17 @@
+{
+  "policyId": "pi2",
+  "policyTypeId": "STD_QoSNudging_0.1.0",
+  "policyClause": {
+    "scope": {
+      "ueId": "ue2",
+      "groupId": "group2",
+      "sliceId": "slice2",
+      "qosId": "qos2",
+      "cellId": "cell2"
+    },
+    "statement": {
+      "priorityLevel": 5
+    }
+  },
+  "notificationDestination": "http://localhost:8085/policynotifications"
+}
diff --git a/near-rt-ric-simulator/ric-plt/a1/policy_type_STD_QoSNudging_0.1.0.json b/near-rt-ric-simulator/ric-plt/a1/policy_type_STD_QoSNudging_0.1.0.json
new file mode 100644
index 0000000..8be17bb
--- /dev/null
+++ b/near-rt-ric-simulator/ric-plt/a1/policy_type_STD_QoSNudging_0.1.0.json
@@ -0,0 +1,25 @@
+{
+  "$schema": "http://json-schema.org/draft-07/schema#",
+  "title": "STD_QoSNudging_0.1.0",
+  "description": "QoS policy type with ueId and qosId scope, version 0.1.0",
+  "type": "object",
+  "properties": {
+    "scope": {
+      "type": "object",
+      "properties": {
+        "ueId": {"type": "string"},
+        "qosId": {"type": "string"}
+      },
+      "additionalProperties": false,
+      "required": ["ueId", "qosId"]
+    },
+    "statement": {
+      "type": "object",
+      "properties": {
+        "priorityLevel": {"type": "number"}
+      },
+      "additionalProperties": false,
+      "required": ["priorityLevel"]
+    }
+  }
+}
diff --git a/near-rt-ric-simulator/ric-plt/a1/run_me.sh b/near-rt-ric-simulator/ric-plt/a1/run_me.sh
new file mode 100755
index 0000000..9052ecf
--- /dev/null
+++ b/near-rt-ric-simulator/ric-plt/a1/run_me.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+# One argument can be used along with the script call: it is the port on which one wish to run the simulator.
+
+if [ $# -eq 0 ]
+then
+  python3 ./main.py
+else
+  python3 ./main.py $1
+fi
diff --git a/near-rt-ric-simulator/ric-plt/a1/var_declaration.py b/near-rt-ric-simulator/ric-plt/a1/var_declaration.py
new file mode 100644
index 0000000..c0dbac4
--- /dev/null
+++ b/near-rt-ric-simulator/ric-plt/a1/var_declaration.py
@@ -0,0 +1,7 @@
+#!/u:sr/bin/env python3
+
+policy_instances = {}
+policy_types = {}
+policy_status = {}
+notification_destination = {}
+notificationDestination = {}