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 "github.com/santhosh-tekuri/jsonschema/v5"
39 a1PolicyPrefix = "a1.policy_type."
40 a1MediatorNs = "A1m_ns"
41 a1InstancePrefix = "a1.policy_instance."
42 a1InstanceMetadataPrefix = "a1.policy_inst_metadata."
43 a1HandlerPrefix = "a1.policy_handler."
46 var typeAlreadyError = errors.New("Policy Type already exists")
47 var InstanceAlreadyError = errors.New("Policy Instance already exists")
48 var typeMismatchError = errors.New("Policytype Mismatch")
49 var invalidJsonSchema = errors.New("Invalid Json ")
50 var policyInstanceNotFoundError = errors.New("Policy Instance Not Found")
51 var policyTypeNotFoundError = errors.New("Policy Type Not Found")
53 func (rh *Resthook) IsPolicyTypePresent(err error) bool {
54 return err == policyTypeNotFoundError
57 func (rh *Resthook) IsPolicyInstanceNotFound(err error) bool {
58 return err == policyInstanceNotFoundError
61 func (rh *Resthook) IsTypeAlready(err error) bool {
62 return err == typeAlreadyError
64 func (rh *Resthook) IsInstanceAlready(err error) bool {
65 return err == InstanceAlreadyError
67 func (rh *Resthook) IsTypeMismatch(err error) bool {
68 return err == typeMismatchError
71 func (rh *Resthook) IsValidJson(err error) bool {
72 return err == invalidJsonSchema
74 func NewResthook() *Resthook {
75 return createResthook(sdlgo.NewSyncStorage())
78 func createResthook(sdlInst iSdl) *Resthook {
84 func (rh *Resthook) GetAllPolicyType() []models.PolicyTypeID {
86 var policyTypeIDs []models.PolicyTypeID
88 keys, err := rh.db.GetAll("A1m_ns")
91 a1.Logger.Error("error in retrieving policy. err: %v", err)
94 a1.Logger.Debug("keys : %+v", keys)
96 for _, key := range keys {
97 if strings.HasPrefix(strings.TrimLeft(key, " "), a1PolicyPrefix) {
98 pti := strings.Split(strings.Trim(key, " "), a1PolicyPrefix)[1]
99 ptii, _ := strconv.ParseInt(pti, 10, 64)
100 policyTypeIDs = append(policyTypeIDs, models.PolicyTypeID(ptii))
104 a1.Logger.Debug("return : %+v", policyTypeIDs)
108 func (rh *Resthook) GetPolicyType(policyTypeId models.PolicyTypeID) *models.PolicyTypeSchema {
109 a1.Logger.Debug("GetPolicyType1")
111 var policytypeschema *models.PolicyTypeSchema
114 key := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
117 a1.Logger.Debug("key : %+v", key)
119 valmap, err := rh.db.Get(a1MediatorNs, keys[:])
121 a1.Logger.Debug("policytype map : %+v", valmap)
123 if len(valmap) == 0 {
124 a1.Logger.Error("policy type Not Present for policyid : %v", policyTypeId)
125 return policytypeschema
129 a1.Logger.Error("error in retrieving policy type. err: %v", err)
133 if valmap[key] == nil {
134 a1.Logger.Error("policy type Not Present for policyid : %v", policyTypeId)
135 return policytypeschema
138 a1.Logger.Debug("keysmap : %+v", valmap[key])
140 var item models.PolicyTypeSchema
141 valStr := fmt.Sprint(valmap[key])
143 a1.Logger.Debug("Policy type for %+v : %+v", key, valStr)
144 valkey := "`" + valStr + "`"
145 valToUnmarshall, err := strconv.Unquote(valkey)
147 a1.Logger.Error("unquote error : %+v", err)
151 a1.Logger.Debug("Policy type for %+v : %+v", key, string(valToUnmarshall))
153 errunm := json.Unmarshal([]byte(valToUnmarshall), &item)
155 a1.Logger.Debug(" Unmarshalled json : %+v", (errunm))
156 a1.Logger.Debug("Policy type Name : %v", (item.Name))
161 func (rh *Resthook) CreatePolicyType(policyTypeId models.PolicyTypeID, httprequest models.PolicyTypeSchema) error {
162 a1.Logger.Debug("CreatePolicyType function")
163 if policyTypeId != models.PolicyTypeID(*httprequest.PolicyTypeID) {
165 a1.Logger.Debug("Policytype Mismatch")
166 return typeMismatchError
168 key := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
169 a1.Logger.Debug("key %+v ", key)
170 if data, err := httprequest.MarshalBinary(); err == nil {
171 a1.Logger.Debug("Marshaled String : %+v", string(data))
172 success, err1 := rh.db.SetIfNotExists(a1MediatorNs, key, string(data))
173 a1.Logger.Info("success:%+v", success)
175 a1.Logger.Error("error :%+v", err1)
179 a1.Logger.Debug("Policy type %+v already exist", policyTypeId)
180 return typeAlreadyError
186 func toStringKeys(val interface{}) (interface{}, error) {
188 switch val := val.(type) {
189 case map[interface{}]interface{}:
190 m := make(map[string]interface{})
191 for k, v := range val {
194 return nil, errors.New("found non-string key")
196 m[k], err = toStringKeys(v)
203 var l = make([]interface{}, len(val))
204 for i, v := range val {
205 l[i], err = toStringKeys(v)
216 var validate(httpBodyString string, schemaString string) bool {
218 err := yaml.Unmarshal([]byte(httpBodyString), &m)
220 a1.Logger.Error("Unmarshal error : %+v", err)
222 m, err = toStringKeys(m)
224 a1.Logger.Error("Conversion to string error : %+v", err)
227 compiler := jsonschema.NewCompiler()
228 if err := compiler.AddResource("schema.json", strings.NewReader(schemaString)); err != nil {
229 a1.Logger.Error("string reader error : %+v", err)
232 schema, err := compiler.Compile("schema.json")
234 a1.Logger.Error("schema json compile error : %+v", err)
237 if err := schema.Validate(m); err != nil {
238 a1.Logger.Error("schema validation error : %+v", err)
241 a1.Logger.Debug("validation successfull")
245 func (rh *Resthook) storePolicyInstance(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID, httpBody interface{}) (string, error) {
247 operation := "CREATE"
248 typekey := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
251 a1.Logger.Debug("key1 : %+v", typekey)
253 valmap, err := rh.db.Get(a1MediatorNs, keys[:])
255 a1.Logger.Error("policy type error : %+v", err)
257 a1.Logger.Debug("policytype map : %+v", valmap)
258 if valmap[typekey] == nil {
259 a1.Logger.Error("policy type Not Present for policyid : %v", policyTypeId)
260 return operation, policyTypeNotFoundError
262 // TODO : rmr creation_timestamp := time.Now() // will be needed for rmr to notify the creation of instance
264 instancekey := a1InstancePrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
266 instanceMap, err := rh.db.Get(a1MediatorNs, keys[:])
268 a1.Logger.Error("policy type error : %v", err)
270 a1.Logger.Debug("policyinstancetype map : %+v", instanceMap)
272 if instanceMap[instancekey] != nil {
274 a1.Logger.Debug("UPDATE")
275 data, _ := json.Marshal(httpBody)
276 a1.Logger.Debug("Marshaled String : %+v", string(data))
277 a1.Logger.Debug("key : %+v", instancekey)
278 success, err1 := rh.db.SetIf(a1MediatorNs, instancekey, instanceMap[instancekey], string(data))
280 a1.Logger.Error("error2 :%+v", err1)
281 return operation, err1
284 a1.Logger.Debug("Policy instance %+v already exist", policyInstanceID)
285 return operation, InstanceAlreadyError
288 data, _ := json.Marshal(httpBody)
289 a1.Logger.Debug("Marshaled String : %+v", string(data))
290 a1.Logger.Debug("key : %+v", instancekey)
292 var instance_map []interface{}
293 instance_map = append(instance_map, instancekey, string(data))
294 a1.Logger.Debug("policyinstancetype map : %+v", instance_map[1])
295 a1.Logger.Debug("policyinstancetype to create : %+v", instance_map)
297 err1 := rh.db.Set(a1MediatorNs, instancekey, string(data))
299 a1.Logger.Error("error1 :%+v", err1)
300 return operation, err1
303 a1.Logger.Debug("Policy Instance created ")
304 return operation, nil
307 func (rh *Resthook) storePolicyInstanceMetadata(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) (bool, error) {
309 creation_timestamp := time.Now()
310 instanceMetadataKey := a1InstanceMetadataPrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
312 a1.Logger.Debug("key : %+v", instanceMetadataKey)
314 var metadatajson []interface{}
315 metadatajson = append(metadatajson, map[string]string{"created_at": creation_timestamp.Format("2006-01-02 15:04:05"), "has_been_deleted": "False"})
316 metadata, _ := json.Marshal(metadatajson)
318 a1.Logger.Debug("policyinstanceMetaData to create : %+v", string(metadata))
320 err := rh.db.Set(a1MediatorNs, instanceMetadataKey, string(metadata))
323 a1.Logger.Error("error :%+v", err)
327 a1.Logger.Debug("Policy Instance Meta Data created at :%+v", creation_timestamp)
332 func (rh *Resthook) CreatePolicyInstance(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID, httpBody interface{}) error {
333 a1.Logger.Debug("CreatePolicyInstance function")
334 // validate the PUT against the schema
335 var policyTypeSchema *models.PolicyTypeSchema
336 policyTypeSchema = rh.GetPolicyType(policyTypeId)
337 schemaStr, err := json.Marshal(policyTypeSchema.CreateSchema)
339 a1.Logger.Error("Json Marshal error : %+v", err)
342 a1.Logger.Debug("schema to validate %+v", string(schemaStr))
343 a1.Logger.Debug("httpbody to validate %+v", httpBody)
344 schemaString := fmt.Sprint(string(schemaStr))
345 httpBodyMarshal, err := json.Marshal(httpBody)
346 httpBodyString := string((httpBodyMarshal))
347 a1.Logger.Debug("schema to validate sprint %+v", (schemaString))
348 a1.Logger.Debug("httpbody to validate sprint %+v", httpBodyString)
349 isvalid := validate(httpBodyString, schemaString)
352 operation, err = rh.storePolicyInstance(policyTypeId, policyInstanceID, httpBody)
354 a1.Logger.Error("error :%+v", err)
357 a1.Logger.Debug("policy instance :%+v", operation)
358 iscreated, errmetadata := rh.storePolicyInstanceMetadata(policyTypeId, policyInstanceID)
359 if errmetadata != nil {
360 a1.Logger.Error("error :%+v", errmetadata)
364 a1.Logger.Debug("policy instance metadata created")
367 a1.Logger.Error("%+v", invalidJsonSchema)
368 return invalidJsonSchema
374 func (rh *Resthook) GetPolicyInstance(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) (interface{}, error) {
375 a1.Logger.Debug("GetPolicyInstance1")
379 typekey := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
382 a1.Logger.Debug("key1 : %+v", typekey)
384 valmap, err := rh.db.Get(a1MediatorNs, keys[:])
385 if len(valmap) == 0 {
386 a1.Logger.Debug("policy type Not Present for policyid : %v", policyTypeId)
387 return "{}", policyTypeNotFoundError
391 a1.Logger.Error("error in retrieving policy type. err: %v", err)
395 if valmap[typekey] == nil {
396 a1.Logger.Debug("policy type Not Present for policyid : %v", policyTypeId)
397 return "{}", policyTypeNotFoundError
400 a1.Logger.Debug("keysmap : %+v", valmap[typekey])
402 instancekey := a1InstancePrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
403 a1.Logger.Debug("key2 : %+v", instancekey)
404 keys[0] = instancekey
405 instanceMap, err := rh.db.Get(a1MediatorNs, keys[:])
407 a1.Logger.Error("policy instance error : %v", err)
409 a1.Logger.Debug("policyinstancetype map : %+v", instanceMap)
411 if instanceMap[instancekey] == nil {
412 a1.Logger.Debug("policy instance Not Present for policyinstaneid : %v", policyInstanceID)
413 return "{}", policyInstanceNotFoundError
416 valStr := fmt.Sprint(instanceMap[instancekey])
420 func (rh *Resthook) GetAllPolicyInstance(policyTypeId models.PolicyTypeID) ([]models.PolicyInstanceID, error) {
421 a1.Logger.Debug("GetAllPolicyInstance")
422 var policyTypeInstances = []models.PolicyInstanceID{}
424 keys, err := rh.db.GetAll("A1m_ns")
427 a1.Logger.Error("error in retrieving policy. err: %v", err)
428 return policyTypeInstances, err
430 a1.Logger.Debug("keys : %+v", keys)
431 typekey := a1InstancePrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "."
433 for _, key := range keys {
434 if strings.HasPrefix(strings.TrimLeft(key, " "), typekey) {
435 pti := strings.Split(strings.Trim(key, " "), typekey)[1]
436 a1.Logger.Debug("pti %+v", pti)
437 policyTypeInstances = append(policyTypeInstances, models.PolicyInstanceID(pti))
441 if len(policyTypeInstances) == 0 {
442 a1.Logger.Debug("policy instance Not Present ")
445 a1.Logger.Debug("return : %+v", policyTypeInstances)
446 return policyTypeInstances, nil