2 ==================================================================================
3 Copyright (c) 2021 Samsung
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
9 http://www.apache.org/licenses/LICENSE-2.0
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
17 This source code is part of the near-RT RIC (RAN Intelligent Controller)
18 platform project (RICP).
19 ==================================================================================
31 "gerrit.o-ran-sc.org/r/ric-plt/a1/pkg/a1"
32 "gerrit.o-ran-sc.org/r/ric-plt/a1/pkg/models"
33 "gerrit.o-ran-sc.org/r/ric-plt/a1/pkg/rmr"
34 "gerrit.o-ran-sc.org/r/ric-plt/sdlgo"
35 "github.com/santhosh-tekuri/jsonschema/v5"
40 a1PolicyPrefix = "a1.policy_type."
41 a1MediatorNs = "A1m_ns"
42 a1InstancePrefix = "a1.policy_instance."
43 a1InstanceMetadataPrefix = "a1.policy_inst_metadata."
44 a1HandlerPrefix = "a1.policy_handler."
47 var typeAlreadyError = errors.New("Policy Type already exists")
48 var InstanceAlreadyError = errors.New("Policy Instance already exists")
49 var typeMismatchError = errors.New("Policytype Mismatch")
50 var invalidJsonSchema = errors.New("Invalid Json ")
51 var policyInstanceNotFoundError = errors.New("Policy Instance Not Found")
52 var policyTypeNotFoundError = errors.New("Policy Type Not Found")
53 var policyTypeCanNotBeDeletedError = errors.New("tried to delete a type that isn't empty")
54 var policyInstanceCanNotBeDeletedError = errors.New("tried to delete a Instance that isn't empty")
56 func (rh *Resthook) CanPolicyInstanceBeDeleted(err error) bool {
57 return err == policyInstanceCanNotBeDeletedError
60 func (rh *Resthook) CanPolicyTypeBeDeleted(err error) bool {
61 return err == policyTypeCanNotBeDeletedError
64 func (rh *Resthook) IsPolicyTypePresent(err error) bool {
65 return err == policyTypeNotFoundError
68 func (rh *Resthook) IsPolicyInstanceNotFound(err error) bool {
69 return err == policyInstanceNotFoundError
72 func (rh *Resthook) IsTypeAlready(err error) bool {
73 return err == typeAlreadyError
75 func (rh *Resthook) IsInstanceAlready(err error) bool {
76 return err == InstanceAlreadyError
78 func (rh *Resthook) IsTypeMismatch(err error) bool {
79 return err == typeMismatchError
82 func (rh *Resthook) IsValidJson(err error) bool {
83 return err == invalidJsonSchema
85 func NewResthook() *Resthook {
86 return createResthook(sdlgo.NewSyncStorage(), rmr.NewRMRSender())
89 func createResthook(sdlInst iSdl, rmrSenderInst rmr.IRmrSender) *Resthook {
92 iRmrSenderInst: rmrSenderInst,
96 func (rh *Resthook) GetAllPolicyType() []models.PolicyTypeID {
98 var policyTypeIDs []models.PolicyTypeID
100 keys, err := rh.db.GetAll("A1m_ns")
103 a1.Logger.Error("error in retrieving policy. err: %v", err)
106 a1.Logger.Debug("keys : %+v", keys)
108 for _, key := range keys {
109 if strings.HasPrefix(strings.TrimLeft(key, " "), a1PolicyPrefix) {
110 pti := strings.Split(strings.Trim(key, " "), a1PolicyPrefix)[1]
111 ptii, _ := strconv.ParseInt(pti, 10, 64)
112 policyTypeIDs = append(policyTypeIDs, models.PolicyTypeID(ptii))
116 a1.Logger.Debug("return : %+v", policyTypeIDs)
120 func (rh *Resthook) GetPolicyType(policyTypeId models.PolicyTypeID) *models.PolicyTypeSchema {
121 a1.Logger.Debug("GetPolicyType1")
123 var policytypeschema *models.PolicyTypeSchema
126 key := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
129 a1.Logger.Debug("key : %+v", key)
131 valmap, err := rh.db.Get(a1MediatorNs, keys[:])
133 a1.Logger.Debug("policytype map : %+v", valmap)
135 if len(valmap) == 0 {
136 a1.Logger.Error("policy type Not Present for policyid : %v", policyTypeId)
137 return policytypeschema
141 a1.Logger.Error("error in retrieving policy type. err: %v", err)
145 if valmap[key] == nil {
146 a1.Logger.Error("policy type Not Present for policyid : %v", policyTypeId)
147 return policytypeschema
150 a1.Logger.Debug("keysmap : %+v", valmap[key])
152 var item models.PolicyTypeSchema
153 valStr := fmt.Sprint(valmap[key])
155 a1.Logger.Debug("Policy type for %+v : %+v", key, valStr)
156 valkey := "`" + valStr + "`"
157 valToUnmarshall, err := strconv.Unquote(valkey)
159 a1.Logger.Error("unquote error : %+v", err)
163 a1.Logger.Debug("Policy type for %+v : %+v", key, string(valToUnmarshall))
165 errunm := json.Unmarshal([]byte(valToUnmarshall), &item)
167 a1.Logger.Debug(" Unmarshalled json : %+v", (errunm))
168 a1.Logger.Debug("Policy type Name : %v", (item.Name))
173 func (rh *Resthook) CreatePolicyType(policyTypeId models.PolicyTypeID, httprequest models.PolicyTypeSchema) error {
174 a1.Logger.Debug("CreatePolicyType function")
175 if policyTypeId != models.PolicyTypeID(*httprequest.PolicyTypeID) {
177 a1.Logger.Debug("Policytype Mismatch")
178 return typeMismatchError
180 key := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
181 a1.Logger.Debug("key %+v ", key)
182 if data, err := httprequest.MarshalBinary(); err == nil {
183 a1.Logger.Debug("Marshaled String : %+v", string(data))
184 success, err1 := rh.db.SetIfNotExists(a1MediatorNs, key, string(data))
185 a1.Logger.Info("success:%+v", success)
187 a1.Logger.Error("error :%+v", err1)
191 a1.Logger.Debug("Policy type %+v already exist", policyTypeId)
192 return typeAlreadyError
198 func toStringKeys(val interface{}) (interface{}, error) {
200 switch val := val.(type) {
201 case map[interface{}]interface{}:
202 m := make(map[string]interface{})
203 for k, v := range val {
206 return nil, errors.New("found non-string key")
208 m[k], err = toStringKeys(v)
215 var l = make([]interface{}, len(val))
216 for i, v := range val {
217 l[i], err = toStringKeys(v)
228 func validate(httpBodyString string, schemaString string) bool {
230 err := yaml.Unmarshal([]byte(httpBodyString), &m)
232 a1.Logger.Error("Unmarshal error : %+v", err)
234 m, err = toStringKeys(m)
236 a1.Logger.Error("Conversion to string error : %+v", err)
239 compiler := jsonschema.NewCompiler()
240 if err := compiler.AddResource("schema.json", strings.NewReader(schemaString)); err != nil {
241 a1.Logger.Error("string reader error : %+v", err)
244 schema, err := compiler.Compile("schema.json")
246 a1.Logger.Error("schema json compile error : %+v", err)
249 if err := schema.Validate(m); err != nil {
250 a1.Logger.Error("schema validation error : %+v", err)
253 a1.Logger.Debug("validation successfull")
257 func (rh *Resthook) storePolicyInstance(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID, httpBody interface{}) (string, error) {
259 operation := "CREATE"
260 typekey := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
263 a1.Logger.Debug("key1 : %+v", typekey)
265 valmap, err := rh.db.Get(a1MediatorNs, keys[:])
267 a1.Logger.Error("policy type error : %+v", err)
269 a1.Logger.Debug("policytype map : %+v", valmap)
270 if valmap[typekey] == nil {
271 a1.Logger.Error("policy type Not Present for policyid : %v", policyTypeId)
272 return operation, policyTypeNotFoundError
274 // TODO : rmr creation_timestamp := time.Now() // will be needed for rmr to notify the creation of instance
276 instancekey := a1InstancePrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
278 instanceMap, err := rh.db.Get(a1MediatorNs, keys[:])
280 a1.Logger.Error("policy type error : %v", err)
282 a1.Logger.Debug("policyinstancetype map : %+v", instanceMap)
284 if instanceMap[instancekey] != nil {
286 a1.Logger.Debug("UPDATE")
287 data, _ := json.Marshal(httpBody)
288 a1.Logger.Debug("Marshaled String : %+v", string(data))
289 a1.Logger.Debug("key : %+v", instancekey)
290 success, err1 := rh.db.SetIf(a1MediatorNs, instancekey, instanceMap[instancekey], string(data))
292 a1.Logger.Error("error2 :%+v", err1)
293 return operation, err1
296 a1.Logger.Debug("Policy instance %+v already exist", policyInstanceID)
297 return operation, InstanceAlreadyError
300 data, _ := json.Marshal(httpBody)
301 a1.Logger.Debug("Marshaled String : %+v", string(data))
302 a1.Logger.Debug("key : %+v", instancekey)
304 var instance_map []interface{}
305 instance_map = append(instance_map, instancekey, string(data))
306 a1.Logger.Debug("policyinstancetype map : %+v", instance_map[1])
307 a1.Logger.Debug("policyinstancetype to create : %+v", instance_map)
309 err1 := rh.db.Set(a1MediatorNs, instancekey, string(data))
311 a1.Logger.Error("error1 :%+v", err1)
312 return operation, err1
315 a1.Logger.Debug("Policy Instance created ")
316 return operation, nil
319 func (rh *Resthook) storePolicyInstanceMetadata(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) (bool, error) {
321 creation_timestamp := time.Now()
322 instanceMetadataKey := a1InstanceMetadataPrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
324 a1.Logger.Debug("key : %+v", instanceMetadataKey)
326 var metadatajson []interface{}
327 metadatajson = append(metadatajson, map[string]string{"created_at": creation_timestamp.Format("2006-01-02 15:04:05"), "has_been_deleted": "False"})
328 metadata, _ := json.Marshal(metadatajson)
330 a1.Logger.Debug("policyinstanceMetaData to create : %+v", string(metadata))
332 err := rh.db.Set(a1MediatorNs, instanceMetadataKey, string(metadata))
335 a1.Logger.Error("error :%+v", err)
339 a1.Logger.Debug("Policy Instance Meta Data created at :%+v", creation_timestamp)
344 func (rh *Resthook) CreatePolicyInstance(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID, httpBody interface{}) error {
345 a1.Logger.Debug("CreatePolicyInstance function")
346 // validate the PUT against the schema
347 var policyTypeSchema *models.PolicyTypeSchema
348 policyTypeSchema = rh.GetPolicyType(policyTypeId)
349 schemaStr, err := json.Marshal(policyTypeSchema.CreateSchema)
351 a1.Logger.Error("Json Marshal error : %+v", err)
354 a1.Logger.Debug("schema to validate %+v", string(schemaStr))
355 a1.Logger.Debug("httpbody to validate %+v", httpBody)
356 schemaString := fmt.Sprint(string(schemaStr))
357 httpBodyMarshal, err := json.Marshal(httpBody)
358 httpBodyString := string((httpBodyMarshal))
359 a1.Logger.Debug("schema to validate sprint %+v", (schemaString))
360 a1.Logger.Debug("httpbody to validate sprint %+v", httpBodyString)
361 isvalid := validate(httpBodyString, schemaString)
364 operation, err = rh.storePolicyInstance(policyTypeId, policyInstanceID, httpBody)
366 a1.Logger.Error("error :%+v", err)
369 a1.Logger.Debug("policy instance :%+v", operation)
370 iscreated, errmetadata := rh.storePolicyInstanceMetadata(policyTypeId, policyInstanceID)
371 if errmetadata != nil {
372 a1.Logger.Error("error :%+v", errmetadata)
376 a1.Logger.Debug("policy instance metadata created")
379 message := rmr.Message{}
380 rmrMessage, err = message.PolicyMessage(strconv.FormatInt((int64(policyTypeId)), 10), string(policyInstanceID), httpBodyString, operation)
382 a1.Logger.Error("error : %v", err)
385 isSent := rh.iRmrSenderInst.RmrSendToXapp(rmrMessage)
387 a1.Logger.Debug("rmrSendToXapp : message sent")
389 a1.Logger.Debug("rmrSendToXapp : message not sent")
393 a1.Logger.Error("%+v", invalidJsonSchema)
394 return invalidJsonSchema
400 func (rh *Resthook) GetPolicyInstance(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) (interface{}, error) {
401 a1.Logger.Debug("GetPolicyInstance1")
405 typekey := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
408 a1.Logger.Debug("key1 : %+v", typekey)
410 valmap, err := rh.db.Get(a1MediatorNs, keys[:])
411 if len(valmap) == 0 {
412 a1.Logger.Debug("policy type Not Present for policyid : %v", policyTypeId)
413 return "{}", policyTypeNotFoundError
417 a1.Logger.Error("error in retrieving policy type. err: %v", err)
421 if valmap[typekey] == nil {
422 a1.Logger.Debug("policy type Not Present for policyid : %v", policyTypeId)
423 return "{}", policyTypeNotFoundError
426 a1.Logger.Debug("keysmap : %+v", valmap[typekey])
428 instancekey := a1InstancePrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
429 a1.Logger.Debug("key2 : %+v", instancekey)
430 keys[0] = instancekey
431 instanceMap, err := rh.db.Get(a1MediatorNs, keys[:])
433 a1.Logger.Error("policy instance error : %v", err)
435 a1.Logger.Debug("policyinstancetype map : %+v", instanceMap)
437 if instanceMap[instancekey] == nil {
438 a1.Logger.Debug("policy instance Not Present for policyinstaneid : %v", policyInstanceID)
439 return "{}", policyInstanceNotFoundError
442 valStr := fmt.Sprint(instanceMap[instancekey])
446 func (rh *Resthook) GetAllPolicyInstance(policyTypeId models.PolicyTypeID) ([]models.PolicyInstanceID, error) {
447 a1.Logger.Debug("GetAllPolicyInstance")
448 var policyTypeInstances = []models.PolicyInstanceID{}
450 keys, err := rh.db.GetAll("A1m_ns")
453 a1.Logger.Error("error in retrieving policy. err: %v", err)
454 return policyTypeInstances, err
456 a1.Logger.Debug("keys : %+v", keys)
457 typekey := a1InstancePrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "."
459 for _, key := range keys {
460 if strings.HasPrefix(strings.TrimLeft(key, " "), typekey) {
461 pti := strings.Split(strings.Trim(key, " "), typekey)[1]
462 a1.Logger.Debug("pti %+v", pti)
463 policyTypeInstances = append(policyTypeInstances, models.PolicyInstanceID(pti))
467 if len(policyTypeInstances) == 0 {
468 a1.Logger.Debug("policy instance Not Present ")
471 a1.Logger.Debug("return : %+v", policyTypeInstances)
472 return policyTypeInstances, nil
475 func (rh *Resthook) DeletePolicyType(policyTypeId models.PolicyTypeID) error {
476 a1.Logger.Debug("DeletePolicyType")
478 policyinstances, err := rh.GetAllPolicyInstance(policyTypeId)
480 a1.Logger.Error("error in retrieving policy. err: %v", err)
485 key := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
487 if len(policyinstances) == 0 {
488 err := rh.db.Remove(a1MediatorNs, keys[:])
490 a1.Logger.Error("error in deleting policy type err: %v", err)
494 a1.Logger.Error("tried to delete a type that isn't empty")
495 return policyTypeCanNotBeDeletedError
500 func (rh *Resthook) typeValidity(policyTypeId models.PolicyTypeID) error {
503 typekey := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
506 a1.Logger.Debug("key1 : %+v", typekey)
507 valmap, err := rh.db.Get(a1MediatorNs, keys[:])
509 a1.Logger.Error("error in retrieving policytype err: %v", err)
512 if len(valmap) == 0 {
513 a1.Logger.Error("policy type Not Present for policyid : %v", policyTypeId)
514 return policyTypeNotFoundError
518 func (rh *Resthook) instanceValidity(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) error {
519 err := rh.typeValidity(policyTypeId)
523 policyTypeInstances, err := rh.GetPolicyInstance(policyTypeId, policyInstanceID)
525 a1.Logger.Error("policy instance error : %v", err)
528 if len(policyTypeInstances.(string)) == 0 {
529 a1.Logger.Debug("policy instance Not Present ")
530 return policyInstanceNotFoundError
534 func (rh *Resthook) getMetaData(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) (map[string]interface{}, error) {
535 instanceMetadataKey := a1InstanceMetadataPrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
536 a1.Logger.Debug("instanceMetadata key : %+v", instanceMetadataKey)
538 keys[0] = instanceMetadataKey
539 instanceMetadataMap, err := rh.db.Get(a1MediatorNs, keys[:])
541 a1.Logger.Error("policy instance error : %v", err)
543 a1.Logger.Debug("instanceMetadata map : %+v", instanceMetadataMap)
544 if instanceMetadataMap[instanceMetadataKey] == nil {
545 a1.Logger.Error("policy instance Not Present for policyinstaneid : %v", policyInstanceID)
546 return map[string]interface{}{}, policyInstanceNotFoundError
548 return instanceMetadataMap, nil
551 func (rh *Resthook) GetPolicyInstanceStatus(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) (*a1_mediator.A1ControllerGetPolicyInstanceStatusOKBody, error) {
552 err := rh.instanceValidity(policyTypeId, policyInstanceID)
553 if err != nil && err == policyInstanceNotFoundError || err == policyTypeNotFoundError {
554 policyInstanceStatus.InstanceStatus = "NOT IN EFFECT"
555 return &policyInstanceStatus, err
557 policyInstanceStatus := a1_mediator.A1ControllerGetPolicyInstanceStatusOKBody{}
558 metadata, err := rh.getMetaData(policyTypeId, policyInstanceID)
559 a1.Logger.Debug(" metadata %v", metadata)
561 a1.Logger.Error("policy instance error : %v", err)
562 policyInstanceStatus.InstanceStatus = "NOT IN EFFECT"
563 return &policyInstanceStatus, err
565 jsonbody, err := json.Marshal(metadata)
567 a1.Logger.Error("marshal error : %v", err)
568 return &policyInstanceStatus, err
571 if err := json.Unmarshal(jsonbody, &policyInstanceStatus); err != nil {
572 a1.Logger.Error("unmarshal error : %v", err)
573 //this error maps to 503 error but can be mapped to 500: internal error
574 return &policyInstanceStatus, err
576 if policyInstanceStatus.HasBeenDeleted == false {
577 policyInstanceStatus.InstanceStatus = "IN EFFECT"
579 policyInstanceStatus.InstanceStatus = "NOT IN EFFECT"
581 return &policyInstanceStatus, nil
584 func (rh *Resthook) storeDeletedPolicyInstanceMetadata(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID, creation_timestamp string) error {
585 deleted_timestamp := time.Now()
587 instanceMetadataKey := a1InstanceMetadataPrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
589 a1.Logger.Debug("instanceMetadata Key : %+v", instanceMetadataKey)
591 var metadatajson interface{}
592 metadatajson = map[string]string{"created_at": creation_timestamp, "has_been_deleted": "True", "deleted_at": deleted_timestamp.Format("2006-01-02 15:04:05")}
593 a1.Logger.Debug("metadatajson to create : %+v", metadatajson)
594 deletedmetadata, err := json.Marshal(metadatajson)
596 a1.Logger.Debug("policyinstanceMetaData to create : %+v", string(deletedmetadata))
598 err = rh.db.Set(a1MediatorNs, instanceMetadataKey, string(deletedmetadata))
599 a1.Logger.Debug("deletemetadatacreated")
601 a1.Logger.Error("error :%+v", err)
605 a1.Logger.Error("Policy Instance Meta Data deleted at :%+v", creation_timestamp)
610 func (rh *Resthook) deleteInstancedata(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) error {
612 instancekey := a1InstancePrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
613 keys[0] = instancekey
614 err := rh.db.Remove(a1MediatorNs, keys[:])
616 a1.Logger.Error("error in deleting policy type err: %v", err)
622 func (rh *Resthook) deleteMetadata(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) error {
624 instanceMetadataKey := a1InstanceMetadataPrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
626 a1.Logger.Debug("instanceMetadata Key : %+v", instanceMetadataKey)
627 keys[0] = instanceMetadataKey
628 err := rh.db.Remove(a1MediatorNs, keys[:])
630 a1.Logger.Error("error in deleting policy metadata err: %v", err)
636 func (rh *Resthook) DeletePolicyInstance(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) error {
637 err := rh.instanceValidity(policyTypeId, policyInstanceID)
639 a1.Logger.Error("policy instance error : %v", err)
640 if err == policyInstanceNotFoundError || err == policyTypeNotFoundError {
645 createdmetadata, err := rh.getMetaData(policyTypeId, policyInstanceID)
647 a1.Logger.Error("error : %v", err)
650 a1.Logger.Debug(" created metadata %v", createdmetadata)
651 instanceMetadataKey := a1InstanceMetadataPrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
652 creation_metadata := createdmetadata[instanceMetadataKey]
653 var metadata map[string]interface{}
654 if err = json.Unmarshal([]byte(creation_metadata.(string)), &metadata); err != nil {
655 a1.Logger.Error("unmarshal error : %v", err)
659 a1.Logger.Debug(" created metadata created_at %v", metadata["created_at"])
660 creation_timestamp := metadata["created_at"]
662 rh.deleteMetadata(policyTypeId, policyInstanceID)
664 rh.deleteInstancedata(policyTypeId, policyInstanceID)
666 rh.storeDeletedPolicyInstanceMetadata(policyTypeId, policyInstanceID, creation_timestamp.(string))
668 message := rmr.Message{}
669 rmrMessage, err = message.PolicyMessage(strconv.FormatInt((int64(policyTypeId)), 10), string(policyInstanceID), "", "DELETE")
671 a1.Logger.Error("error : %v", err)
674 isSent := rh.iRmrSenderInst.RmrSendToXapp(rmrMessage)
676 a1.Logger.Debug("rmrSendToXapp : message sent")
678 //TODO:if message not sent need to return error or just log it or retry sending
679 a1.Logger.Error("rmrSendToXapp : message not sent")