ffb7f42441309f4e06919313d1c57b1ed548857c
[icn/sdwan.git] /
1 // SPDX-License-Identifier: Apache-2.0\r
2 // Copyright (c) 2020 Intel Corporation\r
3 \r
4 package controller\r
5 \r
6 import (\r
7         "encoding/json"\r
8 \r
9         "github.com/open-ness/EMCO/src/orchestrator/pkg/infra/db"\r
10         log "github.com/open-ness/EMCO/src/orchestrator/pkg/infra/logutils"\r
11         rpc "github.com/open-ness/EMCO/src/orchestrator/pkg/infra/rpc"\r
12         mtypes "github.com/open-ness/EMCO/src/orchestrator/pkg/module/types"\r
13         pkgerrors "github.com/pkg/errors"\r
14 )\r
15 \r
16 // Controller contains the parameters needed for Controllers\r
17 // It implements the interface for managing the Controllers\r
18 type Controller struct {\r
19         Metadata mtypes.Metadata `json:"metadata"`\r
20         Spec     ControllerSpec  `json:"spec"`\r
21 }\r
22 \r
23 type ControllerSpec struct {\r
24         Host     string `json:"host"`\r
25         Port     int    `json:"port"`\r
26         Type     string `json:"type"`\r
27         Priority int    `json:"priority"`\r
28 }\r
29 \r
30 const MinControllerPriority = 1\r
31 const MaxControllerPriority = 1000000\r
32 const CONTROLLER_TYPE_ACTION string = "action"\r
33 const CONTROLLER_TYPE_PLACEMENT string = "placement"\r
34 \r
35 var CONTROLLER_TYPES = [...]string{CONTROLLER_TYPE_ACTION, CONTROLLER_TYPE_PLACEMENT}\r
36 \r
37 // ControllerKey is the key structure that is used in the database\r
38 type ControllerKey struct {\r
39         ControllerName string `json:"controller-name"`\r
40 }\r
41 \r
42 // We will use json marshalling to convert to string to\r
43 // preserve the underlying structure.\r
44 func (mk ControllerKey) String() string {\r
45         out, err := json.Marshal(mk)\r
46         if err != nil {\r
47                 return ""\r
48         }\r
49 \r
50         return string(out)\r
51 }\r
52 \r
53 // ControllerManager is an interface exposes the Controller functionality\r
54 type ControllerManager interface {\r
55         CreateController(ms Controller, mayExist bool) (Controller, error)\r
56         GetController(name string) (Controller, error)\r
57         GetControllers() ([]Controller, error)\r
58         InitControllers()\r
59         DeleteController(name string) error\r
60 }\r
61 \r
62 // ControllerClient implements the Manager\r
63 // It will also be used to maintain some localized state\r
64 type ControllerClient struct {\r
65         collectionName string\r
66         tagMeta        string\r
67 }\r
68 \r
69 // NewControllerClient returns an instance of the ControllerClient\r
70 // which implements the Manager\r
71 func NewControllerClient() *ControllerClient {\r
72         return &ControllerClient{\r
73                 collectionName: "controller",\r
74                 tagMeta:        "controllermetadata",\r
75         }\r
76 }\r
77 \r
78 // CreateController a new collection based on the Controller\r
79 func (mc *ControllerClient) CreateController(m Controller, mayExist bool) (Controller, error) {\r
80 \r
81         //Construct the composite key to select the entry\r
82         key := ControllerKey{\r
83                 ControllerName: m.Metadata.Name,\r
84         }\r
85 \r
86         //Check if this Controller already exists\r
87         _, err := mc.GetController(m.Metadata.Name)\r
88         if err == nil && !mayExist {\r
89                 return Controller{}, pkgerrors.New("Controller already exists")\r
90         }\r
91 \r
92         err = db.DBconn.Insert(mc.collectionName, key, nil, mc.tagMeta, m)\r
93         if err != nil {\r
94                 return Controller{}, pkgerrors.Wrap(err, "Creating DB Entry")\r
95         }\r
96 \r
97         // send message to create/update the  rpc connection\r
98         rpc.UpdateRpcConn(m.Metadata.Name, m.Spec.Host, m.Spec.Port)\r
99 \r
100         return m, nil\r
101 }\r
102 \r
103 // GetController returns the Controller for corresponding name\r
104 func (mc *ControllerClient) GetController(name string) (Controller, error) {\r
105 \r
106         //Construct the composite key to select the entry\r
107         key := ControllerKey{\r
108                 ControllerName: name,\r
109         }\r
110         value, err := db.DBconn.Find(mc.collectionName, key, mc.tagMeta)\r
111         if err != nil {\r
112                 return Controller{}, pkgerrors.Wrap(err, "Get Controller")\r
113         }\r
114 \r
115         if value != nil {\r
116                 microserv := Controller{}\r
117                 err = db.DBconn.Unmarshal(value[0], &microserv)\r
118                 if err != nil {\r
119                         return Controller{}, pkgerrors.Wrap(err, "Unmarshaling Value")\r
120                 }\r
121                 return microserv, nil\r
122         }\r
123 \r
124         return Controller{}, pkgerrors.New("Error getting Controller")\r
125 }\r
126 \r
127 // GetControllers returns all the  Controllers that are registered\r
128 func (mc *ControllerClient) GetControllers() ([]Controller, error) {\r
129 \r
130         //Construct the composite key to select the entry\r
131         key := ControllerKey{\r
132                 ControllerName: "",\r
133         }\r
134 \r
135         var resp []Controller\r
136         values, err := db.DBconn.Find(mc.collectionName, key, mc.tagMeta)\r
137         if err != nil {\r
138                 return []Controller{}, pkgerrors.Wrap(err, "Get Controller")\r
139         }\r
140 \r
141         for _, value := range values {\r
142                 microserv := Controller{}\r
143                 err = db.DBconn.Unmarshal(value, &microserv)\r
144                 if err != nil {\r
145                         return []Controller{}, pkgerrors.Wrap(err, "Unmarshaling Value")\r
146                 }\r
147 \r
148                 resp = append(resp, microserv)\r
149         }\r
150 \r
151         return resp, nil\r
152 }\r
153 \r
154 // DeleteController the  Controller from database\r
155 func (mc *ControllerClient) DeleteController(name string) error {\r
156 \r
157         //Construct the composite key to select the entry\r
158         key := ControllerKey{\r
159                 ControllerName: name,\r
160         }\r
161         err := db.DBconn.Remove(mc.collectionName, key)\r
162         if err != nil {\r
163                 return pkgerrors.Wrap(err, "Delete Controller Entry;")\r
164         }\r
165 \r
166         // send message to close rpc connection\r
167         rpc.RemoveRpcConn(name)\r
168 \r
169         return nil\r
170 }\r
171 \r
172 // InitControllers initializes connctions for controllers in the DB\r
173 func (mc *ControllerClient) InitControllers() {\r
174         vals, _ := mc.GetControllers()\r
175         for _, v := range vals {\r
176                 log.Info("Initializing RPC connection for controller", log.Fields{\r
177                         "Controller": v.Metadata.Name,\r
178                 })\r
179                 rpc.UpdateRpcConn(v.Metadata.Name, v.Spec.Host, v.Spec.Port)\r
180         }\r
181 }\r