mirror of https://github.com/k3s-io/k3s
Added openstack instance metadata search order
parent
1a44e26670
commit
870195ad59
|
@ -32,17 +32,25 @@ import (
|
|||
"k8s.io/utils/exec"
|
||||
)
|
||||
|
||||
// metadataUrl is URL to OpenStack metadata server. It's hardcoded IPv4
|
||||
// link-local address as documented in "OpenStack Cloud Administrator Guide",
|
||||
// chapter Compute - Networking with nova-network.
|
||||
// https://docs.openstack.org/admin-guide/compute-networking-nova.html#metadata-service
|
||||
const metadataUrl = "http://169.254.169.254/openstack/2012-08-10/meta_data.json"
|
||||
const (
|
||||
// metadataUrl is URL to OpenStack metadata server. It's hardcoded IPv4
|
||||
// link-local address as documented in "OpenStack Cloud Administrator Guide",
|
||||
// chapter Compute - Networking with nova-network.
|
||||
// https://docs.openstack.org/admin-guide/compute-networking-nova.html#metadata-service
|
||||
metadataUrl = "http://169.254.169.254/openstack/2012-08-10/meta_data.json"
|
||||
|
||||
// Config drive is defined as an iso9660 or vfat (deprecated) drive
|
||||
// with the "config-2" label.
|
||||
// http://docs.openstack.org/user-guide/cli-config-drive.html
|
||||
const configDriveLabel = "config-2"
|
||||
const configDrivePath = "openstack/2012-08-10/meta_data.json"
|
||||
// metadataID is used as an identifier on the metadata search order configuration.
|
||||
metadataID = "metadataService"
|
||||
|
||||
// Config drive is defined as an iso9660 or vfat (deprecated) drive
|
||||
// with the "config-2" label.
|
||||
// http://docs.openstack.org/user-guide/cli-config-drive.html
|
||||
configDriveLabel = "config-2"
|
||||
configDrivePath = "openstack/2012-08-10/meta_data.json"
|
||||
|
||||
// configDriveID is used as an identifier on the metadata search order configuration.
|
||||
configDriveID = "configDrive"
|
||||
)
|
||||
|
||||
var ErrBadMetadata = errors.New("Invalid OpenStack metadata, got empty uuid")
|
||||
|
||||
|
@ -141,12 +149,27 @@ func getMetadataFromMetadataService() (*Metadata, error) {
|
|||
// Metadata is fixed for the current host, so cache the value process-wide
|
||||
var metadataCache *Metadata
|
||||
|
||||
func getMetadata() (*Metadata, error) {
|
||||
func getMetadata(order string) (*Metadata, error) {
|
||||
if metadataCache == nil {
|
||||
md, err := getMetadataFromConfigDrive()
|
||||
if err != nil {
|
||||
var md *Metadata
|
||||
var err error
|
||||
|
||||
elements := strings.Split(order, ",")
|
||||
for _, id := range elements {
|
||||
switch id {
|
||||
case configDriveID:
|
||||
md, err = getMetadataFromConfigDrive()
|
||||
case metadataID:
|
||||
md, err = getMetadataFromMetadataService()
|
||||
default:
|
||||
err = fmt.Errorf("%s is not a valid metadata search order option. Supported options are %s and %s", id, configDriveID, metadataID)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -100,6 +100,10 @@ type RouterOpts struct {
|
|||
RouterId string `gcfg:"router-id"` // required
|
||||
}
|
||||
|
||||
type MetadataOpts struct {
|
||||
SearchOrder string `gcfg:"search-order"`
|
||||
}
|
||||
|
||||
// OpenStack is an implementation of cloud provider Interface for OpenStack.
|
||||
type OpenStack struct {
|
||||
provider *gophercloud.ProviderClient
|
||||
|
@ -107,6 +111,7 @@ type OpenStack struct {
|
|||
lbOpts LoadBalancerOpts
|
||||
bsOpts BlockStorageOpts
|
||||
routeOpts RouterOpts
|
||||
metadataOpts MetadataOpts
|
||||
// InstanceID of the server where this OpenStack object is instantiated.
|
||||
localInstanceID string
|
||||
}
|
||||
|
@ -128,6 +133,7 @@ type Config struct {
|
|||
LoadBalancer LoadBalancerOpts
|
||||
BlockStorage BlockStorageOpts
|
||||
Route RouterOpts
|
||||
Metadata MetadataOpts
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
@ -181,6 +187,7 @@ func readConfig(config io.Reader) (Config, error) {
|
|||
// Set default values for config params
|
||||
cfg.BlockStorage.BSVersion = "auto"
|
||||
cfg.BlockStorage.TrustDevicePath = false
|
||||
cfg.Metadata.SearchOrder = fmt.Sprintf("%s,%s", configDriveID, metadataID)
|
||||
|
||||
err := gcfg.ReadInto(&cfg, config)
|
||||
return cfg, err
|
||||
|
@ -198,7 +205,7 @@ func (c *Caller) Call(f func()) {
|
|||
}
|
||||
}
|
||||
|
||||
func readInstanceID() (string, error) {
|
||||
func readInstanceID(searchOrder string) (string, error) {
|
||||
// Try to find instance ID on the local filesystem (created by cloud-init)
|
||||
const instanceIDFile = "/var/lib/cloud/data/instance-id"
|
||||
idBytes, err := ioutil.ReadFile(instanceIDFile)
|
||||
|
@ -212,7 +219,7 @@ func readInstanceID() (string, error) {
|
|||
// Fall through to metadata server lookup
|
||||
}
|
||||
|
||||
md, err := getMetadata()
|
||||
md, err := getMetadata(searchOrder)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -275,6 +282,8 @@ func newOpenStack(cfg Config) (*OpenStack, error) {
|
|||
err = openstack.Authenticate(provider, cfg.toAuthOptions())
|
||||
}
|
||||
|
||||
err = validateMetadataSearchOrder(cfg.Metadata.SearchOrder)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -285,6 +294,7 @@ func newOpenStack(cfg Config) (*OpenStack, error) {
|
|||
lbOpts: cfg.LoadBalancer,
|
||||
bsOpts: cfg.BlockStorage,
|
||||
routeOpts: cfg.Route,
|
||||
metadataOpts: cfg.Metadata,
|
||||
}
|
||||
|
||||
err = checkOpenStackOpts(&os)
|
||||
|
@ -539,7 +549,7 @@ func (os *OpenStack) Zones() (cloudprovider.Zones, bool) {
|
|||
}
|
||||
|
||||
func (os *OpenStack) GetZone() (cloudprovider.Zone, error) {
|
||||
md, err := getMetadata()
|
||||
md, err := getMetadata(os.metadataOpts.SearchOrder)
|
||||
if err != nil {
|
||||
return cloudprovider.Zone{}, err
|
||||
}
|
||||
|
@ -742,3 +752,27 @@ func (os *OpenStack) volumeService(forceVersion string) (volumeService, error) {
|
|||
return nil, errors.New(err_txt)
|
||||
}
|
||||
}
|
||||
|
||||
func validateMetadataSearchOrder(order string) error {
|
||||
if order == "" {
|
||||
return errors.New("Invalid value in section [Metadata] with key `search-order`. Value cannot be empty")
|
||||
}
|
||||
|
||||
elements := strings.Split(order, ",")
|
||||
if len(elements) > 2 {
|
||||
return errors.New("Invalid value in section [Metadata] with key `search-order`. Value cannot contain more than 2 elements")
|
||||
}
|
||||
|
||||
for _, o := range elements {
|
||||
switch o {
|
||||
case configDriveID:
|
||||
case metadataID:
|
||||
default:
|
||||
errTxt := "Invalid element '%s' found in section [Metadata] with key `search-order`." +
|
||||
"Supported elements include '%s' and '%s'"
|
||||
return fmt.Errorf(errTxt, o, configDriveID, metadataID)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import (
|
|||
|
||||
type Instances struct {
|
||||
compute *gophercloud.ServiceClient
|
||||
opts MetadataOpts
|
||||
}
|
||||
|
||||
// Instances returns an implementation of Instances for OpenStack.
|
||||
|
@ -45,13 +46,16 @@ func (os *OpenStack) Instances() (cloudprovider.Instances, bool) {
|
|||
|
||||
glog.V(1).Info("Claiming to support Instances")
|
||||
|
||||
return &Instances{compute}, true
|
||||
return &Instances{
|
||||
compute: compute,
|
||||
opts: os.metadataOpts,
|
||||
}, true
|
||||
}
|
||||
|
||||
// Implementation of Instances.CurrentNodeName
|
||||
// Note this is *not* necessarily the same as hostname.
|
||||
func (i *Instances) CurrentNodeName(hostname string) (types.NodeName, error) {
|
||||
md, err := getMetadata()
|
||||
md, err := getMetadata(i.opts.SearchOrder)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -119,7 +123,7 @@ func (i *Instances) InstanceExistsByProviderID(providerID string) (bool, error)
|
|||
// InstanceID returns the kubelet's cloud provider ID.
|
||||
func (os *OpenStack) InstanceID() (string, error) {
|
||||
if len(os.localInstanceID) == 0 {
|
||||
id, err := readInstanceID()
|
||||
id, err := readInstanceID(os.metadataOpts.SearchOrder)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue