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")
55 func (rh *Resthook) CanPolicyTypeBeDeleted(err error) bool {
56 return err == policyTypeCanNotBeDeletedError
59 func (rh *Resthook) IsPolicyTypePresent(err error) bool {
60 return err == policyTypeNotFoundError
63 func (rh *Resthook) IsPolicyInstanceNotFound(err error) bool {
64 return err == policyInstanceNotFoundError
67 func (rh *Resthook) IsTypeAlready(err error) bool {
68 return err == typeAlreadyError
70 func (rh *Resthook) IsInstanceAlready(err error) bool {
71 return err == InstanceAlreadyError
73 func (rh *Resthook) IsTypeMismatch(err error) bool {
74 return err == typeMismatchError
77 func (rh *Resthook) IsValidJson(err error) bool {
78 return err == invalidJsonSchema
80 func NewResthook() *Resthook {
81 return createResthook(sdlgo.NewSyncStorage(), rmr.NewRMRSender())
84 func createResthook(sdlInst iSdl, rmrSenderInst rmr.IRmrSender) *Resthook {
87 iRmrSenderInst: rmrSenderInst,
91 func (rh *Resthook) GetAllPolicyType() []models.PolicyTypeID {
93 var policyTypeIDs []models.PolicyTypeID
95 keys, err := rh.db.GetAll("A1m_ns")
98 a1.Logger.Error("error in retrieving policy. err: %v", err)
101 a1.Logger.Debug("keys : %+v", keys)
103 for _, key := range keys {
104 if strings.HasPrefix(strings.TrimLeft(key, " "), a1PolicyPrefix) {
105 pti := strings.Split(strings.Trim(key, " "), a1PolicyPrefix)[1]
106 ptii, _ := strconv.ParseInt(pti, 10, 64)
107 policyTypeIDs = append(policyTypeIDs, models.PolicyTypeID(ptii))
111 a1.Logger.Debug("return : %+v", policyTypeIDs)
115 func (rh *Resthook) GetPolicyType(policyTypeId models.PolicyTypeID) *models.PolicyTypeSchema {
116 a1.Logger.Debug("GetPolicyType1")
118 var policytypeschema *models.PolicyTypeSchema
121 key := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
124 a1.Logger.Debug("key : %+v", key)
126 valmap, err := rh.db.Get(a1MediatorNs, keys[:])
128 a1.Logger.Debug("policytype map : %+v", valmap)
130 if len(valmap) == 0 {
131 a1.Logger.Error("policy type Not Present for policyid : %v", policyTypeId)
132 return policytypeschema
136 a1.Logger.Error("error in retrieving policy type. err: %v", err)
140 if valmap[key] == nil {
141 a1.Logger.Error("policy type Not Present for policyid : %v", policyTypeId)
142 return policytypeschema
145 a1.Logger.Debug("keysmap : %+v", valmap[key])
147 var item models.PolicyTypeSchema
148 valStr := fmt.Sprint(valmap[key])
150 a1.Logger.Debug("Policy type for %+v : %+v", key, valStr)
151 valkey := "`" + valStr + "`"
152 valToUnmarshall, err := strconv.Unquote(valkey)
154 a1.Logger.Error("unquote error : %+v", err)
158 a1.Logger.Debug("Policy type for %+v : %+v", key, string(valToUnmarshall))
160 errunm := json.Unmarshal([]byte(valToUnmarshall), &item)
162 a1.Logger.Debug(" Unmarshalled json : %+v", (errunm))
163 a1.Logger.Debug("Policy type Name : %v", (item.Name))
168 func (rh *Resthook) CreatePolicyType(policyTypeId models.PolicyTypeID, httprequest models.PolicyTypeSchema) error {
169 a1.Logger.Debug("CreatePolicyType function")
170 if policyTypeId != models.PolicyTypeID(*httprequest.PolicyTypeID) {
172 a1.Logger.Debug("Policytype Mismatch")
173 return typeMismatchError
175 key := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
176 a1.Logger.Debug("key %+v ", key)
177 if data, err := httprequest.MarshalBinary(); err == nil {
178 a1.Logger.Debug("Marshaled String : %+v", string(data))
179 success, err1 := rh.db.SetIfNotExists(a1MediatorNs, key, string(data))
180 a1.Logger.Info("success:%+v", success)
182 a1.Logger.Error("error :%+v", err1)
186 a1.Logger.Debug("Policy type %+v already exist", policyTypeId)
187 return typeAlreadyError
193 func toStringKeys(val interface{}) (interface{}, error) {
195 switch val := val.(type) {
196 case map[interface{}]interface{}:
197 m := make(map[string]interface{})
198 for k, v := range val {
201 return nil, errors.New("found non-string key")
203 m[k], err = toStringKeys(v)
210 var l = make([]interface{}, len(val))
211 for i, v := range val {
212 l[i], err = toStringKeys(v)
223 func validate(httpBodyString string, schemaString string) bool {
225 err := yaml.Unmarshal([]byte(httpBodyString), &m)
227 a1.Logger.Error("Unmarshal error : %+v", err)
229 m, err = toStringKeys(m)
231 a1.Logger.Error("Conversion to string error : %+v", err)
234 compiler := jsonschema.NewCompiler()
235 if err := compiler.AddResource("schema.json", strings.NewReader(schemaString)); err != nil {
236 a1.Logger.Error("string reader error : %+v", err)
239 schema, err := compiler.Compile("schema.json")
241 a1.Logger.Error("schema json compile error : %+v", err)
244 if err := schema.Validate(m); err != nil {
245 a1.Logger.Error("schema validation error : %+v", err)
248 a1.Logger.Debug("validation successfull")
252 func (rh *Resthook) storePolicyInstance(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID, httpBody interface{}) (string, error) {
254 operation := "CREATE"
255 typekey := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
258 a1.Logger.Debug("key1 : %+v", typekey)
260 valmap, err := rh.db.Get(a1MediatorNs, keys[:])
262 a1.Logger.Error("policy type error : %+v", err)
264 a1.Logger.Debug("policytype map : %+v", valmap)
265 if valmap[typekey] == nil {
266 a1.Logger.Error("policy type Not Present for policyid : %v", policyTypeId)
267 return operation, policyTypeNotFoundError
269 // TODO : rmr creation_timestamp := time.Now() // will be needed for rmr to notify the creation of instance
271 instancekey := a1InstancePrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
273 instanceMap, err := rh.db.Get(a1MediatorNs, keys[:])
275 a1.Logger.Error("policy type error : %v", err)
277 a1.Logger.Debug("policyinstancetype map : %+v", instanceMap)
279 if instanceMap[instancekey] != nil {
281 a1.Logger.Debug("UPDATE")
282 data, _ := json.Marshal(httpBody)
283 a1.Logger.Debug("Marshaled String : %+v", string(data))
284 a1.Logger.Debug("key : %+v", instancekey)
285 success, err1 := rh.db.SetIf(a1MediatorNs, instancekey, instanceMap[instancekey], string(data))
287 a1.Logger.Error("error2 :%+v", err1)
288 return operation, err1
291 a1.Logger.Debug("Policy instance %+v already exist", policyInstanceID)
292 return operation, InstanceAlreadyError
295 data, _ := json.Marshal(httpBody)
296 a1.Logger.Debug("Marshaled String : %+v", string(data))
297 a1.Logger.Debug("key : %+v", instancekey)
299 var instance_map []interface{}
300 instance_map = append(instance_map, instancekey, string(data))
301 a1.Logger.Debug("policyinstancetype map : %+v", instance_map[1])
302 a1.Logger.Debug("policyinstancetype to create : %+v", instance_map)
304 err1 := rh.db.Set(a1MediatorNs, instancekey, string(data))
306 a1.Logger.Error("error1 :%+v", err1)
307 return operation, err1
310 a1.Logger.Debug("Policy Instance created ")
311 return operation, nil
314 func (rh *Resthook) storePolicyInstanceMetadata(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) (bool, error) {
316 creation_timestamp := time.Now()
317 instanceMetadataKey := a1InstanceMetadataPrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
319 a1.Logger.Debug("key : %+v", instanceMetadataKey)
321 var metadatajson []interface{}
322 metadatajson = append(metadatajson, map[string]string{"created_at": creation_timestamp.Format("2006-01-02 15:04:05"), "has_been_deleted": "False"})
323 metadata, _ := json.Marshal(metadatajson)
325 a1.Logger.Debug("policyinstanceMetaData to create : %+v", string(metadata))
327 err := rh.db.Set(a1MediatorNs, instanceMetadataKey, string(metadata))
330 a1.Logger.Error("error :%+v", err)
334 a1.Logger.Debug("Policy Instance Meta Data created at :%+v", creation_timestamp)
339 func (rh *Resthook) CreatePolicyInstance(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID, httpBody interface{}) error {
340 a1.Logger.Debug("CreatePolicyInstance function")
341 // validate the PUT against the schema
342 var policyTypeSchema *models.PolicyTypeSchema
343 policyTypeSchema = rh.GetPolicyType(policyTypeId)
344 schemaStr, err := json.Marshal(policyTypeSchema.CreateSchema)
346 a1.Logger.Error("Json Marshal error : %+v", err)
349 a1.Logger.Debug("schema to validate %+v", string(schemaStr))
350 a1.Logger.Debug("httpbody to validate %+v", httpBody)
351 schemaString := fmt.Sprint(string(schemaStr))
352 httpBodyMarshal, err := json.Marshal(httpBody)
353 httpBodyString := string((httpBodyMarshal))
354 a1.Logger.Debug("schema to validate sprint %+v", (schemaString))
355 a1.Logger.Debug("httpbody to validate sprint %+v", httpBodyString)
356 isvalid := validate(httpBodyString, schemaString)
359 operation, err = rh.storePolicyInstance(policyTypeId, policyInstanceID, httpBody)
361 a1.Logger.Error("error :%+v", err)
364 a1.Logger.Debug("policy instance :%+v", operation)
365 iscreated, errmetadata := rh.storePolicyInstanceMetadata(policyTypeId, policyInstanceID)
366 if errmetadata != nil {
367 a1.Logger.Error("error :%+v", errmetadata)
371 a1.Logger.Debug("policy instance metadata created")
373 isSent := rh.iRmrSenderInst.RmrSendToXapp(httpBodyString)
375 a1.Logger.Debug("rmrSendToXapp : message sent")
377 a1.Logger.Debug("rmrSendToXapp : message not sent")
381 a1.Logger.Error("%+v", invalidJsonSchema)
382 return invalidJsonSchema
388 func (rh *Resthook) GetPolicyInstance(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) (interface{}, error) {
389 a1.Logger.Debug("GetPolicyInstance1")
393 typekey := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
396 a1.Logger.Debug("key1 : %+v", typekey)
398 valmap, err := rh.db.Get(a1MediatorNs, keys[:])
399 if len(valmap) == 0 {
400 a1.Logger.Debug("policy type Not Present for policyid : %v", policyTypeId)
401 return "{}", policyTypeNotFoundError
405 a1.Logger.Error("error in retrieving policy type. err: %v", err)
409 if valmap[typekey] == nil {
410 a1.Logger.Debug("policy type Not Present for policyid : %v", policyTypeId)
411 return "{}", policyTypeNotFoundError
414 a1.Logger.Debug("keysmap : %+v", valmap[typekey])
416 instancekey := a1InstancePrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
417 a1.Logger.Debug("key2 : %+v", instancekey)
418 keys[0] = instancekey
419 instanceMap, err := rh.db.Get(a1MediatorNs, keys[:])
421 a1.Logger.Error("policy instance error : %v", err)
423 a1.Logger.Debug("policyinstancetype map : %+v", instanceMap)
425 if instanceMap[instancekey] == nil {
426 a1.Logger.Debug("policy instance Not Present for policyinstaneid : %v", policyInstanceID)
427 return "{}", policyInstanceNotFoundError
430 valStr := fmt.Sprint(instanceMap[instancekey])
434 func (rh *Resthook) GetAllPolicyInstance(policyTypeId models.PolicyTypeID) ([]models.PolicyInstanceID, error) {
435 a1.Logger.Debug("GetAllPolicyInstance")
436 var policyTypeInstances = []models.PolicyInstanceID{}
438 keys, err := rh.db.GetAll("A1m_ns")
441 a1.Logger.Error("error in retrieving policy. err: %v", err)
442 return policyTypeInstances, err
444 a1.Logger.Debug("keys : %+v", keys)
445 typekey := a1InstancePrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "."
447 for _, key := range keys {
448 if strings.HasPrefix(strings.TrimLeft(key, " "), typekey) {
449 pti := strings.Split(strings.Trim(key, " "), typekey)[1]
450 a1.Logger.Debug("pti %+v", pti)
451 policyTypeInstances = append(policyTypeInstances, models.PolicyInstanceID(pti))
455 if len(policyTypeInstances) == 0 {
456 a1.Logger.Debug("policy instance Not Present ")
459 a1.Logger.Debug("return : %+v", policyTypeInstances)
460 return policyTypeInstances, nil
463 func (rh *Resthook) DeletePolicyType(policyTypeId models.PolicyTypeID) error {
464 a1.Logger.Debug("DeletePolicyType")
466 policyinstances, err := rh.GetAllPolicyInstance(policyTypeId)
468 a1.Logger.Error("error in retrieving policy. err: %v", err)
473 key := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
475 if len(policyinstances) == 0 {
476 err := rh.db.Remove(a1MediatorNs, keys[:])
478 a1.Logger.Error("error in deleting policy type err: %v", err)
482 a1.Logger.Error("tried to delete a type that isn't empty")
483 return policyTypeCanNotBeDeletedError
488 func (rh *Resthook) typeValidity(policyTypeId models.PolicyTypeID) error {
491 typekey := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
494 a1.Logger.Debug("key1 : %+v", typekey)
495 valmap, err := rh.db.Get(a1MediatorNs, keys[:])
497 a1.Logger.Error("error in retrieving policytype err: %v", err)
500 if len(valmap) == 0 {
501 a1.Logger.Error("policy type Not Present for policyid : %v", policyTypeId)
502 return policyTypeNotFoundError
506 func (rh *Resthook) instanceValidity(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) error {
507 err := rh.typeValidity(policyTypeId)
511 policyTypeInstances, err := rh.GetPolicyInstance(policyTypeId, policyInstanceID)
513 a1.Logger.Error("policy instance error : %v", err)
516 if len(policyTypeInstances.(string)) == 0 {
517 a1.Logger.Debug("policy instance Not Present ")
518 return policyInstanceNotFoundError
522 func (rh *Resthook) getMetaData(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) (map[string]interface{}, error) {
523 instanceMetadataKey := a1InstanceMetadataPrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
524 a1.Logger.Debug("instanceMetadata key : %+v", instanceMetadataKey)
526 keys[0] = instanceMetadataKey
527 instanceMetadataMap, err := rh.db.Get(a1MediatorNs, keys[:])
529 a1.Logger.Error("policy instance error : %v", err)
531 a1.Logger.Debug("instanceMetadata map : %+v", instanceMetadataMap)
532 if instanceMetadataMap[instanceMetadataKey] == nil {
533 a1.Logger.Error("policy instance Not Present for policyinstaneid : %v", policyInstanceID)
534 return map[string]interface{}{}, policyInstanceNotFoundError
536 return instanceMetadataMap, nil
539 func (rh *Resthook) GetPolicyInstanceStatus(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) (*a1_mediator.A1ControllerGetPolicyInstanceStatusOKBody, error) {
540 err := rh.instanceValidity(policyTypeId, policyInstanceID)
541 if err != nil && err == policyInstanceNotFoundError || err == policyTypeNotFoundError {
542 policyInstanceStatus.InstanceStatus = "NOT IN EFFECT"
543 return &policyInstanceStatus, err
545 policyInstanceStatus := a1_mediator.A1ControllerGetPolicyInstanceStatusOKBody{}
546 metadata, err := rh.getMetaData(policyTypeId, policyInstanceID)
547 a1.Logger.Debug(" metadata %v", metadata)
549 a1.Logger.Error("policy instance error : %v", err)
550 policyInstanceStatus.InstanceStatus = "NOT IN EFFECT"
551 return &policyInstanceStatus, err
553 jsonbody, err := json.Marshal(metadata)
555 a1.Logger.Error("marshal error : %v", err)
556 return &policyInstanceStatus, err
559 if err := json.Unmarshal(jsonbody, &policyInstanceStatus); err != nil {
560 a1.Logger.Error("unmarshal error : %v", err)
561 //this error maps to 503 error but can be mapped to 500: internal error
562 return &policyInstanceStatus, err
564 if policyInstanceStatus.HasBeenDeleted == false {
565 policyInstanceStatus.InstanceStatus = "IN EFFECT"
567 policyInstanceStatus.InstanceStatus = "NOT IN EFFECT"
569 return &policyInstanceStatus, nil