Commit 64601373 authored by Doug MacEachern's avatar Doug MacEachern

vsphere: use vim25.Client directly to support token authentication

This refactor is in support of SAML token authentication: #63209 Avoid use of govmomi.Client as it only supports username+password authentication via SessionManager.Login(). Using vim25.Client directly will allow VCP to add other authentication methods, such as SessionManager.LoginByToken().
parent f4b24526
...@@ -18,19 +18,19 @@ package vclib ...@@ -18,19 +18,19 @@ package vclib
import ( import (
"context" "context"
"fmt" "net"
neturl "net/url" neturl "net/url"
"sync" "sync"
"github.com/golang/glog" "github.com/golang/glog"
"github.com/vmware/govmomi"
"github.com/vmware/govmomi/session" "github.com/vmware/govmomi/session"
"github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/soap"
) )
// VSphereConnection contains information for connecting to vCenter // VSphereConnection contains information for connecting to vCenter
type VSphereConnection struct { type VSphereConnection struct {
GoVmomiClient *govmomi.Client GoVmomiClient *vim25.Client
Username string Username string
Password string Password string
Hostname string Hostname string
...@@ -59,7 +59,7 @@ func (connection *VSphereConnection) Connect(ctx context.Context) error { ...@@ -59,7 +59,7 @@ func (connection *VSphereConnection) Connect(ctx context.Context) error {
} }
return nil return nil
} }
m := session.NewManager(connection.GoVmomiClient.Client) m := session.NewManager(connection.GoVmomiClient)
userSession, err := m.UserSession(ctx) userSession, err := m.UserSession(ctx)
if err != nil { if err != nil {
glog.Errorf("Error while obtaining user session. err: %+v", err) glog.Errorf("Error while obtaining user session. err: %+v", err)
...@@ -69,7 +69,7 @@ func (connection *VSphereConnection) Connect(ctx context.Context) error { ...@@ -69,7 +69,7 @@ func (connection *VSphereConnection) Connect(ctx context.Context) error {
return nil return nil
} }
glog.Warningf("Creating new client session since the existing session is not valid or not authenticated") glog.Warningf("Creating new client session since the existing session is not valid or not authenticated")
connection.GoVmomiClient.Logout(ctx)
connection.GoVmomiClient, err = connection.NewClient(ctx) connection.GoVmomiClient, err = connection.NewClient(ctx)
if err != nil { if err != nil {
glog.Errorf("Failed to create govmomi client. err: %+v", err) glog.Errorf("Failed to create govmomi client. err: %+v", err)
...@@ -78,19 +78,36 @@ func (connection *VSphereConnection) Connect(ctx context.Context) error { ...@@ -78,19 +78,36 @@ func (connection *VSphereConnection) Connect(ctx context.Context) error {
return nil return nil
} }
// Logout calls SessionManager.Logout for the given connection.
func (connection *VSphereConnection) Logout(ctx context.Context) {
m := session.NewManager(connection.GoVmomiClient)
if err := m.Logout(ctx); err != nil {
glog.Errorf("Logout failed: %s", err)
}
}
// NewClient creates a new govmomi client for the VSphereConnection obj // NewClient creates a new govmomi client for the VSphereConnection obj
func (connection *VSphereConnection) NewClient(ctx context.Context) (*govmomi.Client, error) { func (connection *VSphereConnection) NewClient(ctx context.Context) (*vim25.Client, error) {
url, err := neturl.Parse(fmt.Sprintf("https://%s:%s/sdk", connection.Hostname, connection.Port)) url, err := soap.ParseURL(net.JoinHostPort(connection.Hostname, connection.Port))
if err != nil { if err != nil {
glog.Errorf("Failed to parse URL: %s. err: %+v", url, err) glog.Errorf("Failed to parse URL: %s. err: %+v", url, err)
return nil, err return nil, err
} }
url.User = neturl.UserPassword(connection.Username, connection.Password)
client, err := govmomi.NewClient(ctx, url, connection.Insecure) sc := soap.NewClient(url, connection.Insecure)
client, err := vim25.NewClient(ctx, sc)
if err != nil { if err != nil {
glog.Errorf("Failed to create new client. err: %+v", err) glog.Errorf("Failed to create new client. err: %+v", err)
return nil, err return nil, err
} }
m := session.NewManager(client)
err = m.Login(ctx, neturl.UserPassword(connection.Username, connection.Password))
if err != nil {
return nil, err
}
if connection.RoundTripperCount == 0 { if connection.RoundTripperCount == 0 {
connection.RoundTripperCount = RoundTripperDefaultCount connection.RoundTripperCount = RoundTripperDefaultCount
} }
......
...@@ -39,7 +39,7 @@ type Datacenter struct { ...@@ -39,7 +39,7 @@ type Datacenter struct {
// GetDatacenter returns the DataCenter Object for the given datacenterPath // GetDatacenter returns the DataCenter Object for the given datacenterPath
// If datacenter is located in a folder, include full path to datacenter else just provide the datacenter name // If datacenter is located in a folder, include full path to datacenter else just provide the datacenter name
func GetDatacenter(ctx context.Context, connection *VSphereConnection, datacenterPath string) (*Datacenter, error) { func GetDatacenter(ctx context.Context, connection *VSphereConnection, datacenterPath string) (*Datacenter, error) {
finder := find.NewFinder(connection.GoVmomiClient.Client, false) finder := find.NewFinder(connection.GoVmomiClient, false)
datacenter, err := finder.Datacenter(ctx, datacenterPath) datacenter, err := finder.Datacenter(ctx, datacenterPath)
if err != nil { if err != nil {
glog.Errorf("Failed to find the datacenter: %s. err: %+v", datacenterPath, err) glog.Errorf("Failed to find the datacenter: %s. err: %+v", datacenterPath, err)
...@@ -52,7 +52,7 @@ func GetDatacenter(ctx context.Context, connection *VSphereConnection, datacente ...@@ -52,7 +52,7 @@ func GetDatacenter(ctx context.Context, connection *VSphereConnection, datacente
// GetAllDatacenter returns all the DataCenter Objects // GetAllDatacenter returns all the DataCenter Objects
func GetAllDatacenter(ctx context.Context, connection *VSphereConnection) ([]*Datacenter, error) { func GetAllDatacenter(ctx context.Context, connection *VSphereConnection) ([]*Datacenter, error) {
var dc []*Datacenter var dc []*Datacenter
finder := find.NewFinder(connection.GoVmomiClient.Client, false) finder := find.NewFinder(connection.GoVmomiClient, false)
datacenters, err := finder.DatacenterList(ctx, "*") datacenters, err := finder.DatacenterList(ctx, "*")
if err != nil { if err != nil {
glog.Errorf("Failed to find the datacenter. err: %+v", err) glog.Errorf("Failed to find the datacenter. err: %+v", err)
......
...@@ -47,7 +47,7 @@ func TestDatacenter(t *testing.T) { ...@@ -47,7 +47,7 @@ func TestDatacenter(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
vc := &VSphereConnection{GoVmomiClient: c} vc := &VSphereConnection{GoVmomiClient: c.Client}
_, err = GetDatacenter(ctx, vc, testNameNotFound) _, err = GetDatacenter(ctx, vc, testNameNotFound)
if err == nil { if err == nil {
......
...@@ -45,7 +45,7 @@ func TestDatastore(t *testing.T) { ...@@ -45,7 +45,7 @@ func TestDatastore(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
vc := &VSphereConnection{GoVmomiClient: c} vc := &VSphereConnection{GoVmomiClient: c.Client}
dc, err := GetDatacenter(ctx, vc, testDefaultDatacenter) dc, err := GetDatacenter(ctx, vc, testDefaultDatacenter)
if err != nil { if err != nil {
......
...@@ -47,7 +47,7 @@ func TestFolder(t *testing.T) { ...@@ -47,7 +47,7 @@ func TestFolder(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
vc := &VSphereConnection{GoVmomiClient: c} vc := &VSphereConnection{GoVmomiClient: c.Client}
dc, err := GetDatacenter(ctx, vc, testDefaultDatacenter) dc, err := GetDatacenter(ctx, vc, testDefaultDatacenter)
if err != nil { if err != nil {
......
...@@ -46,7 +46,7 @@ func TestUtils(t *testing.T) { ...@@ -46,7 +46,7 @@ func TestUtils(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
vc := &VSphereConnection{GoVmomiClient: c} vc := &VSphereConnection{GoVmomiClient: c.Client}
dc, err := GetDatacenter(ctx, vc, testDefaultDatacenter) dc, err := GetDatacenter(ctx, vc, testDefaultDatacenter)
if err != nil { if err != nil {
......
...@@ -23,9 +23,9 @@ import ( ...@@ -23,9 +23,9 @@ import (
"time" "time"
"github.com/golang/glog" "github.com/golang/glog"
"github.com/vmware/govmomi"
"github.com/vmware/govmomi/object" "github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/property" "github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types" "github.com/vmware/govmomi/vim25/types"
) )
...@@ -403,8 +403,8 @@ func (vm *VirtualMachine) deleteController(ctx context.Context, controllerDevice ...@@ -403,8 +403,8 @@ func (vm *VirtualMachine) deleteController(ctx context.Context, controllerDevice
} }
// RenewVM renews this virtual machine with new client connection. // RenewVM renews this virtual machine with new client connection.
func (vm *VirtualMachine) RenewVM(client *govmomi.Client) VirtualMachine { func (vm *VirtualMachine) RenewVM(client *vim25.Client) VirtualMachine {
dc := Datacenter{Datacenter: object.NewDatacenter(client.Client, vm.Datacenter.Reference())} dc := Datacenter{Datacenter: object.NewDatacenter(client, vm.Datacenter.Reference())}
newVM := object.NewVirtualMachine(client.Client, vm.VirtualMachine.Reference()) newVM := object.NewVirtualMachine(client, vm.VirtualMachine.Reference())
return VirtualMachine{VirtualMachine: newVM, Datacenter: &dc} return VirtualMachine{VirtualMachine: newVM, Datacenter: &dc}
} }
...@@ -43,7 +43,7 @@ func TestVirtualMachine(t *testing.T) { ...@@ -43,7 +43,7 @@ func TestVirtualMachine(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
vc := &VSphereConnection{GoVmomiClient: c} vc := &VSphereConnection{GoVmomiClient: c.Client}
dc, err := GetDatacenter(ctx, vc, testDefaultDatacenter) dc, err := GetDatacenter(ctx, vc, testDefaultDatacenter)
if err != nil { if err != nil {
......
...@@ -411,7 +411,7 @@ func newControllerNode(cfg VSphereConfig) (*VSphere, error) { ...@@ -411,7 +411,7 @@ func newControllerNode(cfg VSphereConfig) (*VSphere, error) {
func logout(vs *VSphere) { func logout(vs *VSphere) {
for _, vsphereIns := range vs.vsphereInstanceMap { for _, vsphereIns := range vs.vsphereInstanceMap {
if vsphereIns.conn.GoVmomiClient != nil { if vsphereIns.conn.GoVmomiClient != nil {
vsphereIns.conn.GoVmomiClient.Logout(context.TODO()) vsphereIns.conn.Logout(context.TODO())
} }
} }
......
...@@ -135,7 +135,7 @@ func TestVSphereLogin(t *testing.T) { ...@@ -135,7 +135,7 @@ func TestVSphereLogin(t *testing.T) {
if err != nil { if err != nil {
t.Errorf("Failed to connect to vSphere: %s", err) t.Errorf("Failed to connect to vSphere: %s", err)
} }
defer vcInstance.conn.GoVmomiClient.Logout(ctx) defer vcInstance.conn.Logout(ctx)
} }
func TestZones(t *testing.T) { func TestZones(t *testing.T) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment