Fetch RIC active alarms via O1
[ric-plt/o1.git] / agent / pkg / sbi / sbi.go
1 /*
2 ==================================================================================
3   Copyright (c) 2019 AT&T Intellectual Property.
4   Copyright (c) 2019 Nokia
5
6    Licensed under the Apache License, Version 2.0 (the "License");
7    you may not use this file except in compliance with the License.
8    You may obtain a copy of the License at
9
10        http://www.apache.org/licenses/LICENSE-2.0
11
12    Unless required by applicable law or agreed to in writing, software
13    distributed under the License is distributed on an "AS IS" BASIS,
14    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15    See the License for the specific language governing permissions and
16    limitations under the License.
17 ==================================================================================
18 */
19
20 package sbi
21
22 import (
23         "bytes"
24         "fmt"
25         httptransport "github.com/go-openapi/runtime/client"
26         "github.com/go-openapi/strfmt"
27         "os/exec"
28         "regexp"
29         "strings"
30         "time"
31
32         clientruntime "github.com/go-openapi/runtime/client"
33         "github.com/prometheus/alertmanager/api/v2/client"
34         "github.com/prometheus/alertmanager/api/v2/client/alert"
35
36         apiclient "gerrit.oran-osc.org/r/ric-plt/o1mediator/pkg/appmgrclient"
37         apixapp "gerrit.oran-osc.org/r/ric-plt/o1mediator/pkg/appmgrclient/xapp"
38         apimodel "gerrit.oran-osc.org/r/ric-plt/o1mediator/pkg/appmgrmodel"
39
40         "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
41
42 )
43
44 type PodStatus struct {
45         Name   string
46         Health string
47         Status string
48 }
49
50 var log = xapp.Logger
51
52 func NewSBIClient(appmgrAddr, alertmgrAddr string, timo int) *SBIClient {
53         return &SBIClient{appmgrAddr, alertmgrAddr, time.Duration(timo) * time.Second}
54 }
55
56 func (s *SBIClient) CreateTransport(host string) *apiclient.RICAppmgr {
57         return apiclient.New(httptransport.New(host, "/ric/v1/", []string{"http"}), strfmt.Default)
58 }
59
60 func (s *SBIClient) BuildXappDescriptor(name, namespace, release, version string) *apimodel.XappDescriptor {
61         return &apimodel.XappDescriptor{
62                 XappName:    &name,
63                 HelmVersion: version,
64                 ReleaseName: release,
65                 Namespace:   namespace,
66         }
67 }
68
69 func (s *SBIClient) DeployXapp(xappDesc *apimodel.XappDescriptor) error {
70         params := apixapp.NewDeployXappParamsWithTimeout(s.timeout).WithXappDescriptor(xappDesc)
71         log.Info("SBI: DeployXapp=%v", params)
72
73         result, err := s.CreateTransport(s.appmgrAddr).Xapp.DeployXapp(params)
74         if err != nil {
75                 log.Error("SBI: DeployXapp unsuccessful: %v", err)
76         } else {
77                 log.Info("SBI: DeployXapp successful: payload=%v", result.Payload)
78         }
79         return err
80 }
81
82 func (s *SBIClient) UndeployXapp(xappDesc *apimodel.XappDescriptor) error {
83         name := *xappDesc.XappName
84         if xappDesc.ReleaseName != "" {
85                 name = xappDesc.ReleaseName
86         }
87
88         params := apixapp.NewUndeployXappParamsWithTimeout(s.timeout).WithXAppName(name)
89         log.Info("SBI: UndeployXapp=%v", params)
90
91         result, err := s.CreateTransport(s.appmgrAddr).Xapp.UndeployXapp(params)
92         if err != nil {
93                 log.Error("SBI: UndeployXapp unsuccessful: %v", err)
94         } else {
95                 log.Info("SBI: UndeployXapp successful: payload=%v", result)
96         }
97         return err
98 }
99
100 func (s *SBIClient) GetDeployedXapps() error {
101         params := apixapp.NewGetAllXappsParamsWithTimeout(s.timeout)
102         result, err := s.CreateTransport(s.appmgrAddr).Xapp.GetAllXapps(params)
103         if err != nil {
104                 log.Error("GET unsuccessful: %v", err)
105         } else {
106                 log.Info("GET successful: payload=%v", result.Payload)
107         }
108         return err
109 }
110
111 func (s *SBIClient) BuildXappConfig(name, namespace string, configData interface{}) *apimodel.XAppConfig {
112         metadata := &apimodel.ConfigMetadata{
113                 XappName:  &name,
114                 Namespace: &namespace,
115         }
116
117         return &apimodel.XAppConfig{
118                 Metadata: metadata,
119                 Config:   configData,
120         }
121 }
122
123 func (s *SBIClient) ModifyXappConfig(xappConfig *apimodel.XAppConfig) error {
124         params := apixapp.NewModifyXappConfigParamsWithTimeout(s.timeout).WithXAppConfig(xappConfig)
125         result, err := s.CreateTransport(s.appmgrAddr).Xapp.ModifyXappConfig(params)
126         if err != nil {
127                 log.Error("SBI: ModifyXappConfig unsuccessful: %v", err)
128         } else {
129                 log.Info("SBI: ModifyXappConfig successful: payload=%v", result.Payload)
130         }
131         return err
132 }
133
134 func (s *SBIClient) GetAllPodStatus(namespace string) ([]PodStatus, error) {
135         output, err := s.RunCommand(fmt.Sprintf("/usr/local/bin/kubectl get pod -n %s", namespace))
136         if err != nil {
137                 return []PodStatus{}, err
138         }
139
140         podStatusList := []PodStatus{}
141         var readyStr string
142         re := regexp.MustCompile(fmt.Sprintf(`%s-.*`, namespace))
143         podList := re.FindAllStringSubmatch(string(output), -1)
144         if podList != nil {
145                 for _, pod := range podList {
146                         p := PodStatus{}
147                         fmt.Sscanf(pod[0], "%s %s %s", &p.Name, &readyStr, &p.Status)
148                         p.Name = strings.Split(p.Name, "-")[1]
149                         p.Health = s.GetHealthState(readyStr)
150
151                         podStatusList = append(podStatusList, p)
152                 }
153         }
154         return podStatusList, nil
155 }
156
157 func (s *SBIClient) GetHealthState(ready string) (state string) {
158         result := strings.Split(ready, "/")
159         if len(result) < 2 {
160                 return "unavailable"
161         }
162
163         if result[0] == result[1] {
164                 state = "healthy"
165         } else {
166                 state = "unhealthy"
167         }
168         return
169 }
170
171 func (s *SBIClient) RunCommand(args string) (string, error) {
172         return CommandExec(args)
173 }
174
175 var CommandExec = func(args string) (string, error) {
176         cmd := exec.Command("/bin/sh", "-c", args)
177         var stdout bytes.Buffer
178         var stderr bytes.Buffer
179         cmd.Stdout = &stdout
180         cmd.Stderr = &stderr
181
182         xapp.Logger.Debug("Running command: '%s'", cmd)
183         if err := cmd.Run(); err != nil {
184                 xapp.Logger.Error("Command failed (%s): %v - %s", cmd, err.Error(), stderr.String())
185                 return "", err
186         }
187         xapp.Logger.Debug("Command executed successfully!")
188         return stdout.String(), nil
189 }
190
191 func (s *SBIClient) GetAlerts() (*alert.GetAlertsOK, error) {
192         xapp.Logger.Info("Fetching alerts ...")
193
194         cr := clientruntime.New(s.alertmgrAddr, "/api/v2", []string{"http"})
195         resp, err := client.New(cr, strfmt.Default).Alert.GetAlerts(nil)
196         if err != nil {
197                 xapp.Logger.Error("Fetching alerts failed with error: %v", err)
198                 return nil, err
199         }
200
201         return resp, nil
202 }