Skip to content

Commit

Permalink
Further implementation of proxmox library and some basic metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
Starttoaster committed Mar 8, 2024
1 parent c137bd5 commit 3c0f6c5
Show file tree
Hide file tree
Showing 9 changed files with 329 additions and 182 deletions.
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func init() {

rootCmd.PersistentFlags().String("log-level", "info", "The log-level for the application, can be one of info, warn, error, debug.")
rootCmd.PersistentFlags().Uint16("server-port", 8080, "The port the metrics server binds to.")
rootCmd.PersistentFlags().String("proxmox-endpoints", "", "The Proxmox API endpoint, you can pass in multiple endpoints separated by commas (ex: https://localhost:8006/api2/json)")
rootCmd.PersistentFlags().String("proxmox-endpoints", "", "The Proxmox API endpoint, you can pass in multiple endpoints separated by commas (ex: https://localhost:8006/)")
rootCmd.PersistentFlags().String("proxmox-token-id", "", "Proxmox API token ID")
rootCmd.PersistentFlags().String("proxmox-token", "", "Proxmox API token")
rootCmd.PersistentFlags().Bool("proxmox-api-insecure", false, "Whether or not this client should accept insecure connections to Proxmox (default: false)")
Expand Down
8 changes: 0 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ go 1.21
require (
github.com/google/go-querystring v1.1.0
github.com/gorilla/mux v1.8.1
github.com/luthermonson/go-proxmox v0.0.0-beta3
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/prometheus/client_golang v1.18.0
github.com/spf13/cobra v1.8.0
Expand All @@ -14,15 +13,10 @@ require (

require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/buger/goterm v1.0.4 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/diskfs/go-diskfs v1.4.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gorilla/websocket v1.5.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jinzhu/copier v0.4.0 // indirect
github.com/magefile/mage v1.15.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
Expand All @@ -38,11 +32,9 @@ require (
github.com/subosito/gotenv v1.6.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/sys v0.17.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/protobuf v1.32.0 // indirect
gopkg.in/djherbis/times.v1 v1.3.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
23 changes: 0 additions & 23 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,49 +1,31 @@
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/buger/goterm v1.0.4 h1:Z9YvGmOih81P0FbVtEYTFF6YsSgxSUKEhf/f9bTMXbY=
github.com/buger/goterm v1.0.4/go.mod h1:HiFWV3xnkolgrBV3mY8m0X0Pumt4zg4QhbdOzQtB8tE=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/diskfs/go-diskfs v1.4.0 h1:MAybY6TPD+fmhY+a2qFhmdvMeIKvCqlgh4QIc1uCmBs=
github.com/diskfs/go-diskfs v1.4.0/go.mod h1:G8cyy+ngM+3yKlqjweMmtqvE+TxsnIo1xumbJX1AeLg=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/h2non/gock v1.2.0 h1:K6ol8rfrRkUOefooBC8elXoaNGYkpp7y2qcxGG6BzUE=
github.com/h2non/gock v1.2.0/go.mod h1:tNhoxHYW2W42cYkYb1WqzdbYIieALC99kpYr7rH/BQk=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/luthermonson/go-proxmox v0.0.0-beta3 h1:X1RAP/R/pytwgku9/ySir/JwWCZu/UOCn+hLWOz3r54=
github.com/luthermonson/go-proxmox v0.0.0-beta3/go.mod h1:wkD6045y9lKBCP0sJGjNqmlBCo0vwRwnfhmsrPBTu34=
github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg=
github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
Expand Down Expand Up @@ -95,9 +77,6 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
Expand All @@ -108,8 +87,6 @@ google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHh
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/djherbis/times.v1 v1.3.0 h1:uxMS4iMtH6Pwsxog094W0FYldiNnfY/xba00vq6C2+o=
gopkg.in/djherbis/times.v1 v1.3.0/go.mod h1:AQlg6unIsrsCEdQYhTzERy542dz6SFdQFZFv6mUY0P8=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
56 changes: 37 additions & 19 deletions internal/prometheus/prometheus.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package prometheus

import (
"github.com/luthermonson/go-proxmox"
"strings"

"github.com/prometheus/client_golang/prometheus"
"github.com/starttoaster/proxmox-exporter/internal/logger"
wrappedProxmox "github.com/starttoaster/proxmox-exporter/internal/proxmox"
Expand All @@ -16,7 +17,7 @@ type Collector struct {
func NewCollector() *Collector {
return &Collector{
up: prometheus.NewDesc(fqAddPrefix("up"),
"Shows whether nodes and vms in a proxmox cluster are up. (0=down,1=up)",
"Shows whether nodes, VMs, and LXCs in a proxmox cluster are up. (0=down,1=up)",
[]string{"type", "name"},
nil,
),
Expand All @@ -31,42 +32,59 @@ func (c *Collector) Describe(ch chan<- *prometheus.Desc) {
// Collect instructs the prometheus client how to collect the metrics for each descriptor
func (c *Collector) Collect(ch chan<- prometheus.Metric) {
// Retrieve node statuses for the cluster
nodeStatuses, err := wrappedProxmox.Nodes()
nodes, err := wrappedProxmox.GetNodes()
if err != nil {
logger.Logger.Error(err.Error())
return
}

// Retrieve node info for each node from statuses
var nodes []*proxmox.Node
for _, nodeStatus := range nodeStatuses {
for _, node := range nodes.Data {
// Get Node status online float metric from string
var nodeStatusOnline float64
if strings.EqualFold(node.Status, "online") {
nodeStatusOnline = 1.0
}

// Add node up metric
ch <- prometheus.MustNewConstMetric(c.up, prometheus.GaugeValue, float64(nodeStatus.Online), "node", nodeStatus.Name)
ch <- prometheus.MustNewConstMetric(c.up, prometheus.GaugeValue, nodeStatusOnline, node.Type, node.Node)

// Get node from node status's name
node, err := wrappedProxmox.Node(nodeStatus.Name)
// Get VM statuses from each node
vms, err := wrappedProxmox.GetNodeQemu(node.Node)
if err != nil {
logger.Logger.Error(err.Error())
return
}
nodes = append(nodes, node)
}

for _, node := range nodes {
// Get VMs for node
vms, err := wrappedProxmox.VirtualMachinesOnNode(node)
// Retrieve info for each VM
for _, vm := range vms.Data {
// Get Node status online float metric from string
var vmStatusOnline float64
if strings.EqualFold(vm.Status, "running") {
vmStatusOnline = 1.0
}

// Add node up metric
ch <- prometheus.MustNewConstMetric(c.up, prometheus.GaugeValue, vmStatusOnline, "qemu", vm.Name)
}

// Get LXC statuses from each node
lxcs, err := wrappedProxmox.GetNodeLxc(node.Node)
if err != nil {
logger.Logger.Error(err.Error())
return
}

for _, vm := range vms {
// Add vm up metric
var vmUp float64 = 0.0
if vm.IsRunning() {
vmUp = 1.0
// Retrieve info for each LXC
for _, lxc := range lxcs.Data {
// Get LXC status online float metric from string
var lxcStatusOnline float64
if strings.EqualFold(lxc.Status, "running") {
lxcStatusOnline = 1.0
}
ch <- prometheus.MustNewConstMetric(c.up, prometheus.GaugeValue, vmUp, "qemu", vm.Name)

// Add node up metric
ch <- prometheus.MustNewConstMetric(c.up, prometheus.GaugeValue, lxcStatusOnline, lxc.Type, lxc.Name)
}
}
}
29 changes: 10 additions & 19 deletions internal/proxmox/client.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package proxmox

import (
"context"
"crypto/tls"
"errors"
"fmt"
"net/http"
"net/url"
Expand All @@ -12,7 +10,7 @@ import (
"github.com/patrickmn/go-cache"
log "github.com/starttoaster/proxmox-exporter/internal/logger"

"github.com/luthermonson/go-proxmox"
"github.com/starttoaster/proxmox-exporter/pkg/proxmox"
)

var (
Expand Down Expand Up @@ -46,26 +44,19 @@ func Init(endpoints []string, tokenID, token string, tlsVerify bool) error {
}
hostname := parsedURL.Hostname()

// Add client to map
// Create API client
log.Logger.Debug("Creating Proxmox client", "endpoint", endpoint, "hostname", hostname)
clients[hostname] = proxmox.NewClient(endpoint,
proxmox.WithHTTPClient(&httpClient),
proxmox.WithAPIToken(tokenID, token),
c, err := proxmox.NewClient(tokenID, token,
proxmox.WithBaseURL(endpoint),
proxmox.WithHttpClient(&httpClient),
)
}

// Test API client with a request to the server
log.Logger.Debug("Testing Proxmox API client with request to server version")
version, err := anyClient().Version(context.Background())
if err != nil {
return fmt.Errorf("error retrieving Proxmox server version: \n%v", err)
}
if err != nil {
return fmt.Errorf("error creating API client for exporter: %w", err)
}

// Check and log version
if version == nil {
return errors.New("the Proxmox server returned no error from version request, but version is nil")
// Add client to map
clients[hostname] = c
}
log.Logger.Debug("Proxmox server", "version", version.Release)

// init cache -- at longest, cache will live for 29 seconds
// which should ensure metrics are updated if scraping in 30 second intervals
Expand Down
85 changes: 67 additions & 18 deletions internal/proxmox/nodes.go
Original file line number Diff line number Diff line change
@@ -1,60 +1,109 @@
package proxmox

import (
"context"
"fmt"

"github.com/luthermonson/go-proxmox"
"github.com/patrickmn/go-cache"
log "github.com/starttoaster/proxmox-exporter/internal/logger"
"github.com/starttoaster/proxmox-exporter/pkg/proxmox"
)

// Nodes returns a proxmox NodeStatuses object or an error from the /nodes endpoint
func Nodes() (proxmox.NodeStatuses, error) {
// GetNodes returns a proxmox NodeStatuses object or an error from the /nodes endpoint
func GetNodes() (*proxmox.GetNodesResponse, error) {
// Chech cache
var nodes proxmox.NodeStatuses
if x, found := cash.Get("Nodes"); found {
var nodes *proxmox.GetNodesResponse
if x, found := cash.Get("GetNodes"); found {
var ok bool
nodes, ok = x.(proxmox.NodeStatuses)
nodes, ok = x.(*proxmox.GetNodesResponse)
if ok {
log.Logger.Debug("proxmox request was found in cache for Nodes")
return nodes, nil
}
}

// Make request if not found in cache
nodes, err := anyClient().Nodes(context.Background())
nodes, _, err := anyClient().Nodes.GetNodes()
if err != nil {
return nil, fmt.Errorf("encountered error making request to /nodes: \n%v", err)
return nil, err
}

// Update cache
cash.Set("Nodes", nodes, cache.DefaultExpiration)
cash.Set("GetNodes", nodes, cache.DefaultExpiration)

return nodes, nil
}

// Node returns a proxmox Node object or an error from the /nodes/%s/status endpoint
func Node(name string) (*proxmox.Node, error) {
// GetNode returns a proxmox Node object or an error from the /nodes/%s/status endpoint
func GetNode(name string) (*proxmox.GetNodeResponse, error) {
// Chech cache
var node *proxmox.Node
if x, found := cash.Get(fmt.Sprintf("Node_%s", name)); found {
var node *proxmox.GetNodeResponse
if x, found := cash.Get(fmt.Sprintf("GetNode_%s", name)); found {
var ok bool
node, ok = x.(*proxmox.Node)
node, ok = x.(*proxmox.GetNodeResponse)
if ok {
log.Logger.Debug("proxmox request was found in cache for Node", "node", name)
return node, nil
}
}

// Make request if not found in cache
node, err := anyClient().Node(context.Background(), name)
node, _, err := anyClient().Nodes.GetNode(name)
if err != nil {
return nil, fmt.Errorf("encountered error making request to /nodes/%s/status: \n%v", name, err)
return nil, err
}

// Update cache
cash.Set(fmt.Sprintf("Node_%s", name), node, cache.DefaultExpiration)
cash.Set(fmt.Sprintf("GetNode_%s", name), node, cache.DefaultExpiration)

return node, nil
}

// GetNodeQemu returns the virtual machines for a node
func GetNodeQemu(name string) (*proxmox.GetNodeQemuResponse, error) {
// Chech cache
var vms *proxmox.GetNodeQemuResponse
if x, found := cash.Get(fmt.Sprintf("GetNodeQemu_%s", name)); found {
var ok bool
vms, ok = x.(*proxmox.GetNodeQemuResponse)
if ok {
log.Logger.Debug("proxmox request was found in cache for GetNodeQemu", "node", name)
return vms, nil
}
}

// Make request if not found in cache
vms, _, err := anyClient().Nodes.GetNodeQemu(name)
if err != nil {
return nil, err
}

// Update per-node cache since we have it
cash.Set(fmt.Sprintf("GetNodeQemu_%s", name), vms, cache.DefaultExpiration)

return vms, nil
}

// GetNodeLxc returns the LXCs for a node
func GetNodeLxc(name string) (*proxmox.GetNodeLxcResponse, error) {
// Chech cache
var lxcs *proxmox.GetNodeLxcResponse
if x, found := cash.Get(fmt.Sprintf("GetNodeLxc_%s", name)); found {
var ok bool
lxcs, ok = x.(*proxmox.GetNodeLxcResponse)
if ok {
log.Logger.Debug("proxmox request was found in cache for GetNodeLxc", "node", name)
return lxcs, nil
}
}

// Make request if not found in cache
vms, _, err := anyClient().Nodes.GetNodeLxc(name)
if err != nil {
return nil, err
}

// Update per-node cache since we have it
cash.Set(fmt.Sprintf("GetNodeLxc_%s", name), vms, cache.DefaultExpiration)

return vms, nil
}
Loading

0 comments on commit 3c0f6c5

Please sign in to comment.