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")
374 message := rmr.Message{}
375 rmrMessage, err := message.PolicyMessage(strconv.FormatInt((int64(policyTypeId)), 10), string(policyInstanceID), httpBodyString, operation)
377 a1.Logger.Error("error : %v", err)
380 isSent := rh.iRmrSenderInst.RmrSendToXapp(rmrMessage)
382 a1.Logger.Debug("rmrSendToXapp : message sent")
384 a1.Logger.Debug("rmrSendToXapp : message not sent")
388 a1.Logger.Error("%+v", invalidJsonSchema)
389 return invalidJsonSchema
395 func (rh *Resthook) GetPolicyInstance(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) (interface{}, error) {
396 a1.Logger.Debug("GetPolicyInstance1")
400 typekey := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
403 a1.Logger.Debug("key1 : %+v", typekey)
405 valmap, err := rh.db.Get(a1MediatorNs, keys[:])
406 if len(valmap) == 0 {
407 a1.Logger.Debug("policy type Not Present for policyid : %v", policyTypeId)
408 return "{}", policyTypeNotFoundError
412 a1.Logger.Error("error in retrieving policy type. err: %v", err)
416 if valmap[typekey] == nil {
417 a1.Logger.Debug("policy type Not Present for policyid : %v", policyTypeId)
418 return "{}", policyTypeNotFoundError
421 a1.Logger.Debug("keysmap : %+v", valmap[typekey])
423 instancekey := a1InstancePrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
424 a1.Logger.Debug("key2 : %+v", instancekey)
425 keys[0] = instancekey
426 instanceMap, err := rh.db.Get(a1MediatorNs, keys[:])
428 a1.Logger.Error("policy instance error : %v", err)
430 a1.Logger.Debug("policyinstancetype map : %+v", instanceMap)
432 if instanceMap[instancekey] == nil {
433 a1.Logger.Debug("policy instance Not Present for policyinstaneid : %v", policyInstanceID)
434 return "{}", policyInstanceNotFoundError
437 valStr := fmt.Sprint(instanceMap[instancekey])
441 func (rh *Resthook) GetAllPolicyInstance(policyTypeId models.PolicyTypeID) ([]models.PolicyInstanceID, error) {
442 a1.Logger.Debug("GetAllPolicyInstance")
443 var policyTypeInstances = []models.PolicyInstanceID{}
445 keys, err := rh.db.GetAll("A1m_ns")
448 a1.Logger.Error("error in retrieving policy. err: %v", err)
449 return policyTypeInstances, err
451 a1.Logger.Debug("keys : %+v", keys)
452 typekey := a1InstancePrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "."
454 for _, key := range keys {
455 if strings.HasPrefix(strings.TrimLeft(key, " "), typekey) {
456 pti := strings.Split(strings.Trim(key, " "), typekey)[1]
457 a1.Logger.Debug("pti %+v", pti)
458 policyTypeInstances = append(policyTypeInstances, models.PolicyInstanceID(pti))
462 if len(policyTypeInstances) == 0 {
463 a1.Logger.Debug("policy instance Not Present ")
466 a1.Logger.Debug("return : %+v", policyTypeInstances)
467 return policyTypeInstances, nil
470 func (rh *Resthook) DeletePolicyType(policyTypeId models.PolicyTypeID) error {
471 a1.Logger.Debug("DeletePolicyType")
473 policyinstances, err := rh.GetAllPolicyInstance(policyTypeId)
475 a1.Logger.Error("error in retrieving policy. err: %v", err)
480 key := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
482 if len(policyinstances) == 0 {
483 err := rh.db.Remove(a1MediatorNs, keys[:])
485 a1.Logger.Error("error in deleting policy type err: %v", err)
489 a1.Logger.Error("tried to delete a type that isn't empty")
490 return policyTypeCanNotBeDeletedError
495 func (rh *Resthook) typeValidity(policyTypeId models.PolicyTypeID) error {
498 typekey := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
501 a1.Logger.Debug("key1 : %+v", typekey)
502 valmap, err := rh.db.Get(a1MediatorNs, keys[:])
504 a1.Logger.Error("error in retrieving policytype err: %v", err)
507 if len(valmap) == 0 {
508 a1.Logger.Error("policy type Not Present for policyid : %v", policyTypeId)
509 return policyTypeNotFoundError
513 func (rh *Resthook) instanceValidity(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) error {
514 err := rh.typeValidity(policyTypeId)
518 policyTypeInstances, err := rh.GetPolicyInstance(policyTypeId, policyInstanceID)
520 a1.Logger.Error("policy instance error : %v", err)
523 if len(policyTypeInstances.(string)) == 0 {
524 a1.Logger.Debug("policy instance Not Present ")
525 return policyInstanceNotFoundError
529 func (rh *Resthook) getMetaData(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) (map[string]interface{}, error) {
530 instanceMetadataKey := a1InstanceMetadataPrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
531 a1.Logger.Debug("instanceMetadata key : %+v", instanceMetadataKey)
533 keys[0] = instanceMetadataKey
534 instanceMetadataMap, err := rh.db.Get(a1MediatorNs, keys[:])
536 a1.Logger.Error("policy instance error : %v", err)
538 a1.Logger.Debug("instanceMetadata map : %+v", instanceMetadataMap)
539 if instanceMetadataMap[instanceMetadataKey] == nil {
540 a1.Logger.Error("policy instance Not Present for policyinstaneid : %v", policyInstanceID)
541 return map[string]interface{}{}, policyInstanceNotFoundError
543 return instanceMetadataMap, nil
546 func (rh *Resthook) GetPolicyInstanceStatus(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) (*a1_mediator.A1ControllerGetPolicyInstanceStatusOKBody, error) {
547 err := rh.instanceValidity(policyTypeId, policyInstanceID)
548 if err != nil && err == policyInstanceNotFoundError || err == policyTypeNotFoundError {
549 policyInstanceStatus.InstanceStatus = "NOT IN EFFECT"
550 return &policyInstanceStatus, err
552 policyInstanceStatus := a1_mediator.A1ControllerGetPolicyInstanceStatusOKBody{}
553 metadata, err := rh.getMetaData(policyTypeId, policyInstanceID)
554 a1.Logger.Debug(" metadata %v", metadata)
556 a1.Logger.Error("policy instance error : %v", err)
557 policyInstanceStatus.InstanceStatus = "NOT IN EFFECT"
558 return &policyInstanceStatus, err
560 jsonbody, err := json.Marshal(metadata)
562 a1.Logger.Error("marshal error : %v", err)
563 return &policyInstanceStatus, err
566 if err := json.Unmarshal(jsonbody, &policyInstanceStatus); err != nil {
567 a1.Logger.Error("unmarshal error : %v", err)
568 //this error maps to 503 error but can be mapped to 500: internal error
569 return &policyInstanceStatus, err
571 if policyInstanceStatus.HasBeenDeleted == false {
572 policyInstanceStatus.InstanceStatus = "IN EFFECT"
574 policyInstanceStatus.InstanceStatus = "NOT IN EFFECT"
576 return &policyInstanceStatus, nil