--- /dev/null
+/*
+==================================================================================
+ Copyright (c) 2019 AT&T Intellectual Property.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================================
+*/
+package main
+
+import "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
+import "encoding/json"
+import "strconv"
+
+
+type robotPolicy struct {
+ Message string `json:"message"`
+}
+
+type A1Policy struct {
+ Operation string `json:"operation"`
+ Type int `json:"policy_type_id"`
+ Instance string `json:"policy_instance_id"`
+ Payload robotPolicy `json:"payload"`
+}
+
+type A1Response struct {
+ Type int `json:"policy_type_id"`
+ Instance string `json:"policy_instance_id"`
+ Handler string `json:"handler_id"`
+ Status string `json:"status"`
+}
+
+type robotXApp struct {
+ metrics map[string]xapp.Counter
+}
+
+func sdlKey(t int, i string) (key string) {
+ return strconv.Itoa(t) +"|"+ i
+}
+
+func (r robotXApp) SendA1Response (t int, i string, handler string, status string) {
+ /* A1_POLICY_RESP, _ := xapp.Rmr.GetRicMessageId("A1_POLICY_RESP") */
+ A1_POLICY_RESP := 20011
+ msg, _ := json.Marshal(A1Response {
+ Type: t,
+ Instance: i,
+ Handler: handler,
+ Status: status,
+ })
+
+ xapp.Logger.Debug("Outgoing A1 Response %s (length %d)", string(msg), len(msg))
+ /* fixme: check response for errors */
+ xapp.Rmr.SendMsg(&xapp.RMRParams {
+ Mtype: A1_POLICY_RESP,
+ Payload: msg,
+ PayloadLen: len(msg),
+ Xid: "",
+ SubId: t,
+ })
+ r.metrics["MessagesSent"].Inc()
+}
+
+func (r robotXApp) CreatePolicy(t int, i string, policy robotPolicy) {
+ k := sdlKey(t, i)
+ err := xapp.Sdl.Store(k, policy.Message)
+ if err == nil {
+ xapp.Logger.Debug("Created instance %s of policy %d", i, t)
+ r.metrics["PolicyCreates"].Inc()
+ r.metrics["dbStores"].Inc()
+ r.SendA1Response(t, i, "robot", "OK")
+ } else {
+ xapp.Logger.Error("Failed to create DB record for instance %s of policy %d: %v", i, t, err)
+ r.metrics["dbStoreFailures"].Inc()
+ r.SendA1Response(t, i, "robot", "ERROR")
+ }
+}
+
+func (r robotXApp) DeletePolicy(t int, i string) {
+ k := sdlKey(t, i)
+
+ policies, _ := xapp.Sdl.Read(k)
+ existingPolicy, _ := policies[k]
+
+ if existingPolicy != nil {
+ err := xapp.Sdl.Delete([]string{k})
+ if err == nil {
+ xapp.Logger.Debug("Deleted instance %s of policy %d, old value: %s", i, t, existingPolicy)
+ r.metrics["PolicyDeletes"].Inc()
+ r.metrics["dbDeletes"].Inc()
+ r.SendA1Response(t, i, "robot", "DELETED")
+ } else {
+ xapp.Logger.Error("Failed to delete DB record for instance %s of policy %d: %v", i, t, err)
+ r.metrics["dbDeleteFailures"].Inc()
+ r.SendA1Response(t, i, "robot", "ERROR")
+ }
+ } else {
+ xapp.Logger.Error("Attempt to delete nonexistent instance %s of policy %d", i, t)
+ r.metrics["NonexistentPolicyDeletes"].Inc()
+ r.SendA1Response(t, i, "robot", "ERROR")
+ }
+}
+
+func (r robotXApp) Consume(msg *xapp.RMRParams) (err error) {
+ /* this is returning 0. will investigate and fix someday. */
+ /* A1_POLICY_REQ, _ := xapp.Rmr.GetRicMessageId("A1_POLICY_REQ") */
+ A1_POLICY_REQ := 20010
+
+ xapp.Logger.Debug("Message received - type=%d, Src=%s (%s), payload=%s",
+ msg.Mtype, xapp.Rmr.GetRicMessageName(msg.Mtype), msg.Src, string(msg.Payload))
+
+ /* this is bogus right now, but we'll eventually support more than one message
+ also, xapps really should handle messages in a separate goroutine, but there's
+ no real need in this one as we're not latency bound */
+ if msg.Mtype == A1_POLICY_REQ {
+ var a1Msg A1Policy
+ err := json.Unmarshal(msg.Payload, &a1Msg)
+
+ xapp.Logger.Debug("... Policy request - err=%v|op=%s|type=%d|instance=%s",
+ err, a1Msg.Operation, a1Msg.Type, a1Msg.Instance)
+ switch a1Msg.Operation {
+ case "CREATE":
+ go r.CreatePolicy(a1Msg.Type, a1Msg.Instance, a1Msg.Payload)
+ case "DELETE":
+ go r.DeletePolicy(a1Msg.Type, a1Msg.Instance)
+ }
+ }
+ return nil
+}
+
+func main() {
+ counters := []xapp.CounterOpts {
+ { Name: "PolicyCreates", Help: "A1 policies created" },
+ { Name: "DuplicatePolicyCreates",
+ Help: "A1 CREATE requests received for existing policy instances" },
+ { Name: "PolicyUpdates", Help: "A1 policies updateded" },
+ { Name: "NonexistentPolicyUpdates",
+ Help: "A1 UPDATE requests received for nonexistent policy instances" },
+ { Name: "PolicyDeletes", Help: "A1 policies deleted" },
+ { Name: "NonexistentPolicyDeletes",
+ Help: "A1 DELETE requests received for nonexistent policy instances" },
+ { Name: "dbStores",
+ Help: "SDL store requests" },
+ { Name: "dbStoreFailures",
+ Help: "SDL store request failures" },
+ { Name: "dbDeletes",
+ Help: "SDL delete requests" },
+ { Name: "dbDeleteFailures",
+ Help: "SDL delete request failures" },
+ { Name: "MessagesReceived",
+ Help: "Total RMR messages received" },
+ { Name: "MessagesSent",
+ Help: "Total RMR messages sent" },
+ }
+ xapp.Run(robotXApp{ metrics: xapp.Metric.RegisterCounterGroup(counters, "robotXApp")})
+}