Skip to content

Instantly share code, notes, and snippets.

@eumel8
Last active May 10, 2022 17:26
Show Gist options
  • Select an option

  • Save eumel8/087dbad0d33471a64b9a2d4621cc5d20 to your computer and use it in GitHub Desktop.

Select an option

Save eumel8/087dbad0d33471a64b9a2d4621cc5d20 to your computer and use it in GitHub Desktop.
otc-rds-alarm.go
package main
import (
"fmt"
"net/http"
"os"
"github.com/gophercloud/utils/client"
golangsdk "github.com/opentelekomcloud/gophertelekomcloud"
"github.com/opentelekomcloud/gophertelekomcloud/openstack"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/cloudeyeservice/alarmrule"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/smn/v2/subscriptions"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/smn/v2/topics"
"github.com/opentelekomcloud/gophertelekomcloud/pagination"
"k8s.io/klog/v2"
)
const (
rootPath = "alarms"
)
func rootURL(c *golangsdk.ServiceClient) string {
return c.ServiceURL(rootPath)
}
type AlarmRulePage struct {
pagination.SinglePageBase
}
type ListAlarmRuleOpts struct {
AlarmName string `q:"alarm_name"`
MetricAlarms []string `q:"metric_alarms"`
MetaData MetaData `q:"meta_data"`
}
type MetaData struct {
Count int `q:"count"`
Marker string `q:"marker"`
Total int `q:"total"`
}
type ListAlarmRuleBuilder interface {
ToAlarmRuleListDetailQuery() (string, error)
}
func (opts ListAlarmRuleOpts) ToAlarmRuleListDetailQuery() (string, error) {
q, err := golangsdk.BuildQueryString(opts)
if err != nil {
return "", err
}
return q.String(), err
}
func List(client *golangsdk.ServiceClient, opts ListAlarmRuleBuilder) pagination.Pager {
url := rootURL(client)
if opts != nil {
query, err := opts.ToAlarmRuleListDetailQuery()
if err != nil {
return pagination.Pager{Err: err}
}
url += query
}
pageAlarmRuleList := pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
return AlarmRulePage{pagination.SinglePageBase(r)}
})
alarmruleheader := map[string]string{"Content-Type": "application/json"}
pageAlarmRuleList.Headers = alarmruleheader
return pageAlarmRuleList
}
func getProvider() *golangsdk.ProviderClient {
if os.Getenv("OS_AUTH_URL") == "" {
os.Setenv("OS_AUTH_URL", "https://iam.eu-de.otc.t-systems.com:443/v3")
}
if os.Getenv("OS_IDENTITY_API_VERSION") == "" {
os.Setenv("OS_IDENTITY_API_VERSION", "3")
}
if os.Getenv("OS_REGION_NAME") == "" {
os.Setenv("OS_REGION_NAME", "eu-de")
}
if os.Getenv("OS_PROJECT_NAME") == "" {
os.Setenv("OS_PROJECT_NAME", "eu-de")
}
opts, err := openstack.AuthOptionsFromEnv()
if err != nil {
klog.Exitf("error getting auth from env: %v", err)
}
provider, err := openstack.AuthenticatedClient(opts)
if err != nil {
klog.Exitf("unable to initialize openstack client: %v", err)
}
if os.Getenv("OS_DEBUG") == "1" {
provider.HTTPClient = http.Client{
Transport: &client.RoundTripper{
Rt: &http.Transport{},
Logger: &client.DefaultLogger{},
},
}
}
return provider
}
func ExtractAlarmRules(r pagination.Page) ([]alarmrule.AlarmRule, error) {
var s []alarmrule.AlarmRule
err := ExtractAlarmRulesInto(r, &s)
return s, err
}
func ExtractAlarmRulesInto(r pagination.Page, v interface{}) error {
return r.(AlarmRulePage).Result.ExtractIntoSlicePtr(v, "metric_alarms")
}
func CreateAlarm(instanceId string, smnEndpoint string, rdsName string, namespace string) {
nsRds := namespace + "-" + rdsName
// initial provider
provider := getProvider()
// inital service clients for CES and SMN
ces, err := openstack.NewCESClient(provider, golangsdk.EndpointOpts{})
if err != nil {
klog.Exitf("unable to initialize ces client: %v", err)
return
}
smn, err := openstack.NewSMNV2(provider, golangsdk.EndpointOpts{})
if err != nil {
klog.Exitf("unable to initialize ces client: %v", err)
return
}
// check if topic for rds exists
tl, err := topics.List(smn).Extract()
if err != nil {
klog.Exitf("unable to get topic list: %v", err)
return
}
for _, tc := range tl {
if tc.Name == nsRds {
klog.Exitf("topic exists for %s", nsRds)
return
}
}
// create topic
newTopic := topics.CreateOps{
Name: nsRds,
DisplayName: nsRds,
}
topic, err := topics.Create(smn, newTopic).Extract()
if err != nil {
klog.Exitf("unable to create topic: %v", err)
return
}
// check of subscription exists for rds
smnList, err := subscriptions.List(smn).Extract()
if err != nil {
klog.Exitf("error extracting subscription list: %v", err)
return
}
for _, sl := range smnList {
if sl.Endpoint == smnEndpoint {
klog.Exitf("subscription esists for %s\n", nsRds)
return
}
}
// create smn subscription
newSmn := subscriptions.CreateOpts{
Endpoint: smnEndpoint,
Protocol: "https",
Remark: "RDS Operator",
}
_, err = subscriptions.Create(smn, newSmn, topic.TopicUrn).Extract()
if err != nil {
klog.Exitf("error create subscription: %v", err)
return
}
// list all alarmrules
pages, err := List(ces, &ListAlarmRuleOpts{}).AllPages()
if err != nil {
klog.Exitf("ces list failed allpages: %v", err)
return
}
alarms, err := ExtractAlarmRules(pages)
if err != nil {
klog.Exitf("ces list extract failed: %v", err)
return
}
for _, alarm := range alarms {
if alarm.AlarmName == nsRds+"-disc-util" {
klog.Exitf("alarmrule exists for %s", nsRds)
return
}
}
alarmDiscUtil := alarmrule.CreateOpts{
AlarmName: nsRds + "-disc-util",
AlarmDescription: "RDS Operator Autopilot",
AlarmLevel: 2,
Metric: alarmrule.MetricOpts{
Namespace: "SYS.RDS",
MetricName: "rds039_disk_util",
Dimensions: []alarmrule.DimensionOpts{{
Name: "rds_instance_id",
Value: instanceId,
}},
},
Condition: alarmrule.ConditionOpts{
Period: 300,
Filter: "average",
ComparisonOperator: ">=",
Value: 12,
Unit: "",
Count: 3,
},
AlarmActions: []alarmrule.ActionOpts{{
Type: "notification",
NotificationList: []string{topic.TopicUrn},
}},
AlarmEnabled: true,
AlarmActionEnabled: true,
}
alarmCpuUtil := alarmrule.CreateOpts{
AlarmName: nsRds + "-cpu-util",
AlarmDescription: "RDS Operator Autopilot",
AlarmLevel: 2,
Metric: alarmrule.MetricOpts{
Namespace: "SYS.RDS",
MetricName: "rds001_cpu_util",
Dimensions: []alarmrule.DimensionOpts{{
Name: "rds_instance_id",
Value: instanceId,
}},
},
Condition: alarmrule.ConditionOpts{
Period: 300,
Filter: "average",
ComparisonOperator: ">=",
Value: 90,
Unit: "",
Count: 3,
},
AlarmActions: []alarmrule.ActionOpts{{
Type: "notification",
NotificationList: []string{topic.TopicUrn},
}},
AlarmEnabled: true,
AlarmActionEnabled: true,
}
alarmMemUtil := alarmrule.CreateOpts{
AlarmName: nsRds + "-mem-util",
AlarmDescription: "RDS Operator Autopilot",
AlarmLevel: 2,
Metric: alarmrule.MetricOpts{
Namespace: "SYS.RDS",
MetricName: "rds002_mem_util",
Dimensions: []alarmrule.DimensionOpts{{
Name: "rds_instance_id",
Value: instanceId,
}},
},
Condition: alarmrule.ConditionOpts{
Period: 300,
Filter: "average",
ComparisonOperator: ">=",
Value: 90,
Unit: "",
Count: 3,
},
AlarmActions: []alarmrule.ActionOpts{{
Type: "notification",
NotificationList: []string{topic.TopicUrn},
}},
AlarmEnabled: true,
AlarmActionEnabled: true,
}
alarmDiscUtilResult, err := alarmrule.Create(ces, alarmDiscUtil).Extract()
if err != nil {
klog.Exitf("error creating alarmrule: %v", err)
return
}
fmt.Println(alarmDiscUtilResult.AlarmID)
alarmCpuUtilResult, err := alarmrule.Create(ces, alarmCpuUtil).Extract()
if err != nil {
klog.Exitf("error creating alarmrule: %v", err)
return
}
fmt.Println(alarmCpuUtilResult.AlarmID)
alarmMemUtilResult, err := alarmrule.Create(ces, alarmMemUtil).Extract()
if err != nil {
klog.Exitf("error creating alarmrule: %v", err)
return
}
fmt.Println(alarmMemUtilResult.AlarmID)
}
func main() {
// we need here
// RDS NodeID
// Ingress URL
// newRDS.Name
// newRDS.MetaData.Namespace
instanceId := "xxxx"
smnEndpoint := "xxx"
rdsName := "xxxx"
namespace := "xxxx"
CreateAlarm(instanceId, smnEndpoint, rdsName, namespace)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment