1 // SPDX-License-Identifier: Apache-2.0
2 // Copyright (c) 2020 Intel Corporation
10 "github.com/open-ness/EMCO/src/orchestrator/pkg/infra/db"
11 log "github.com/open-ness/EMCO/src/orchestrator/pkg/infra/logutils"
12 rpc "github.com/open-ness/EMCO/src/orchestrator/pkg/infra/rpc"
13 mtypes "github.com/open-ness/EMCO/src/orchestrator/pkg/module/types"
14 pkgerrors "github.com/pkg/errors"
17 // Controller contains the parameters needed for Controllers
18 // It implements the interface for managing the Controllers
19 type Controller struct {
20 Metadata mtypes.Metadata `json:"metadata"`
21 Spec ControllerSpec `json:"spec"`
24 type ControllerSpec struct {
25 Host string `json:"host"`
26 Port int `json:"port"`
27 Type string `json:"type"`
28 Priority int `json:"priority"`
31 const MinControllerPriority = 1
32 const MaxControllerPriority = 1000000
33 const CONTROLLER_TYPE_ACTION string = "action"
34 const CONTROLLER_TYPE_PLACEMENT string = "placement"
36 var CONTROLLER_TYPES = [...]string{CONTROLLER_TYPE_ACTION, CONTROLLER_TYPE_PLACEMENT}
38 // ControllerKey is the key structure that is used in the database
39 type ControllerKey struct {
40 ControllerName string `json:"controller-name"`
43 // We will use json marshalling to convert to string to
44 // preserve the underlying structure.
45 func (mk ControllerKey) String() string {
46 out, err := json.Marshal(mk)
54 // ControllerManager is an interface exposes the Controller functionality
55 type ControllerManager interface {
56 CreateController(ms Controller, mayExist bool) (Controller, error)
57 GetController(name string) (Controller, error)
58 GetControllers() ([]Controller, error)
60 DeleteController(name string) error
63 // ControllerClient implements the Manager
64 // It will also be used to maintain some localized state
65 type ControllerClient struct {
70 // NewControllerClient returns an instance of the ControllerClient
71 // which implements the Manager
72 func NewControllerClient() *ControllerClient {
73 return &ControllerClient{
74 collectionName: "controller",
75 tagMeta: "controllermetadata",
79 // CreateController a new collection based on the Controller
80 func (mc *ControllerClient) CreateController(m Controller, mayExist bool) (Controller, error) {
82 log.Info("CreateController .. start", log.Fields{"Controller": m, "exists": mayExist})
84 //Construct the composite key to select the entry
86 ControllerName: m.Metadata.Name,
89 //Check if this Controller already exists
90 _, err := mc.GetController(m.Metadata.Name)
91 if err == nil && !mayExist {
92 return Controller{}, pkgerrors.New("Controller already exists")
95 err = db.DBconn.Insert(mc.collectionName, key, nil, mc.tagMeta, m)
97 return Controller{}, pkgerrors.Wrap(err, "Creating DB Entry")
100 // send message to create/update the rpc connection
101 rpc.UpdateRpcConn(m.Metadata.Name, m.Spec.Host, m.Spec.Port)
103 log.Info("CreateController .. end", log.Fields{"Controller": m, "exists": mayExist})
107 // GetController returns the Controller for corresponding name
108 func (mc *ControllerClient) GetController(name string) (Controller, error) {
110 //Construct the composite key to select the entry
111 key := ControllerKey{
112 ControllerName: name,
114 value, err := db.DBconn.Find(mc.collectionName, key, mc.tagMeta)
116 return Controller{}, pkgerrors.Wrap(err, "db Find error")
117 } else if len(value) == 0 {
118 return Controller{}, pkgerrors.New("Controller not found")
122 microserv := Controller{}
123 err = db.DBconn.Unmarshal(value[0], µserv)
125 return Controller{}, pkgerrors.Wrap(err, "Unmarshaling Value")
127 return microserv, nil
130 return Controller{}, pkgerrors.New("Error getting Controller")
133 // GetControllers returns all the Controllers that are registered
134 func (mc *ControllerClient) GetControllers() ([]Controller, error) {
136 //Construct the composite key to select the entry
137 key := ControllerKey{
141 var resp []Controller
142 values, err := db.DBconn.Find(mc.collectionName, key, mc.tagMeta)
144 return []Controller{}, pkgerrors.Wrap(err, "db Find error")
147 for _, value := range values {
148 microserv := Controller{}
149 err = db.DBconn.Unmarshal(value, µserv)
151 return []Controller{}, pkgerrors.Wrap(err, "Unmarshaling Value")
154 resp = append(resp, microserv)
160 // DeleteController the Controller from database
161 func (mc *ControllerClient) DeleteController(name string) error {
163 //Construct the composite key to select the entry
164 key := ControllerKey{
165 ControllerName: name,
167 err := db.DBconn.Remove(mc.collectionName, key)
169 if strings.Contains(err.Error(), "Error finding:") {
170 return pkgerrors.Wrap(err, "db Remove error - not found")
171 } else if strings.Contains(err.Error(), "Can't delete parent without deleting child") {
172 return pkgerrors.Wrap(err, "db Remove error - conflict")
174 return pkgerrors.Wrap(err, "db Remove error - general")
178 // send message to close rpc connection
179 rpc.RemoveRpcConn(name)
184 // InitControllers initializes connctions for controllers in the DB
185 func (mc *ControllerClient) InitControllers() {
186 vals, _ := mc.GetControllers()
187 for _, v := range vals {
188 log.Info("Initializing RPC connection for controller", log.Fields{
189 "Controller": v.Metadata.Name,
191 rpc.UpdateRpcConn(v.Metadata.Name, v.Spec.Host, v.Spec.Port)