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"
33 "github.com/santhosh-tekuri/jsonschema/v5"
38 a1PolicyPrefix = "a1.policy_type."
39 a1MediatorNs = "A1m_ns"
40 a1InstancePrefix = "a1.policy_instance."
43 var typeAlreadyError = errors.New("Policy Type already exists")
44 var InstanceAlreadyError = errors.New("Policy Instance already exists")
45 var typeMismatchError = errors.New("Policytype Mismatch")
46 var invalidJsonSchema = errors.New("Invalid Json ")
47 var policyInstanceNotFoundError = errors.New("Policy Instance Not Found")
48 var policyTypeNotFoundError = errors.New("Policy Type Not Found")
50 func (rh *Resthook) IsPolicyTypePresent(err error) bool {
51 return err == policyTypeNotFoundError
54 func (rh *Resthook) IsPolicyInstanceNotFound(err error) bool {
55 return err == policyInstanceNotFoundError
58 func (rh *Resthook) IsTypeAlready(err error) bool {
59 return err == typeAlreadyError
61 func (rh *Resthook) IsInstanceAlready(err error) bool {
62 return err == InstanceAlreadyError
64 func (rh *Resthook) IsTypeMismatch(err error) bool {
65 return err == typeMismatchError
68 func (rh *Resthook) IsValidJson(err error) bool {
69 return err == invalidJsonSchema
71 func NewResthook() *Resthook {
72 return createResthook(sdlgo.NewSyncStorage())
75 func createResthook(sdlInst iSdl) *Resthook {
81 func (rh *Resthook) GetAllPolicyType() []models.PolicyTypeID {
83 var policyTypeIDs []models.PolicyTypeID
85 keys, err := rh.db.GetAll("A1m_ns")
88 a1.Logger.Error("error in retrieving policy. err: %v", err)
91 a1.Logger.Debug("keys : %+v", keys)
93 for _, key := range keys {
94 if strings.HasPrefix(strings.TrimLeft(key, " "), a1PolicyPrefix) {
95 pti := strings.Split(strings.Trim(key, " "), a1PolicyPrefix)[1]
96 ptii, _ := strconv.ParseInt(pti, 10, 64)
97 policyTypeIDs = append(policyTypeIDs, models.PolicyTypeID(ptii))
101 a1.Logger.Debug("return : %+v", policyTypeIDs)
105 func (rh *Resthook) GetPolicyType(policyTypeId models.PolicyTypeID) *models.PolicyTypeSchema {
106 a1.Logger.Debug("GetPolicyType1")
108 var policytypeschema *models.PolicyTypeSchema
111 key := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
114 a1.Logger.Debug("key : %+v", key)
116 valmap, err := rh.db.Get(a1MediatorNs, keys[:])
118 a1.Logger.Debug("policytype map : ", valmap)
120 if len(valmap) == 0 {
121 a1.Logger.Error("policy type Not Present for policyid : %v", policyTypeId)
122 return policytypeschema
126 a1.Logger.Error("error in retrieving policy type. err: %v", err)
130 if valmap[key] == nil {
131 a1.Logger.Error("policy type Not Present for policyid : %v", policyTypeId)
132 return policytypeschema
135 a1.Logger.Debug("keysmap : %+v", valmap[key])
137 var item models.PolicyTypeSchema
138 valStr := fmt.Sprint(valmap[key])
140 a1.Logger.Debug("Policy type for %+v : %+v", key, valStr)
141 valkey := "`" + valStr + "`"
142 valToUnmarshall, err := strconv.Unquote(valkey)
144 a1.Logger.Error("unquote error : %+v", err)
148 a1.Logger.Debug("Policy type for %+v : %+v", key, string(valToUnmarshall))
150 errunm := json.Unmarshal([]byte(valToUnmarshall), &item)
152 a1.Logger.Debug(" Unmarshalled json : %+v", (errunm))
153 a1.Logger.Debug("Policy type Name : %v", (item.Name))
158 func (rh *Resthook) CreatePolicyType(policyTypeId models.PolicyTypeID, httprequest models.PolicyTypeSchema) error {
159 a1.Logger.Debug("CreatePolicyType function")
160 if policyTypeId != models.PolicyTypeID(*httprequest.PolicyTypeID) {
162 a1.Logger.Debug("Policytype Mismatch")
163 return typeMismatchError
165 key := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
166 a1.Logger.Debug("key %+v ", key)
167 if data, err := httprequest.MarshalBinary(); err == nil {
168 a1.Logger.Debug("Marshaled String : %+v", string(data))
169 success, err1 := rh.db.SetIfNotExists(a1MediatorNs, key, string(data))
170 a1.Logger.Info("success:%+v", success)
172 a1.Logger.Error("error :%+v", err1)
176 a1.Logger.Debug("Policy type %+v already exist", policyTypeId)
177 return typeAlreadyError
183 func toStringKeys(val interface{}) (interface{}, error) {
185 switch val := val.(type) {
186 case map[interface{}]interface{}:
187 m := make(map[string]interface{})
188 for k, v := range val {
191 return nil, errors.New("found non-string key")
193 m[k], err = toStringKeys(v)
200 var l = make([]interface{}, len(val))
201 for i, v := range val {
202 l[i], err = toStringKeys(v)
213 func validate(httpBodyString string, schemaString string) bool {
215 err := yaml.Unmarshal([]byte(httpBodyString), &m)
217 a1.Logger.Error("Unmarshal error : %+v", err)
219 m, err = toStringKeys(m)
221 a1.Logger.Error("Conversion to string error : %+v", err)
224 compiler := jsonschema.NewCompiler()
225 if err := compiler.AddResource("schema.json", strings.NewReader(schemaString)); err != nil {
226 a1.Logger.Error("string reader error : %+v", err)
229 schema, err := compiler.Compile("schema.json")
231 a1.Logger.Error("schema json compile error : %+v", err)
234 if err := schema.Validate(m); err != nil {
235 a1.Logger.Error("schema validation error : %+v", err)
238 a1.Logger.Debug("validation successfull")
242 func (rh *Resthook) StorePolicyInstance(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID, httpBody interface{}) (string, error) {
244 operation := "CREATE"
245 typekey := a1PolicyPrefix + strconv.FormatInt((int64(policyTypeId)), 10)
248 a1.Logger.Debug("key1 : %+v", typekey)
250 valmap, err := rh.db.Get(a1MediatorNs, keys[:])
252 a1.Logger.Error("policy type error : %+v", err)
254 a1.Logger.Debug("policytype map : %+v", valmap)
255 if valmap[typekey] == nil {
256 a1.Logger.Error("policy type Not Present for policyid : %v", policyTypeId)
257 return operation, policyTypeNotFoundError
259 // TODO : rmr creation_timestamp := time.Now() // will be needed for rmr to notify the creation of instance
261 instancekey := a1InstancePrefix + strconv.FormatInt((int64(policyTypeId)), 10) + "." + string(policyInstanceID)
263 instanceMap, err := rh.db.Get(a1MediatorNs, keys[:])
265 a1.Logger.Error("policy type error : %v", err)
267 a1.Logger.Debug("policyinstancetype map : %+v", instanceMap)
269 if instanceMap[instancekey] != nil {
271 a1.Logger.Debug("UPDATE")
272 data, _ := json.Marshal(httpBody)
273 a1.Logger.Debug("Marshaled String : %+v", string(data))
274 a1.Logger.Debug("key : %+v", instancekey)
275 success, err1 := rh.db.SetIf(a1MediatorNs, instancekey, instanceMap[instancekey], string(data))
277 a1.Logger.Error("error2 :%+v", err1)
278 return operation, err1
281 a1.Logger.Debug("Policy instance %+v already exist", policyInstanceID)
282 return operation, InstanceAlreadyError
285 data, _ := json.Marshal(httpBody)
286 a1.Logger.Debug("Marshaled String : %+v", string(data))
287 a1.Logger.Debug("key : %+v", instancekey)
289 var instance_map []interface{}
290 instance_map = append(instance_map, instancekey, string(data))
291 a1.Logger.Debug("policyinstancetype map : %+v", instance_map[1])
292 a1.Logger.Debug("policyinstancetype to create : %+v", instance_map)
294 err1 := rh.db.Set(a1MediatorNs, instancekey, string(data))
296 a1.Logger.Error("error1 :%+v", err1)
297 return operation, err1
300 a1.Logger.Debug("Policy Instance created ")
301 return operation, nil
304 func (rh *Resthook) CreatePolicyInstance(policyTypeId models.PolicyTypeID, policyInstanceID models.PolicyInstanceID, httpBody interface{}) error {
305 a1.Logger.Debug("CreatePolicyInstance function")
306 // validate the PUT against the schema
307 var policyTypeSchema *models.PolicyTypeSchema
308 policyTypeSchema = rh.GetPolicyType(policyTypeId)
309 schemaStr, err := json.Marshal(policyTypeSchema.CreateSchema)
311 a1.Logger.Error("Json Marshal error : %+v", err)
314 a1.Logger.Debug("schema to validate %+v", string(schemaStr))
315 a1.Logger.Debug("httpbody to validate %+v", httpBody)
316 schemaString := fmt.Sprint(string(schemaStr))
317 httpBodyString := fmt.Sprint((httpBody))
318 isvalid := validate(httpBodyString, schemaString)
320 operation, err := rh.StorePolicyInstance(policyTypeId, policyInstanceID, httpBody)
322 a1.Logger.Error("error :%+v", err)
325 a1.Logger.Debug("policy instance :%+v", operation)
327 a1.Logger.Error("%+v", invalidJsonSchema)
328 return invalidJsonSchema