티스토리 뷰

Cloud/Private Cloud

gophercloud sdk

jacobbaek Jacob_baek 2021. 2. 8. 22:22

gophercloud sdk를 활용하여 openstack api를 호출하는 golang program을 만들어보자.

아래 링크에서도 (clientconfig)[https://github.com/gophercloud/utils/tree/master/openstack/clientconfig]의 사용을 권장하고 있다.
https://pkg.go.dev/github.com/gophercloud/gophercloud#hdr-Authenticating_with_Providers

하여 clientconfig를 사용하는 방법 기반으로 설명하려 한다.

gophercloud의 clientconfig를 사용하는 과정은 다음과 같다.
(clientconfig의 경우 기존 document가 생각보다 자세히 나와있지 않아 관련 flow와 예제를 통해 좀더 쉽게 알아갈수 있도록 한다.)

  1. clientconfig.LoadCloudsYAML을 통해 clouds.yaml을 읽고 client 객체를 만든다.
  2. 생성된 client객체를 이용하여 clientconfig.ClientOpts 객체를 생성한다.
  3. 생성된 ClientOpts 객체를 clientconfig.NewServiceClient의 argument에 "compute", "gnocchi"와 같은 component를 전달하여 OpenStack Component를 호출할수 있도록 준비한다.
  4. (servers)[https://pkg.go.dev/github.com/gophercloud/gophercloud/openstack/compute/v2/servers] 혹은 (resources)[https://pkg.go.dev/github.com/gophercloud/utils/gnocchi/metric/v1/resources] 등을 사용하여 실제 데이터를 가져오거나 추가한다.
package main

import (
    "bytes"
    "container/list"
    "io/ioutil"
    "log"
    "net/http"
    "os"
    "time"

    "github.com/gophercloud/gophercloud"
    "github.com/gophercloud/openstack/openstack/compute/v2/servers"
    "github.com/gophercloud/utils/gnocchi/metric/v1/measures"
    "github.com/gophercloud/utils/gnocchi/metric/v1/resources"
    "github.com/gophercloud/utils/openstack/clientconfig"
)

var Logger *log.Logger

func CheckNexit(err error) {
    if err != nil {
        Logger.Println(err)
        os.Exit(1)
    }
}

func CheckObjInList(srvlst *list.List, ID string) bool {
    for e := srvlst.Back(); e != nil; e = e.Prev() {
        if e.Value == ID {
            return true
        }
    }
    return false
}

// get the resoures and make
func MakeMetricServerList(auth_opts *clientconfig.ClientOpts, retlst *list.List, srvlst *list.List) {
    // get the metrics
    gnocchiClient, err := clientconfig.NewServiceClient("gnocchi", auth_opts)
    CheckNexit(err)

    // https://pkg.golangclub.com/github.com/gophercloud/utils/gnocchi/metric/v1/measures?tab=doc
    // only resources that have instance type.
    resourceType := "instance"
    listOpts := resources.ListOpts{
        Details: true,
    }

    allPages, err := resources.List(gnocchiClient, listOpts, resourceType).AllPages()
    CheckNexit(err)

    allResources, err := resources.ExtractResources(allPages)
    CheckNexit(err)

    currentTimestamp := time.Now().UTC()
    pastHourTimestamp := currentTimestamp.Add(-4 * time.Hour)

    Logger.Printf("total count for resources : %d\n", len(allResources))

    // https://pkg.golangclub.com/github.com/gophercloud/utils/gnocchi/metric/v1/resources?tab=doc
    for _, resource := range allResources {
        Logger.Printf("instance: %s(%s)", resource.ExtraAttributes["display_name"], resource.OriginalResourceID)
    }
}

// get the servers and make Active Server list
func MakeActiveServerList(opts *clientconfig.ClientOpts, srvlst *list.List) {
    computeClient, err := clientconfig.NewServiceClient("compute", opts)
    CheckNexit(err)

    listOpts := servers.ListOpts{
        AllTenants: true,
    }

    allPages, err := servers.List(computeClient, listOpts).AllPages()
    CheckNexit(err)

    allServers, err := servers.ExtractServers(allPages)
    CheckNexit(err)

    for _, server := range allServers {
        if server.Status == "ACTIVE" {
            srvlst.PushBack(server.ID)
        }
    }
}

func main() {
    Logger = log.New(os.Stdout, "LOG: ", log.LstdFlags)
    retlst := list.New()
    srvlst := list.New()

    client_map, err := clientconfig.LoadCloudsYAML()
    CheckNexit(err)

    Logger.Printf("start crawling for %s\n", client_map["dev"].AuthInfo.AuthURL)
        auth_opts := &clientconfig.ClientOpts{
        AuthInfo: client_map["dev"].AuthInfo,
    }

    MakeActiveServerList(auth_opts, srvlst)

    Logger.Printf("Active instances: %d", srvlst.Len())

    MakeMetricServerList(auth_opts, retlst, srvlst)

    Logger.Printf("%d empty metrics found\n", retlst.Len())
    for e := retlst.Front(); e != nil; e = e.Next() {
        Logger.Printf("Found instance UUID : %s", e.Value)
    }
}

참고
gnocchi resource의 경우 중복된 데이터가 나오는 문제가 있었다.
debugging이 필요하고 추가로 확인되는 사항이 있을 경우 업데이트 할 예정이다.

'Cloud > Private Cloud' 카테고리의 다른 글

kolla-ansible with elasticsearch  (0) 2021.02.23
Packer on OpenStack  (0) 2021.02.19
gophercloud sdk  (0) 2021.02.08
prometheus alertmanager workflow  (0) 2020.12.28
Jenkins pipeline for Terraform OpenStack  (0) 2020.11.04
Terraform OpenStack Provider  (0) 2020.11.04
댓글
댓글쓰기 폼