a201f7f9aac6cad6066b34e466e455fb30265d0e
[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 type PodStatus struct {
44         Name   string
45         Health string
46         Status string
47 }
48
49 var log = xapp.Logger
50
51 func NewSBIClient(appmgrAddr, alertmgrAddr string, timo int) *SBIClient {
52         return &SBIClient{appmgrAddr, alertmgrAddr, time.Duration(timo) * time.Second}
53 }
54
55 func (s *SBIClient) CreateTransport(host string) *apiclient.RICAppmgr {
56         return apiclient.New(httptransport.New(host, "/ric/v1/", []string{"http"}), strfmt.Default)
57 }
58
59 func (s *SBIClient) BuildXappDescriptor(name, namespace, release, version string) *apimodel.XappDescriptor {
60         return &apimodel.XappDescriptor{
61                 XappName:    &name,
62                 HelmVersion: version,
63                 ReleaseName: release,
64                 Namespace:   namespace,
65         }
66 }
67
68 func (s *SBIClient) DeployXapp(xappDesc *apimodel.XappDescriptor) error {
69         params := apixapp.NewDeployXappParamsWithTimeout(s.timeout).WithXappDescriptor(xappDesc)
70         log.Info("SBI: DeployXapp=%v", params)
71
72         result, err := s.CreateTransport(s.appmgrAddr).Xapp.DeployXapp(params)
73         if err != nil {
74                 log.Error("SBI: DeployXapp unsuccessful: %v", err)
75         } else {
76                 log.Info("SBI: DeployXapp successful: payload=%v", result.Payload)
77         }
78         return err
79 }
80
81 func (s *SBIClient) UndeployXapp(xappDesc *apimodel.XappDescriptor) error {
82         name := *xappDesc.XappName
83         if xappDesc.ReleaseName != "" {
84                 name = xappDesc.ReleaseName
85         }
86
87         params := apixapp.NewUndeployXappParamsWithTimeout(s.timeout).WithXAppName(name)
88         log.Info("SBI: UndeployXapp=%v", params)
89
90         result, err := s.CreateTransport(s.appmgrAddr).Xapp.UndeployXapp(params)
91         if err != nil {
92                 log.Error("SBI: UndeployXapp unsuccessful: %v", err)
93         } else {
94                 log.Info("SBI: UndeployXapp successful: payload=%v", result)
95         }
96         return err
97 }
98
99 func (s *SBIClient) GetDeployedXapps() error {
100         params := apixapp.NewGetAllXappsParamsWithTimeout(s.timeout)
101         result, err := s.CreateTransport(s.appmgrAddr).Xapp.GetAllXapps(params)
102         if err != nil {
103                 log.Error("GET unsuccessful: %v", err)
104         } else {
105                 log.Info("GET successful: payload=%v", result.Payload)
106         }
107         return err
108 }
109
110 func (s *SBIClient) BuildXappConfig(name, namespace string, configData interface{}) *apimodel.XAppConfig {
111         metadata := &apimodel.ConfigMetadata{
112                 XappName:  &name,
113                 Namespace: &namespace,
114         }
115
116         return &apimodel.XAppConfig{
117                 Metadata: metadata,
118                 Config:   configData,
119         }
120 }
121
122 func (s *SBIClient) ModifyXappConfig(xappConfig *apimodel.XAppConfig) error {
123         params := apixapp.NewModifyXappConfigParamsWithTimeout(s.timeout).WithXAppConfig(xappConfig)
124         result, err := s.CreateTransport(s.appmgrAddr).Xapp.ModifyXappConfig(params)
125         if err != nil {
126                 log.Error("SBI: ModifyXappConfig unsuccessful: %v", err)
127         } else {
128                 log.Info("SBI: ModifyXappConfig successful: payload=%v", result.Payload)
129         }
130         return err
131 }
132
133 func (s *SBIClient) GetAllPodStatus(namespace string) ([]PodStatus, error) {
134         output, err := s.RunCommand(fmt.Sprintf("/usr/local/bin/kubectl get pod -n %s", namespace))
135         if err != nil {
136                 return []PodStatus{}, err
137         }
138
139         podStatusList := []PodStatus{}
140         var readyStr string
141         re := regexp.MustCompile(fmt.Sprintf(`%s-.*`, namespace))
142         podList := re.FindAllStringSubmatch(string(output), -1)
143         if podList != nil {
144                 for _, pod := range podList {
145                         p := PodStatus{}
146                         fmt.Sscanf(pod[0], "%s %s %s", &p.Name, &readyStr, &p.Status)
147                         p.Name = strings.Split(p.Name, "-")[1]
148                         p.Health = s.GetHealthState(readyStr)
149
150                         podStatusList = append(podStatusList, p)
151                 }
152         }
153         return podStatusList, nil
154 }
155
156 func (s *SBIClient) GetHealthState(ready string) (state string) {
157         result := strings.Split(ready, "/")
158         if len(result) < 2 {
159                 return "unavailable"
160         }
161
162         if result[0] == result[1] {
163                 state = "healthy"
164         } else {
165                 state = "unhealthy"
166         }
167         return
168 }
169
170 func (s *SBIClient) RunCommand(args string) (string, error) {
171         return CommandExec(args)
172 }
173
174 var CommandExec = func(args string) (string, error) {
175         cmd := exec.Command("/bin/sh", "-c", args)
176         var stdout bytes.Buffer
177         var stderr bytes.Buffer
178         cmd.Stdout = &stdout
179         cmd.Stderr = &stderr
180
181         xapp.Logger.Debug("Running command: '%s'", strings.Join(cmd.Args, " "))
182         if err := cmd.Run(); err != nil {
183                 xapp.Logger.Error("Command failed (%s): %v - %s", strings.Join(cmd.Args, " "), err.Error(), stderr.String())
184                 return "", err
185         }
186         xapp.Logger.Debug("Command executed successfully!")
187         return stdout.String(), nil
188 }
189
190 func (s *SBIClient) GetAlerts() (*alert.GetAlertsOK, error) {
191         xapp.Logger.Info("Fetching alerts ...")
192
193         cr := clientruntime.New(s.alertmgrAddr, "/api/v2", []string{"http"})
194         resp, err := client.New(cr, strfmt.Default).Alert.GetAlerts(nil)
195         if err != nil {
196                 xapp.Logger.Error("Fetching alerts failed with error: %v", err)
197                 return nil, err
198         }
199
200         return resp, nil
201 }