1// Copyright 2017 The Prometheus Authors
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14package openstack
15
16import (
17	"errors"
18	"time"
19
20	"github.com/gophercloud/gophercloud"
21	"github.com/prometheus/client_golang/prometheus"
22	"github.com/prometheus/common/log"
23	"golang.org/x/net/context"
24
25	"github.com/prometheus/prometheus/config"
26)
27
28var (
29	refreshFailuresCount = prometheus.NewCounter(
30		prometheus.CounterOpts{
31			Name: "prometheus_sd_openstack_refresh_failures_total",
32			Help: "The number of OpenStack-SD scrape failures.",
33		})
34	refreshDuration = prometheus.NewSummary(
35		prometheus.SummaryOpts{
36			Name: "prometheus_sd_openstack_refresh_duration_seconds",
37			Help: "The duration of an OpenStack-SD refresh in seconds.",
38		})
39)
40
41func init() {
42	prometheus.MustRegister(refreshFailuresCount)
43	prometheus.MustRegister(refreshDuration)
44}
45
46// Discovery periodically performs OpenStack-SD requests. It implements
47// the TargetProvider interface.
48type Discovery interface {
49	Run(ctx context.Context, ch chan<- []*config.TargetGroup)
50	refresh() (tg *config.TargetGroup, err error)
51}
52
53// NewDiscovery returns a new OpenStackDiscovery which periodically refreshes its targets.
54func NewDiscovery(conf *config.OpenstackSDConfig, l log.Logger) (Discovery, error) {
55	opts := gophercloud.AuthOptions{
56		IdentityEndpoint: conf.IdentityEndpoint,
57		Username:         conf.Username,
58		UserID:           conf.UserID,
59		Password:         string(conf.Password),
60		TenantName:       conf.ProjectName,
61		TenantID:         conf.ProjectID,
62		DomainName:       conf.DomainName,
63		DomainID:         conf.DomainID,
64	}
65	switch conf.Role {
66	case config.OpenStackRoleHypervisor:
67		hypervisor := NewHypervisorDiscovery(&opts,
68			time.Duration(conf.RefreshInterval), conf.Port, conf.Region, l)
69		return hypervisor, nil
70	case config.OpenStackRoleInstance:
71		instance := NewInstanceDiscovery(&opts,
72			time.Duration(conf.RefreshInterval), conf.Port, conf.Region, l)
73		return instance, nil
74	default:
75		return nil, errors.New("unknown OpenStack discovery role")
76	}
77}
78