"fmt"
"strconv"
"strings"
+ "time"
"gerrit.o-ran-sc.org/r/ric-plt/a1/pkg/a1"
"gerrit.o-ran-sc.org/r/ric-plt/a1/pkg/models"
+ "gerrit.o-ran-sc.org/r/ric-plt/a1/pkg/rmr"
"gerrit.o-ran-sc.org/r/ric-plt/sdlgo"
-
"github.com/santhosh-tekuri/jsonschema/v5"
"gopkg.in/yaml.v2"
)
const (
- a1PolicyPrefix = "a1.policy_type."
- a1MediatorNs = "A1m_ns"
- a1InstancePrefix = "a1.policy_instance."
+ a1PolicyPrefix = "a1.policy_type."
+ a1MediatorNs = "A1m_ns"
+ a1InstancePrefix = "a1.policy_instance."
a1InstanceMetadataPrefix = "a1.policy_inst_metadata."
- a1HandlerPrefix = "a1.policy_handler."
+ a1HandlerPrefix = "a1.policy_handler."
+ a1PolicyRequest = 20010
+ a1EIDataDelivery = 20017
)
var typeAlreadyError = errors.New("Policy Type already exists")
var invalidJsonSchema = errors.New("Invalid Json ")
var policyInstanceNotFoundError = errors.New("Policy Instance Not Found")
var policyTypeNotFoundError = errors.New("Policy Type Not Found")
+var policyTypeCanNotBeDeletedError = errors.New("tried to delete a type that isn't empty")
+var policyInstanceCanNotBeDeletedError = errors.New("tried to delete a Instance that isn't empty")
+
+func (rh *Resthook) CanPolicyInstanceBeDeleted(err error) bool {
+ return err == policyInstanceCanNotBeDeletedError
+}
+
+func (rh *Resthook) CanPolicyTypeBeDeleted(err error) bool {
+ return err == policyTypeCanNotBeDeletedError
+}
func (rh *Resthook) IsPolicyTypePresent(err error) bool {
return err == policyTypeNotFoundError
return err == invalidJsonSchema
}
func NewResthook() *Resthook {
- return createResthook(sdlgo.NewSyncStorage())
+ return createResthook(sdlgo.NewSyncStorage(), rmr.NewRMRSender())
}
-func createResthook(sdlInst iSdl) *Resthook {
+func createResthook(sdlInst iSdl, rmrSenderInst rmr.IRmrSender) *Resthook {
return &Resthook{
- db: sdlInst,
+ db: sdlInst,
+ iRmrSenderInst: rmrSenderInst,
}
}
valmap, err := rh.db.Get(a1MediatorNs, keys[:])
- a1.Logger.Debug("policytype map : ", valmap)
+ a1.Logger.Debug("policytype map : %+v", valmap)
if len(valmap) == 0 {
a1.Logger.Error("policy type Not Present for policyid : %v", policyTypeId)
return nil
}
-
-
func toStringKeys(val interface{}) (interface{}, error) {
var err error
switch val := val.(type) {
return true
}
-func (rh *Resthook) StorePolicyInstance(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID, httpBody interface{}) (string, error) {
+func (rh *Resthook) storePolicyInstance(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID, httpBody interface{}) (string, error) {
var keys [1]string
operation := "CREATE"
typekey := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
a1.Logger.Debug("schema to validate %+v", string(schemaStr))
a1.Logger.Debug("httpbody to validate %+v", httpBody)
schemaString := fmt.Sprint(string(schemaStr))
- httpBodyString := fmt.Sprint((httpBody))
+ httpBodyMarshal, err := json.Marshal(httpBody)
+ httpBodyString := string((httpBodyMarshal))
+ a1.Logger.Debug("schema to validate sprint %+v", (schemaString))
+ a1.Logger.Debug("httpbody to validate sprint %+v", httpBodyString)
isvalid := validate(httpBodyString, schemaString)
if isvalid {
var operation string
- operation, err = rh.StorePolicyInstance(policyTypeId, policyInstanceID, httpBody)
+ operation, err = rh.storePolicyInstance(policyTypeId, policyInstanceID, httpBody)
if err != nil {
a1.Logger.Error("error :%+v", err)
return err
}
a1.Logger.Debug("policy instance :%+v", operation)
- iscreated,errmetadata := rh.StorePolicyInstanceMetadata(policyTypeId, policyInstanceID)
+ iscreated, errmetadata := rh.storePolicyInstanceMetadata(policyTypeId, policyInstanceID)
if errmetadata != nil {
a1.Logger.Error("error :%+v", errmetadata)
return errmetadata
}
if iscreated {
- a1.Logger.Debug("policy instance metadata created")
+ a1.Logger.Debug("policy instance metadata created")
+ }
+
+ message := rmr.Message{}
+ rmrMessage, err = message.PolicyMessage(strconv.FormatInt((int64(policyTypeId)), 10), string(policyInstanceID), httpBodyString, operation)
+ if err != nil {
+ a1.Logger.Error("error : %v", err)
+ return err
}
+ isSent := rh.iRmrSenderInst.RmrSendToXapp(rmrMessage, a1PolicyRequest)
+ if isSent {
+ a1.Logger.Debug("rmrSendToXapp : message sent")
+ } else {
+ a1.Logger.Debug("rmrSendToXapp : message not sent")
+ }
+
} else {
a1.Logger.Error("%+v", invalidJsonSchema)
return invalidJsonSchema
return valStr, nil
}
-func (rh *Resthook) GetAllPolicyInstance(policyTypeId models.PolicyTypeID) []models.PolicyInstanceID ,error {
+func (rh *Resthook) GetAllPolicyInstance(policyTypeId models.PolicyTypeID) ([]models.PolicyInstanceID, error) {
a1.Logger.Debug("GetAllPolicyInstance")
- var policyTypeInstances = []models.PolicyInstanceID{}
+ var policyTypeInstances = []models.PolicyInstanceID{}
keys, err := rh.db.GetAll("A1m_ns")
if err != nil {
a1.Logger.Error("error in retrieving policy. err: %v", err)
- return policyTypeInstances ,err
+ return policyTypeInstances, err
}
a1.Logger.Debug("keys : %+v", keys)
typekey := a1InstancePrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "."
}
}
- if len(policyTypeInstances)==0{
+ if len(policyTypeInstances) == 0 {
a1.Logger.Debug("policy instance Not Present ")
}
a1.Logger.Debug("return : %+v", policyTypeInstances)
- return policyTypeInstances ,nil
+ return policyTypeInstances, nil
+}
+
+func (rh *Resthook) DeletePolicyType(policyTypeId models.PolicyTypeID) error {
+ a1.Logger.Debug("DeletePolicyType")
+
+ policyinstances, err := rh.GetAllPolicyInstance(policyTypeId)
+ if err != nil {
+ a1.Logger.Error("error in retrieving policy. err: %v", err)
+ return err
+ }
+
+ var keys [1]string
+ key := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
+ keys[0] = key
+ if len(policyinstances) == 0 {
+ err := rh.db.Remove(a1MediatorNs, keys[:])
+ if err != nil {
+ a1.Logger.Error("error in deleting policy type err: %v", err)
+ return err
+ }
+ } else {
+ a1.Logger.Error("tried to delete a type that isn't empty")
+ return policyTypeCanNotBeDeletedError
+ }
+ return nil
+}
+
+func (rh *Resthook) typeValidity(policyTypeId models.PolicyTypeID) error {
+ var keys [1]string
+
+ typekey := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
+ keys[0] = typekey
+
+ a1.Logger.Debug("key1 : %+v", typekey)
+ valmap, err := rh.db.Get(a1MediatorNs, keys[:])
+ if err != nil {
+ a1.Logger.Error("error in retrieving policytype err: %v", err)
+ return err
+ }
+ if len(valmap) == 0 {
+ a1.Logger.Error("policy type Not Present for policyid : %v", policyTypeId)
+ return policyTypeNotFoundError
+ }
+}
+
+func (rh *Resthook) instanceValidity(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) error {
+ err := rh.typeValidity(policyTypeId)
+ if err != nil {
+ return err
+ }
+ policyTypeInstances, err := rh.GetPolicyInstance(policyTypeId, policyInstanceID)
+ if err != nil {
+ a1.Logger.Error("policy instance error : %v", err)
+ return err
+ }
+ if len(policyTypeInstances.(string)) == 0 {
+ a1.Logger.Debug("policy instance Not Present ")
+ return policyInstanceNotFoundError
+ }
+}
+
+func (rh *Resthook) getMetaData(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) (map[string]interface{}, error) {
+ instanceMetadataKey := a1InstanceMetadataPrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
+ a1.Logger.Debug("instanceMetadata key : %+v", instanceMetadataKey)
+ var keys [1]string
+ keys[0] = instanceMetadataKey
+ instanceMetadataMap, err := rh.db.Get(a1MediatorNs, keys[:])
+ if err != nil {
+ a1.Logger.Error("policy instance error : %v", err)
+ }
+ a1.Logger.Debug("instanceMetadata map : %+v", instanceMetadataMap)
+ if instanceMetadataMap[instanceMetadataKey] == nil {
+ a1.Logger.Error("policy instance Not Present for policyinstaneid : %v", policyInstanceID)
+ return map[string]interface{}{}, policyInstanceNotFoundError
+ }
+ return instanceMetadataMap, nil
+}
+
+func (rh *Resthook) GetPolicyInstanceStatus(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) (*a1_mediator.A1ControllerGetPolicyInstanceStatusOKBody, error) {
+ err := rh.instanceValidity(policyTypeId, policyInstanceID)
+ if err != nil && err == policyInstanceNotFoundError || err == policyTypeNotFoundError {
+ policyInstanceStatus.InstanceStatus = "NOT IN EFFECT"
+ return &policyInstanceStatus, err
+ }
+ policyInstanceStatus := a1_mediator.A1ControllerGetPolicyInstanceStatusOKBody{}
+ metadata, err := rh.getMetaData(policyTypeId, policyInstanceID)
+ a1.Logger.Debug(" metadata %v", metadata)
+ if err != nil {
+ a1.Logger.Error("policy instance error : %v", err)
+ policyInstanceStatus.InstanceStatus = "NOT IN EFFECT"
+ return &policyInstanceStatus, err
+ }
+ jsonbody, err := json.Marshal(metadata)
+ if err != nil {
+ a1.Logger.Error("marshal error : %v", err)
+ return &policyInstanceStatus, err
+ }
+
+ if err := json.Unmarshal(jsonbody, &policyInstanceStatus); err != nil {
+ a1.Logger.Error("unmarshal error : %v", err)
+ //this error maps to 503 error but can be mapped to 500: internal error
+ return &policyInstanceStatus, err
+ }
+ if policyInstanceStatus.HasBeenDeleted == false {
+ policyInstanceStatus.InstanceStatus = "IN EFFECT"
+ } else {
+ policyInstanceStatus.InstanceStatus = "NOT IN EFFECT"
+ }
+ return &policyInstanceStatus, nil
+}
+
+func (rh *Resthook) storeDeletedPolicyInstanceMetadata(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID, creation_timestamp string) error {
+ deleted_timestamp := time.Now()
+
+ instanceMetadataKey := a1InstanceMetadataPrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
+
+ a1.Logger.Debug("instanceMetadata Key : %+v", instanceMetadataKey)
+
+ var metadatajson interface{}
+ metadatajson = map[string]string{"created_at": creation_timestamp, "has_been_deleted": "True", "deleted_at": deleted_timestamp.Format("2006-01-02 15:04:05")}
+ a1.Logger.Debug("metadatajson to create : %+v", metadatajson)
+ deletedmetadata, err := json.Marshal(metadatajson)
+
+ a1.Logger.Debug("policyinstanceMetaData to create : %+v", string(deletedmetadata))
+
+ err = rh.db.Set(a1MediatorNs, instanceMetadataKey, string(deletedmetadata))
+ a1.Logger.Debug("deletemetadatacreated")
+ if err != nil {
+ a1.Logger.Error("error :%+v", err)
+ return err
+ }
+
+ a1.Logger.Error("Policy Instance Meta Data deleted at :%+v", creation_timestamp)
+
+ return nil
+}
+
+func (rh *Resthook) deleteInstancedata(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) error {
+ var keys [1]string
+ instancekey := a1InstancePrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
+ keys[0] = instancekey
+ err := rh.db.Remove(a1MediatorNs, keys[:])
+ if err != nil {
+ a1.Logger.Error("error in deleting policy type err: %v", err)
+ return err
+ }
+ return nil
+}
+
+func (rh *Resthook) deleteMetadata(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) error {
+ var keys [1]string
+ instanceMetadataKey := a1InstanceMetadataPrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
+
+ a1.Logger.Debug("instanceMetadata Key : %+v", instanceMetadataKey)
+ keys[0] = instanceMetadataKey
+ err := rh.db.Remove(a1MediatorNs, keys[:])
+ if err != nil {
+ a1.Logger.Error("error in deleting policy metadata err: %v", err)
+ return err
+ }
+ return nil
+}
+
+func (rh *Resthook) DeletePolicyInstance(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) error {
+ err := rh.instanceValidity(policyTypeId, policyInstanceID)
+ if err != nil {
+ a1.Logger.Error("policy instance error : %v", err)
+ if err == policyInstanceNotFoundError || err == policyTypeNotFoundError {
+ return err
+ }
+ }
+
+ createdmetadata, err := rh.getMetaData(policyTypeId, policyInstanceID)
+ if err != nil {
+ a1.Logger.Error("error : %v", err)
+ return err
+ }
+ a1.Logger.Debug(" created metadata %v", createdmetadata)
+ instanceMetadataKey := a1InstanceMetadataPrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
+ creation_metadata := createdmetadata[instanceMetadataKey]
+ var metadata map[string]interface{}
+ if err = json.Unmarshal([]byte(creation_metadata.(string)), &metadata); err != nil {
+ a1.Logger.Error("unmarshal error : %v", err)
+ return err
+ }
+
+ a1.Logger.Debug(" created metadata created_at %v", metadata["created_at"])
+ creation_timestamp := metadata["created_at"]
+
+ rh.deleteMetadata(policyTypeId, policyInstanceID)
+
+ rh.deleteInstancedata(policyTypeId, policyInstanceID)
+
+ rh.storeDeletedPolicyInstanceMetadata(policyTypeId, policyInstanceID, creation_timestamp.(string))
+
+ message := rmr.Message{}
+ rmrMessage, err = message.PolicyMessage(strconv.FormatInt((int64(policyTypeId)), 10), string(policyInstanceID), "", "DELETE")
+ if err != nil {
+ a1.Logger.Error("error : %v", err)
+ return err
+ }
+ isSent := rh.iRmrSenderInst.RmrSendToXapp(rmrMessage, a1PolicyRequest)
+ if isSent {
+ a1.Logger.Debug("rmrSendToXapp : message sent")
+ } else {
+ //TODO:if message not sent need to return error or just log it or retry sending
+ a1.Logger.Error("rmrSendToXapp : message not sent")
+ }
+
+ return nil
+}
+
+func (rh *Resthook) DataDelivery(httpBody interface{}) error {
+ a1.Logger.Debug("httpbody : %+v", httpBody)
+ mymap := httpBody.(map[string]interface{})
+ message := rmr.Message{}
+ rmrMessage, err := message.A1EIMessage(mymap["job"].(string), mymap["payload"].(string))
+ if err != nil {
+ a1.Logger.Error("error : %v", err)
+ return err
+ }
+ a1.Logger.Debug("rmrSendToXapp :rmrMessage %+v", rmrMessage)
+ isSent := rh.iRmrSenderInst.RmrSendToXapp(rmrMessage, a1EIDataDelivery)
+ if isSent {
+ a1.Logger.Debug("rmrSendToXapp : message sent")
+ } else {
+ a1.Logger.Error("rmrSendToXapp : message not sent")
+ }
+ return nil
}