rally_exporter/rally/runner.go
Mohammed Naser b0fb284432 Publish output when failing to create deployment
This patch will publish output if Rally fails to create the
deployment for some reason.

Change-Id: Ie5b4db653d7ffc43832abb5b376a0d67612f2665
2020-04-05 21:35:32 -04:00

181 lines
4.2 KiB
Go

package rally
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"os/exec"
"time"
"github.com/gophercloud/utils/openstack/clientconfig"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/sqlite"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
"opendev.org/vexxhost/rally-exporter/models"
)
// TaskLabels has the common labels used by every task.
var TaskLabels = []string{"title"}
// PeriodicRunner defines the structure of the collector
type PeriodicRunner struct {
prometheus.Collector
CloudName string
TaskFile string
TaskDuration *prometheus.Desc
TaskSLADesc *prometheus.Desc
TaskTime *prometheus.Desc
}
// NewPeriodicRunner creates a rally runner which executes every 5 minutes
func NewPeriodicRunner(cloudName string, taskFile string) *PeriodicRunner {
return &PeriodicRunner{
CloudName: cloudName,
TaskFile: taskFile,
TaskDuration: prometheus.NewDesc(
"rally_task_duration",
"Rally task duration",
TaskLabels, nil,
),
TaskSLADesc: prometheus.NewDesc(
"rally_task_passed",
"Rally task passed",
TaskLabels, nil,
),
TaskTime: prometheus.NewDesc(
"rally_task_time",
"Rally last run time",
[]string{}, nil,
),
}
}
// Run starts the PeriodicRunner which runs Rally every 5 minutes.
func (runner *PeriodicRunner) Run() {
runner.createDeployment()
for {
log.Info("Starting Rally run...")
cmd := exec.Command("rally", "task", "start", runner.TaskFile)
output, err := cmd.CombinedOutput()
if err != nil {
log.Error("Failed test, output below:")
} else {
log.Info("Successful run, output below:")
}
fmt.Println(string(output))
time.Sleep(5 * time.Minute)
}
}
func (runner *PeriodicRunner) createDeployment() {
opts := &clientconfig.ClientOpts{Cloud: runner.CloudName}
cloud, err := clientconfig.GetCloudFromYAML(opts)
if err != nil {
log.Fatal(err)
}
deployment := &Deployment{
OpenStackDeployment: OpenStackDeployment{
AuthURL: cloud.AuthInfo.AuthURL,
RegionName: cloud.RegionName,
EndpointType: cloud.EndpointType,
Users: []OpenStackUser{
OpenStackUser{
Username: cloud.AuthInfo.Username,
Password: cloud.AuthInfo.Password,
UserDomainName: cloud.AuthInfo.UserDomainName,
ProjectName: cloud.AuthInfo.ProjectName,
ProjectDomainName: cloud.AuthInfo.ProjectDomainName,
},
},
},
}
b, err := json.Marshal(deployment)
if err != nil {
log.Fatal(err)
}
file, err := ioutil.TempFile("/tmp", "deployment")
if err != nil {
log.Fatal(err)
}
defer os.Remove(file.Name())
_, err = file.Write(b)
if err != nil {
log.Fatal(err)
}
cmd := exec.Command("rally", "deployment", "create", "--filename", file.Name(), "--name", runner.CloudName)
output, err := cmd.CombinedOutput()
if err != nil {
fmt.Println(string(output))
log.Fatal("Failed to install Rally deployment: ", err)
}
}
// Describe provides all the descriptions of all the information for the collector
func (runner *PeriodicRunner) Describe(ch chan<- *prometheus.Desc) {
ch <- runner.TaskDuration
ch <- runner.TaskSLADesc
ch <- runner.TaskTime
}
func getLatestTask(db *gorm.DB) (*models.Task, error) {
task := &models.Task{}
err := db.Not("status", []string{"running"}).Last(task).Error
return task, err
}
// Collect grabs all the data from the Rally database
func (runner *PeriodicRunner) Collect(ch chan<- prometheus.Metric) {
db, err := gorm.Open("sqlite3", "/home/rally/data/rally.db")
if err != nil {
log.Fatal(err)
}
defer db.Close()
task, err := getLatestTask(db)
if err != nil {
log.Error(err)
return
}
subtasks := []models.Subtask{}
if err := db.Where(&models.Subtask{TaskUUID: task.UUID}).Find(&subtasks).Error; err != nil {
log.Fatal(err)
}
for _, subtask := range subtasks {
ch <- prometheus.MustNewConstMetric(
runner.TaskDuration,
prometheus.GaugeValue,
subtask.Duration, subtask.Title,
)
passSLA := float64(0)
if subtask.PassSLA && subtask.Status == "finished" {
passSLA = float64(1)
}
ch <- prometheus.MustNewConstMetric(
runner.TaskSLADesc,
prometheus.GaugeValue,
passSLA, subtask.Title,
)
}
ch <- prometheus.MustNewConstMetric(
runner.TaskTime,
prometheus.GaugeValue,
float64(task.UpdatedAt.Unix()),
)
}