Skip to content

Commit

Permalink
Merge pull request kubernetes#7 from dagnello/vsphere-instance
Browse files Browse the repository at this point in the history
VSphere Instance NodeAddresses ExternalID and InstanceID
  • Loading branch information
vipulsabhaya authored and dagnello committed Apr 15, 2016
2 parents f920fa1 + 8638c58 commit cba291d
Show file tree
Hide file tree
Showing 2 changed files with 211 additions and 48 deletions.
215 changes: 179 additions & 36 deletions pkg/cloudprovider/providers/vsphere/vsphere.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (

"github.com/vmware/govmomi"
"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
Expand All @@ -36,20 +37,25 @@ import (
)

const ProviderName = "vsphere"
const ActivePowerState = "poweredOn"

// VSphere is an implementation of Interface, LoadBalancer and Instances for vSphere.
// VSphere is an implementation of cloud provider Interface for VSphere.
type VSphere struct {
cfg *VSphereConfig
}

type VSphereConfig struct {
Global struct {
User string `gcfg:"user"`
Password string `gcfg:"password"`
VCenterIp string `gcfg:"server"`
VCenterPort string `gcfg:"port"`
InsecureFlag bool `gcfg:"insecure-flag"`
Datacenter string `gcfg:"datacenter"`
User string `gcfg:"user"`
Password string `gcfg:"password"`
VCenterIP string `gcfg:"server"`
VCenterPort string `gcfg:"port"`
InsecureFlag bool `gcfg:"insecure-flag"`
Datacenter string `gcfg:"datacenter"`
}

Network struct {
PublicNetwork string `gcfg:"public-network"`
}
}

Expand Down Expand Up @@ -84,7 +90,7 @@ func newVSphere(cfg VSphereConfig) (*VSphere, error) {
func vsphereLogin(cfg *VSphereConfig, ctx context.Context) (*govmomi.Client, error) {

// Parse URL from string
u, err := url.Parse(fmt.Sprintf("https://%s:%s/sdk", cfg.Global.VCenterIp, cfg.Global.VCenterPort))
u, err := url.Parse(fmt.Sprintf("https://%s:%s/sdk", cfg.Global.VCenterIP, cfg.Global.VCenterPort))
if err != nil {
return nil, err
}
Expand All @@ -100,19 +106,49 @@ func vsphereLogin(cfg *VSphereConfig, ctx context.Context) (*govmomi.Client, err
return c, nil
}

type Instances struct {
cfg *VSphereConfig
func getVirtualMachineByName(cfg *VSphereConfig, ctx context.Context, c *govmomi.Client, name string) (*object.VirtualMachine, error){
// Create a new finder
f := find.NewFinder(c.Client, true)

// Fetch and set data center
dc, err := f.Datacenter(ctx, cfg.Global.Datacenter)
if err != nil {
return nil, err
}
f.SetDatacenter(dc)

// Retrieve vm by name
//TODO: also look for vm inside subfolders
vm, err := f.VirtualMachine(ctx, name)
if err != nil {
return nil, err
}

return vm, nil
}

// Instances returns an implementation of Instances for vSphere.
func (vs *VSphere) Instances() (cloudprovider.Instances, bool) {

return &Instances{vs.cfg}, true
func getVirtualMachineManagedObjectReference(ctx context.Context, c *govmomi.Client, vm *object.VirtualMachine, field string, dst interface{}) error{
collector := property.DefaultCollector(c.Client)

// Retrieve required field from VM object
err := collector.RetrieveOne(ctx, vm.Reference(), []string{field}, dst);
if err !=nil {
return err
}
return nil
}

func getInstances(c *govmomi.Client, finder *find.Finder, ctx context.Context, nameFilter string) ([]string, error) {
func getInstances(cfg *VSphereConfig, ctx context.Context, c *govmomi.Client, filter string) ([]string, error) {
f := find.NewFinder(c.Client, true)
dc, err := f.Datacenter(ctx, cfg.Global.Datacenter)
if err != nil {
return nil, err
}

f.SetDatacenter(dc)

//TODO: get all vms inside subfolders
vms, err := finder.VirtualMachineList(ctx, nameFilter)
vms, err := f.VirtualMachineList(ctx, filter)
if err != nil {
return nil, err
}
Expand All @@ -132,45 +168,89 @@ func getInstances(c *govmomi.Client, finder *find.Finder, ctx context.Context, n

var vmList []string
for _, vm := range vmt {
vmPowerstate := vm.Summary.Runtime.PowerState
if vmPowerstate == "poweredOn" {
if vm.Summary.Runtime.PowerState == ActivePowerState {
vmList = append(vmList, vm.Name)
} else if vm.Summary.Config.Template == false {
glog.Warningf("VM %s, is not in %s state", vm.Name, ActivePowerState)
}
}
return vmList, nil
}

func (i *Instances) List(nameFilter string) ([]string, error) {
type Instances struct {
cfg *VSphereConfig
}

// Instances returns an implementation of Instances for vSphere.
func (vs *VSphere) Instances() (cloudprovider.Instances, bool) {
return &Instances{vs.cfg}, true
}

// List is an implementation of Instances.List.
func (i *Instances) List(filter string) ([]string, error) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c, err := vsphereLogin(i.cfg, ctx)
if err != nil {
fmt.Errorf("Failed to create vSpere client: %s", err)
return nil, err
}
defer c.Logout(ctx)

fo := find.NewFinder(c.Client, true)
dc, err := fo.Datacenter(ctx, i.cfg.Global.Datacenter)
vmList, err := getInstances(i.cfg, ctx, c, filter)
if err != nil {
glog.Warningf("Failed to find %v", err)
return nil, err
}

finderObj := fo.SetDatacenter(dc)
vmList, err := getInstances(c, finderObj, ctx, nameFilter)
glog.V(3).Infof("Found %s instances matching %s: %s",
len(vmList), filter, vmList)

return vmList, nil
}

// NodeAddresses is an implementation of Instances.NodeAddresses.
func (i *Instances) NodeAddresses(name string) ([]api.NodeAddress, error) {
addrs := []api.NodeAddress{}

// Create context
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

// Create vSphere client
c, err := vsphereLogin(i.cfg, ctx)
if err != nil {
return nil, err
}
defer c.Logout(ctx)

glog.V(3).Infof("Found %v instances matching %v: %v",
len(vmList), nameFilter, vmList)
vm, err := getVirtualMachineByName(i.cfg, ctx, c, name)
if err !=nil {
return nil, err
}

return vmList, nil
}
var mvm mo.VirtualMachine
err = getVirtualMachineManagedObjectReference(ctx, c, vm, "guest.net", &mvm)
if err !=nil {
return nil, err
}

func (i *Instances) NodeAddresses(name string) ([]api.NodeAddress, error) {
return nil, nil
// retrieve VM's ip(s)
for _, v := range mvm.Guest.Net {
var addressType api.NodeAddressType
if i.cfg.Network.PublicNetwork == v.Network {
addressType = api.NodeExternalIP
} else {
addressType = api.NodeInternalIP
}
for _, ip := range v.IpAddress {
api.AddToNodeAddresses(&addrs,
api.NodeAddress{
Type: addressType,
Address: ip,
},
)
}
}
return addrs, nil
}

func (i *Instances) AddSSHKeyToAllInstances(user string, keyData []byte) error {
Expand All @@ -181,16 +261,79 @@ func (i *Instances) CurrentNodeName(hostname string) (string, error) {
return hostname, nil
}

// ExternalID returns the cloud provider ID of the specified instance (deprecated).
func (i *Instances) ExternalID(name string) (string, error) {
return "", nil
}
// Create context
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

func (i *Instances) InstanceType(name string) (string, error) {
return "", nil
// Create vSphere client
c, err := vsphereLogin(i.cfg, ctx)
if err != nil {
return "", err
}
defer c.Logout(ctx)

vm, err := getVirtualMachineByName(i.cfg, ctx, c, name)
if err != nil {
return "", err
}

var mvm mo.VirtualMachine
err = getVirtualMachineManagedObjectReference(ctx, c, vm, "summary", &mvm)
if err !=nil {
return "", err
}

if mvm.Summary.Runtime.PowerState == ActivePowerState {
return vm.InventoryPath, nil
}

if mvm.Summary.Config.Template == false {
glog.Warningf("VM %s, is not in %s state", name, ActivePowerState)
} else {
glog.Warningf("VM %s, is a template", name)
}

return "", cloudprovider.InstanceNotFound
}

// InstanceID returns the cloud provider ID of the specified instance.
func (i *Instances) InstanceID(name string) (string, error) {
return "/" + " ", nil
// Create context
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

// Create vSphere client
c, err := vsphereLogin(i.cfg, ctx)
if err != nil {
return "", err
}
defer c.Logout(ctx)

vm, err := getVirtualMachineByName(i.cfg, ctx, c, name)

var mvm mo.VirtualMachine
err = getVirtualMachineManagedObjectReference(ctx, c, vm, "summary", &mvm)
if err !=nil {
return "", err
}

if mvm.Summary.Runtime.PowerState == ActivePowerState {
return "/" + vm.InventoryPath, nil
}

if mvm.Summary.Config.Template == false {
glog.Warning("VM %s, is not in %s state", name, ActivePowerState)
} else {
glog.Warning("VM %s, is a template", name)
}

return "", cloudprovider.InstanceNotFound
}

func (i *Instances) InstanceType(name string) (string, error) {
return "", nil
}

func (vs *VSphere) Clusters() (cloudprovider.Clusters, bool) {
Expand Down
44 changes: 32 additions & 12 deletions pkg/cloudprovider/providers/vsphere/vsphere_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,23 @@ import (
)

func configFromEnv() (cfg VSphereConfig, ok bool) {
cfg.Global.VCenterIp = os.Getenv("VSPHERE_VCENTER")
cfg.Global.VCenterIP = os.Getenv("VSPHERE_VCENTER")
cfg.Global.VCenterPort = os.Getenv("VSPHERE_VCENTER_PORT")
cfg.Global.User = os.Getenv("VSPHERE_USER")
cfg.Global.Password = os.Getenv("VSPHERE_PASSWORD")
cfg.Global.Datacenter = os.Getenv("VSPHERE_DATACENTER")

InsecureFlag, err := strconv.ParseBool(os.Getenv("VSPHERE_INSECURE"))
if err != nil {
log.Fatal(err)
}

cfg.Global.InsecureFlag = InsecureFlag

ok = (cfg.Global.VCenterIp != "" &&
cfg.Network.PublicNetwork = os.Getenv("VSPHERE_PUBLIC_NETWORK")
if os.Getenv("VSPHERE_INSECURE") != "" {
insecureFlag, err := strconv.ParseBool(os.Getenv("VSPHERE_INSECURE"))
if err != nil {
log.Fatal(err)
}
cfg.Global.InsecureFlag = insecureFlag
} else {
cfg.Global.InsecureFlag = false
}

ok = (cfg.Global.VCenterIP != "" &&
cfg.Global.User != "")

return
Expand All @@ -65,8 +68,8 @@ datacenter = us-west
t.Fatalf("Should succeed when a valid config is provided: %s", err)
}

if cfg.Global.VCenterIp != "0.0.0.0" {
t.Errorf("incorrect vcenter ip: %s", cfg.Global.VCenterIp)
if cfg.Global.VCenterIP != "0.0.0.0" {
t.Errorf("incorrect vcenter ip: %s", cfg.Global.VCenterIP)
}

if cfg.Global.VCenterPort != "443" {
Expand Down Expand Up @@ -165,4 +168,21 @@ func TestInstances(t *testing.T) {
}
t.Logf("Found servers (%d): %s\n", len(srvs), srvs)

externalId, err := i.ExternalID(srvs[0])
if err != nil {
t.Fatalf("Instances.ExternalID(%s) failed: %s", srvs[0], err)
}
t.Logf("Found ExternalID(%s) = %s\n", srvs[0], externalId)

instanceId, err := i.InstanceID(srvs[0])
if err != nil {
t.Fatalf("Instances.InstanceID(%s) failed: %s", srvs[0], err)
}
t.Logf("Found InstanceID(%s) = %s\n", srvs[0], instanceId)

addrs, err := i.NodeAddresses(srvs[0])
if err != nil {
t.Fatalf("Instances.NodeAddresses(%s) failed: %s", srvs[0], err)
}
t.Logf("Found NodeAddresses(%s) = %s\n", srvs[0], addrs)
}

0 comments on commit cba291d

Please sign in to comment.