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 ==================================================================================
30 "gerrit.o-ran-sc.org/r/ric-plt/a1/pkg/a1"
31 "gerrit.o-ran-sc.org/r/ric-plt/a1/pkg/models"
32 "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 : ", 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
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 httpBodyString := fmt.Sprint((httpBody))
348 isvalid := validate(httpBodyString, schemaString)
351 operation, err = rh.StorePolicyInstance(policyTypeId, policyInstanceID, httpBody)
353 a1.Logger.Error("error :%+v", err)
356 a1.Logger.Debug("policy instance :%+v", operation)
357 iscreated,errmetadata := rh.StorePolicyInstanceMetadata(policyTypeId, policyInstanceID)
358 if errmetadata != nil {
359 a1.Logger.Error("error :%+v", errmetadata)
363 a1.Logger.Debug("policy instance metadata created")
366 a1.Logger.Error("%+v", invalidJsonSchema)
367 return invalidJsonSchema
373 func (rh *Resthook) GetPolicyInstance(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID) (interface{}, error) {
374 a1.Logger.Debug("GetPolicyInstance1")
378 typekey := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
381 a1.Logger.Debug("key1 : %+v", typekey)
383 valmap, err := rh.db.Get(a1MediatorNs, keys[:])
384 if len(valmap) == 0 {
385 a1.Logger.Debug("policy type Not Present for policyid : %v", policyTypeId)
386 return "{}", policyTypeNotFoundError
390 a1.Logger.Error("error in retrieving policy type. err: %v", err)
394 if valmap[typekey] == nil {
395 a1.Logger.Debug("policy type Not Present for policyid : %v", policyTypeId)
396 return "{}", policyTypeNotFoundError
399 a1.Logger.Debug("keysmap : %+v", valmap[typekey])
401 instancekey := a1InstancePrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
402 a1.Logger.Debug("key2 : %+v", instancekey)
403 keys[0] = instancekey
404 instanceMap, err := rh.db.Get(a1MediatorNs, keys[:])
406 a1.Logger.Error("policy instance error : %v", err)
408 a1.Logger.Debug("policyinstancetype map : %+v", instanceMap)
410 if instanceMap[instancekey] == nil {
411 a1.Logger.Debug("policy instance Not Present for policyinstaneid : %v", policyInstanceID)
412 return "{}", policyInstanceNotFoundError
415 valStr := fmt.Sprint(instanceMap[instancekey])
419 func (rh *Resthook) GetAllPolicyInstance(policyTypeId models.PolicyTypeID) []models.PolicyInstanceID ,error {
420 a1.Logger.Debug("GetAllPolicyInstance")
421 var policyTypeInstances = []models.PolicyInstanceID{}
423 keys, err := rh.db.GetAll("A1m_ns")
426 a1.Logger.Error("error in retrieving policy. err: %v", err)
427 return policyTypeInstances ,err
429 a1.Logger.Debug("keys : %+v", keys)
430 typekey := a1InstancePrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "."
432 for _, key := range keys {
433 if strings.HasPrefix(strings.TrimLeft(key, " "), typekey) {
434 pti := strings.Split(strings.Trim(key, " "), typekey)[1]
435 a1.Logger.Debug("pti %+v", pti)
436 policyTypeInstances = append(policyTypeInstances, models.PolicyInstanceID(pti))
440 if len(policyTypeInstances)==0{
441 a1.Logger.Debug("policy instance Not Present ")
444 a1.Logger.Debug("return : %+v", policyTypeInstances)
445 return policyTypeInstances ,nil