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/sdlgo"
34 "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
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")
54 func (rh *Resthook) IsPolicyTypePresent(err error) bool {
55 return err == policyTypeNotFoundError
58 func (rh *Resthook) IsPolicyInstanceNotFound(err error) bool {
59 return err == policyInstanceNotFoundError
62 func (rh *Resthook) IsTypeAlready(err error) bool {
63 return err == typeAlreadyError
65 func (rh *Resthook) IsInstanceAlready(err error) bool {
66 return err == InstanceAlreadyError
68 func (rh *Resthook) IsTypeMismatch(err error) bool {
69 return err == typeMismatchError
72 func (rh *Resthook) IsValidJson(err error) bool {
73 return err == invalidJsonSchema
75 func NewResthook() *Resthook {
76 return createResthook(sdlgo.NewSyncStorage(), rmr.NewRMRSender())
79 func createResthook(sdlInst iSdl, rmrSenderInst rmr.IRmrSender) *Resthook {
82 iRmrSenderInst: rmrSenderInst,
86 func (rh *Resthook) GetAllPolicyType() []models.PolicyTypeID {
88 var policyTypeIDs []models.PolicyTypeID
90 keys, err := rh.db.GetAll("A1m_ns")
93 a1.Logger.Error("error in retrieving policy. err: %v", err)
96 a1.Logger.Debug("keys : %+v", keys)
98 for _, key := range keys {
99 if strings.HasPrefix(strings.TrimLeft(key, " "), a1PolicyPrefix) {
100 pti := strings.Split(strings.Trim(key, " "), a1PolicyPrefix)[1]
101 ptii, _ := strconv.ParseInt(pti, 10, 64)
102 policyTypeIDs = append(policyTypeIDs, models.PolicyTypeID(ptii))
106 a1.Logger.Debug("return : %+v", policyTypeIDs)
110 func (rh *Resthook) GetPolicyType(policyTypeId models.PolicyTypeID) *models.PolicyTypeSchema {
111 a1.Logger.Debug("GetPolicyType1")
113 var policytypeschema *models.PolicyTypeSchema
116 key := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
119 a1.Logger.Debug("key : %+v", key)
121 valmap, err := rh.db.Get(a1MediatorNs, keys[:])
123 a1.Logger.Debug("policytype map : %+v", valmap)
125 if len(valmap) == 0 {
126 a1.Logger.Error("policy type Not Present for policyid : %v", policyTypeId)
127 return policytypeschema
131 a1.Logger.Error("error in retrieving policy type. err: %v", err)
135 if valmap[key] == nil {
136 a1.Logger.Error("policy type Not Present for policyid : %v", policyTypeId)
137 return policytypeschema
140 a1.Logger.Debug("keysmap : %+v", valmap[key])
142 var item models.PolicyTypeSchema
143 valStr := fmt.Sprint(valmap[key])
145 a1.Logger.Debug("Policy type for %+v : %+v", key, valStr)
146 valkey := "`" + valStr + "`"
147 valToUnmarshall, err := strconv.Unquote(valkey)
149 a1.Logger.Error("unquote error : %+v", err)
153 a1.Logger.Debug("Policy type for %+v : %+v", key, string(valToUnmarshall))
155 errunm := json.Unmarshal([]byte(valToUnmarshall), &item)
157 a1.Logger.Debug(" Unmarshalled json : %+v", (errunm))
158 a1.Logger.Debug("Policy type Name : %v", (item.Name))
163 func (rh *Resthook) CreatePolicyType(policyTypeId models.PolicyTypeID, httprequest models.PolicyTypeSchema) error {
164 a1.Logger.Debug("CreatePolicyType function")
165 if policyTypeId != models.PolicyTypeID(*httprequest.PolicyTypeID) {
167 a1.Logger.Debug("Policytype Mismatch")
168 return typeMismatchError
170 key := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
171 a1.Logger.Debug("key %+v ", key)
172 if data, err := httprequest.MarshalBinary(); err == nil {
173 a1.Logger.Debug("Marshaled String : %+v", string(data))
174 success, err1 := rh.db.SetIfNotExists(a1MediatorNs, key, string(data))
175 a1.Logger.Info("success:%+v", success)
177 a1.Logger.Error("error :%+v", err1)
181 a1.Logger.Debug("Policy type %+v already exist", policyTypeId)
182 return typeAlreadyError
188 func toStringKeys(val interface{}) (interface{}, error) {
190 switch val := val.(type) {
191 case map[interface{}]interface{}:
192 m := make(map[string]interface{})
193 for k, v := range val {
196 return nil, errors.New("found non-string key")
198 m[k], err = toStringKeys(v)
205 var l = make([]interface{}, len(val))
206 for i, v := range val {
207 l[i], err = toStringKeys(v)
218 func validate(httpBodyString string, schemaString string) bool {
220 err := yaml.Unmarshal([]byte(httpBodyString), &m)
222 a1.Logger.Error("Unmarshal error : %+v", err)
224 m, err = toStringKeys(m)
226 a1.Logger.Error("Conversion to string error : %+v", err)
229 compiler := jsonschema.NewCompiler()
230 if err := compiler.AddResource("schema.json", strings.NewReader(schemaString)); err != nil {
231 a1.Logger.Error("string reader error : %+v", err)
234 schema, err := compiler.Compile("schema.json")
236 a1.Logger.Error("schema json compile error : %+v", err)
239 if err := schema.Validate(m); err != nil {
240 a1.Logger.Error("schema validation error : %+v", err)
243 a1.Logger.Debug("validation successfull")
247 func (rh *Resthook) storePolicyInstance(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID, httpBody interface{}) (string, error) {
249 operation := "CREATE"
250 typekey := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
253 a1.Logger.Debug("key1 : %+v", typekey)
255 valmap, err := rh.db.Get(a1MediatorNs, keys[:])
257 a1.Logger.Error("policy type error : %+v", err)
259 a1.Logger.Debug("policytype map : %+v", valmap)
260 if valmap[typekey] == nil {
261 a1.Logger.Error("policy type Not Present for policyid : %v", policyTypeId)
262 return operation, policyTypeNotFoundError
264 // TODO : rmr creation_timestamp := time.Now() // will be needed for rmr to notify the creation of instance
266 instancekey := a1InstancePrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
268 instanceMap, err := rh.db.Get(a1MediatorNs, keys[:])
270 a1.Logger.Error("policy type error : %v", err)
272 a1.Logger.Debug("policyinstancetype map : %+v", instanceMap)
274 if instanceMap[instancekey] != nil {
276 a1.Logger.Debug("UPDATE")
277 data, _ := json.Marshal(httpBody)
278 a1.Logger.Debug("Marshaled String : %+v", string(data))
279 a1.Logger.Debug("key : %+v", instancekey)
280 success, err1 := rh.db.SetIf(a1MediatorNs, instancekey, instanceMap[instancekey], string(data))
282 a1.Logger.Error("error2 :%+v", err1)
283 return operation, err1
286 a1.Logger.Debug("Policy instance %+v already exist", policyInstanceID)
287 return operation, InstanceAlreadyError
290 data, _ := json.Marshal(httpBody)
291 a1.Logger.Debug("Marshaled String : %+v", string(data))
292 a1.Logger.Debug("key : %+v", instancekey)
294 var instance_map []interface{}
295 instance_map = append(instance_map, instancekey, string(data))
296 a1.Logger.Debug("policyinstancetype map : %+v", instance_map[1])
297 a1.Logger.Debug("policyinstancetype to create : %+v", instance_map)
299 err1 := rh.db.Set(a1MediatorNs, instancekey, string(data))
301 a1.Logger.Error("error1 :%+v", err1)
302 return operation, err1
305 a1.Logger.Debug("Policy Instance created ")
306 return operation, nil
309 func (rh *Resthook) storePolicyInstanceMetadata(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) (bool, error) {
311 creation_timestamp := time.Now()
312 instanceMetadataKey := a1InstanceMetadataPrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
314 a1.Logger.Debug("key : %+v", instanceMetadataKey)
316 var metadatajson []interface{}
317 metadatajson = append(metadatajson, map[string]string{"created_at": creation_timestamp.Format("2006-01-02 15:04:05"), "has_been_deleted": "False"})
318 metadata, _ := json.Marshal(metadatajson)
320 a1.Logger.Debug("policyinstanceMetaData to create : %+v", string(metadata))
322 err := rh.db.Set(a1MediatorNs, instanceMetadataKey, string(metadata))
325 a1.Logger.Error("error :%+v", err)
329 a1.Logger.Debug("Policy Instance Meta Data created at :%+v", creation_timestamp)
334 func (rh *Resthook) CreatePolicyInstance(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID, httpBody interface{}) error {
335 a1.Logger.Debug("CreatePolicyInstance function")
336 // validate the PUT against the schema
337 var policyTypeSchema *models.PolicyTypeSchema
338 policyTypeSchema = rh.GetPolicyType(policyTypeId)
339 schemaStr, err := json.Marshal(policyTypeSchema.CreateSchema)
341 a1.Logger.Error("Json Marshal error : %+v", err)
344 a1.Logger.Debug("schema to validate %+v", string(schemaStr))
345 a1.Logger.Debug("httpbody to validate %+v", httpBody)
346 schemaString := fmt.Sprint(string(schemaStr))
347 httpBodyMarshal, err := json.Marshal(httpBody)
348 httpBodyString := string((httpBodyMarshal))
349 a1.Logger.Debug("schema to validate sprint %+v", (schemaString))
350 a1.Logger.Debug("httpbody to validate sprint %+v", httpBodyString)
351 isvalid := validate(httpBodyString, schemaString)
354 operation, err = rh.storePolicyInstance(policyTypeId, policyInstanceID, httpBody)
356 a1.Logger.Error("error :%+v", err)
359 a1.Logger.Debug("policy instance :%+v", operation)
360 iscreated, errmetadata := rh.storePolicyInstanceMetadata(policyTypeId, policyInstanceID)
361 if errmetadata != nil {
362 a1.Logger.Error("error :%+v", errmetadata)
366 a1.Logger.Debug("policy instance metadata created")
368 isSent := rh.iRmrSenderInst.RmrSendToXapp(httpBodyString)
370 a1.Logger.Debug("rmrSendToXapp : message sent")
372 a1.Logger.Debug("rmrSendToXapp : message not sent")
376 a1.Logger.Error("%+v", invalidJsonSchema)
377 return invalidJsonSchema
383 func (rh *Resthook) GetPolicyInstance(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) (interface{}, error) {
384 a1.Logger.Debug("GetPolicyInstance1")
388 typekey := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
391 a1.Logger.Debug("key1 : %+v", typekey)
393 valmap, err := rh.db.Get(a1MediatorNs, keys[:])
394 if len(valmap) == 0 {
395 a1.Logger.Debug("policy type Not Present for policyid : %v", policyTypeId)
396 return "{}", policyTypeNotFoundError
400 a1.Logger.Error("error in retrieving policy type. err: %v", err)
404 if valmap[typekey] == nil {
405 a1.Logger.Debug("policy type Not Present for policyid : %v", policyTypeId)
406 return "{}", policyTypeNotFoundError
409 a1.Logger.Debug("keysmap : %+v", valmap[typekey])
411 instancekey := a1InstancePrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
412 a1.Logger.Debug("key2 : %+v", instancekey)
413 keys[0] = instancekey
414 instanceMap, err := rh.db.Get(a1MediatorNs, keys[:])
416 a1.Logger.Error("policy instance error : %v", err)
418 a1.Logger.Debug("policyinstancetype map : %+v", instanceMap)
420 if instanceMap[instancekey] == nil {
421 a1.Logger.Debug("policy instance Not Present for policyinstaneid : %v", policyInstanceID)
422 return "{}", policyInstanceNotFoundError
425 valStr := fmt.Sprint(instanceMap[instancekey])
429 func (rh *Resthook) GetAllPolicyInstance(policyTypeId models.PolicyTypeID) ([]models.PolicyInstanceID, error) {
430 a1.Logger.Debug("GetAllPolicyInstance")
431 var policyTypeInstances = []models.PolicyInstanceID{}
433 keys, err := rh.db.GetAll("A1m_ns")
436 a1.Logger.Error("error in retrieving policy. err: %v", err)
437 return policyTypeInstances, err
439 a1.Logger.Debug("keys : %+v", keys)
440 typekey := a1InstancePrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "."
442 for _, key := range keys {
443 if strings.HasPrefix(strings.TrimLeft(key, " "), typekey) {
444 pti := strings.Split(strings.Trim(key, " "), typekey)[1]
445 a1.Logger.Debug("pti %+v", pti)
446 policyTypeInstances = append(policyTypeInstances, models.PolicyInstanceID(pti))
450 if len(policyTypeInstances) == 0 {
451 a1.Logger.Debug("policy instance Not Present ")
454 a1.Logger.Debug("return : %+v", policyTypeInstances)
455 return policyTypeInstances, nil