mirror of https://github.com/k3s-io/k3s
- Updated vmware/govmomi godep (Needs for vsan support)
- Fix unmount for vsanDatastore - Add support for vsan datastorepull/6/head
parent
2301ab7e0e
commit
87e7535e94
|
@ -2015,78 +2015,78 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "github.com/vmware/govmomi",
|
||||
"Comment": "v0.6.2",
|
||||
"Rev": "9051bd6b44125d9472e0c148b5965692ab283d4a"
|
||||
"Comment": "v0.8.0-9-gb5ee639",
|
||||
"Rev": "b5ee639d7aa4b8dbb48ab4f75dddc19f71b5c514"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vmware/govmomi/find",
|
||||
"Comment": "v0.6.2",
|
||||
"Rev": "9051bd6b44125d9472e0c148b5965692ab283d4a"
|
||||
"Comment": "v0.8.0-9-gb5ee639",
|
||||
"Rev": "b5ee639d7aa4b8dbb48ab4f75dddc19f71b5c514"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vmware/govmomi/list",
|
||||
"Comment": "v0.6.2",
|
||||
"Rev": "9051bd6b44125d9472e0c148b5965692ab283d4a"
|
||||
"Comment": "v0.8.0-9-gb5ee639",
|
||||
"Rev": "b5ee639d7aa4b8dbb48ab4f75dddc19f71b5c514"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vmware/govmomi/object",
|
||||
"Comment": "v0.6.2",
|
||||
"Rev": "9051bd6b44125d9472e0c148b5965692ab283d4a"
|
||||
"Comment": "v0.8.0-9-gb5ee639",
|
||||
"Rev": "b5ee639d7aa4b8dbb48ab4f75dddc19f71b5c514"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vmware/govmomi/property",
|
||||
"Comment": "v0.6.2",
|
||||
"Rev": "9051bd6b44125d9472e0c148b5965692ab283d4a"
|
||||
"Comment": "v0.8.0-9-gb5ee639",
|
||||
"Rev": "b5ee639d7aa4b8dbb48ab4f75dddc19f71b5c514"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vmware/govmomi/session",
|
||||
"Comment": "v0.6.2",
|
||||
"Rev": "9051bd6b44125d9472e0c148b5965692ab283d4a"
|
||||
"Comment": "v0.8.0-9-gb5ee639",
|
||||
"Rev": "b5ee639d7aa4b8dbb48ab4f75dddc19f71b5c514"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vmware/govmomi/task",
|
||||
"Comment": "v0.6.2",
|
||||
"Rev": "9051bd6b44125d9472e0c148b5965692ab283d4a"
|
||||
"Comment": "v0.8.0-9-gb5ee639",
|
||||
"Rev": "b5ee639d7aa4b8dbb48ab4f75dddc19f71b5c514"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vmware/govmomi/vim25",
|
||||
"Comment": "v0.6.2",
|
||||
"Rev": "9051bd6b44125d9472e0c148b5965692ab283d4a"
|
||||
"Comment": "v0.8.0-9-gb5ee639",
|
||||
"Rev": "b5ee639d7aa4b8dbb48ab4f75dddc19f71b5c514"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vmware/govmomi/vim25/debug",
|
||||
"Comment": "v0.6.2",
|
||||
"Rev": "9051bd6b44125d9472e0c148b5965692ab283d4a"
|
||||
"Comment": "v0.8.0-9-gb5ee639",
|
||||
"Rev": "b5ee639d7aa4b8dbb48ab4f75dddc19f71b5c514"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vmware/govmomi/vim25/methods",
|
||||
"Comment": "v0.6.2",
|
||||
"Rev": "9051bd6b44125d9472e0c148b5965692ab283d4a"
|
||||
"Comment": "v0.8.0-9-gb5ee639",
|
||||
"Rev": "b5ee639d7aa4b8dbb48ab4f75dddc19f71b5c514"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vmware/govmomi/vim25/mo",
|
||||
"Comment": "v0.6.2",
|
||||
"Rev": "9051bd6b44125d9472e0c148b5965692ab283d4a"
|
||||
"Comment": "v0.8.0-9-gb5ee639",
|
||||
"Rev": "b5ee639d7aa4b8dbb48ab4f75dddc19f71b5c514"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vmware/govmomi/vim25/progress",
|
||||
"Comment": "v0.6.2",
|
||||
"Rev": "9051bd6b44125d9472e0c148b5965692ab283d4a"
|
||||
"Comment": "v0.8.0-9-gb5ee639",
|
||||
"Rev": "b5ee639d7aa4b8dbb48ab4f75dddc19f71b5c514"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vmware/govmomi/vim25/soap",
|
||||
"Comment": "v0.6.2",
|
||||
"Rev": "9051bd6b44125d9472e0c148b5965692ab283d4a"
|
||||
"Comment": "v0.8.0-9-gb5ee639",
|
||||
"Rev": "b5ee639d7aa4b8dbb48ab4f75dddc19f71b5c514"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vmware/govmomi/vim25/types",
|
||||
"Comment": "v0.6.2",
|
||||
"Rev": "9051bd6b44125d9472e0c148b5965692ab283d4a"
|
||||
"Comment": "v0.8.0-9-gb5ee639",
|
||||
"Rev": "b5ee639d7aa4b8dbb48ab4f75dddc19f71b5c514"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vmware/govmomi/vim25/xml",
|
||||
"Comment": "v0.6.2",
|
||||
"Rev": "9051bd6b44125d9472e0c148b5965692ab283d4a"
|
||||
"Comment": "v0.8.0-9-gb5ee639",
|
||||
"Rev": "b5ee639d7aa4b8dbb48ab4f75dddc19f71b5c514"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/xiang90/probing",
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"net"
|
||||
"net/url"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi"
|
||||
|
@ -74,24 +75,35 @@ type VSphere struct {
|
|||
|
||||
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"`
|
||||
Datastore string `gcfg:"datastore"`
|
||||
WorkingDir string `gcfg:"working-dir"`
|
||||
// vCenter username.
|
||||
User string `gcfg:"user"`
|
||||
// vCenter password in clear text.
|
||||
Password string `gcfg:"password"`
|
||||
// vCenter IP.
|
||||
VCenterIP string `gcfg:"server"`
|
||||
// vCenter port.
|
||||
VCenterPort string `gcfg:"port"`
|
||||
// True if vCenter uses self-signed cert.
|
||||
InsecureFlag bool `gcfg:"insecure-flag"`
|
||||
// Datacenter in which VMs are located.
|
||||
Datacenter string `gcfg:"datacenter"`
|
||||
// Datastore in which vmdks are stored.
|
||||
Datastore string `gcfg:"datastore"`
|
||||
// WorkingDir is path where VMs can be found.
|
||||
WorkingDir string `gcfg:"working-dir"`
|
||||
}
|
||||
|
||||
Network struct {
|
||||
// PublicNetwork is name of the network the VMs are joined to.
|
||||
PublicNetwork string `gcfg:"public-network"`
|
||||
}
|
||||
Disk struct {
|
||||
// SCSIControllerType defines SCSI controller to be used.
|
||||
SCSIControllerType string `dcfg:"scsicontrollertype"`
|
||||
}
|
||||
}
|
||||
|
||||
// Parses vSphere cloud config file and stores it into VSphereConfig.
|
||||
func readConfig(config io.Reader) (VSphereConfig, error) {
|
||||
if config == nil {
|
||||
err := fmt.Errorf("no vSphere cloud provider config file given")
|
||||
|
@ -113,6 +125,9 @@ func init() {
|
|||
})
|
||||
}
|
||||
|
||||
// Returns the name of the VM on which this code is running.
|
||||
// This is done by searching for the name of virtual machine by current IP.
|
||||
// Prerequisite: this code assumes VMWare vmtools or open-vm-tools to be installed in the VM.
|
||||
func readInstanceID(cfg *VSphereConfig) (string, error) {
|
||||
addrs, err := net.InterfaceAddrs()
|
||||
if err != nil {
|
||||
|
@ -153,6 +168,7 @@ func readInstanceID(cfg *VSphereConfig) (string, error) {
|
|||
return "", fmt.Errorf("unable to parse cidr from ip")
|
||||
}
|
||||
|
||||
// Finds a virtual machine or host by IP address.
|
||||
svm, err = s.FindByIp(ctx, dc, ip.String(), true)
|
||||
if err == nil && svm != nil {
|
||||
break
|
||||
|
@ -192,6 +208,7 @@ func newVSphere(cfg VSphereConfig) (*VSphere, error) {
|
|||
return &vs, nil
|
||||
}
|
||||
|
||||
// Returns if the given controller type is supported by the plugin
|
||||
func checkControllerSupported(ctrlType string) bool {
|
||||
for _, c := range supportedSCSIControllerType {
|
||||
if ctrlType == c {
|
||||
|
@ -201,8 +218,9 @@ func checkControllerSupported(ctrlType string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// Returns a client which communicates with vCenter.
|
||||
// This client can used to perform further vCenter operations.
|
||||
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))
|
||||
if err != nil {
|
||||
|
@ -220,6 +238,7 @@ func vsphereLogin(cfg *VSphereConfig, ctx context.Context) (*govmomi.Client, err
|
|||
return c, nil
|
||||
}
|
||||
|
||||
// Returns vSphere object `virtual machine` by its name.
|
||||
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)
|
||||
|
@ -254,6 +273,7 @@ func getVirtualMachineManagedObjectReference(ctx context.Context, c *govmomi.Cli
|
|||
return nil
|
||||
}
|
||||
|
||||
// Returns names of running VMs inside VM folder.
|
||||
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)
|
||||
|
@ -305,7 +325,7 @@ func (vs *VSphere) Instances() (cloudprovider.Instances, bool) {
|
|||
return &Instances{vs.cfg, vs.localInstanceID}, true
|
||||
}
|
||||
|
||||
// List is an implementation of Instances.List.
|
||||
// List returns names of VMs (inside vm folder) by applying filter and which are currently running.
|
||||
func (i *Instances) List(filter string) ([]string, error) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
@ -492,40 +512,40 @@ func (vs *VSphere) ScrubDNS(nameservers, searches []string) (nsOut, srchOut []st
|
|||
return nameservers, searches
|
||||
}
|
||||
|
||||
func getVirtualMachineDevices(cfg *VSphereConfig, ctx context.Context, c *govmomi.Client, name string) (*object.VirtualMachine, object.VirtualDeviceList, *object.Datastore, error) {
|
||||
|
||||
// Returns vSphere objects virtual machine, virtual device list, datastore and datacenter.
|
||||
func getVirtualMachineDevices(cfg *VSphereConfig, ctx context.Context, c *govmomi.Client, name string) (*object.VirtualMachine, object.VirtualDeviceList, *object.Datastore, *object.Datacenter, 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, nil, nil, err
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
f.SetDatacenter(dc)
|
||||
|
||||
// Find datastores
|
||||
ds, err := f.Datastore(ctx, cfg.Global.Datastore)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
|
||||
vmRegex := cfg.Global.WorkingDir + name
|
||||
|
||||
vm, err := f.VirtualMachine(ctx, vmRegex)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
|
||||
// Get devices from VM
|
||||
vmDevices, err := vm.Device(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
return vm, vmDevices, ds, nil
|
||||
return vm, vmDevices, ds, dc, nil
|
||||
}
|
||||
|
||||
//cleaning up the controller
|
||||
// Removes SCSI controller which is latest attached to VM.
|
||||
func cleanUpController(newSCSIController types.BaseVirtualDevice, vmDevices object.VirtualDeviceList, vm *object.VirtualMachine, ctx context.Context) error {
|
||||
ctls := vmDevices.SelectByType(newSCSIController)
|
||||
if len(ctls) < 1 {
|
||||
|
@ -561,7 +581,7 @@ func (vs *VSphere) AttachDisk(vmDiskPath string, nodeName string) (diskID string
|
|||
}
|
||||
|
||||
// Get VM device list
|
||||
vm, vmDevices, ds, err := getVirtualMachineDevices(vs.cfg, ctx, c, vSphereInstance)
|
||||
vm, vmDevices, ds, _, err := getVirtualMachineDevices(vs.cfg, ctx, c, vSphereInstance)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
@ -606,7 +626,7 @@ func (vs *VSphere) AttachDisk(vmDiskPath string, nodeName string) (diskID string
|
|||
// verify scsi controller in virtual machine
|
||||
vmDevices, err = vm.Device(ctx)
|
||||
if err != nil {
|
||||
//cannot cleanup if there is no device list
|
||||
// cannot cleanup if there is no device list
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
|
@ -747,33 +767,77 @@ func getAvailableSCSIController(scsiControllers []*types.VirtualController) *typ
|
|||
return nil
|
||||
}
|
||||
|
||||
// Returns formatted UUID for a virtual disk device.
|
||||
func getVirtualDiskUUID(newDevice types.BaseVirtualDevice) (string, error) {
|
||||
vd := newDevice.GetVirtualDevice()
|
||||
|
||||
if b, ok := vd.Backing.(*types.VirtualDiskFlatVer2BackingInfo); ok {
|
||||
uuidWithNoHypens := strings.Replace(b.Uuid, "-", "", -1)
|
||||
return strings.ToLower(uuidWithNoHypens), nil
|
||||
uuid := formatVirtualDiskUUID(b.Uuid)
|
||||
return uuid, nil
|
||||
}
|
||||
return "", ErrNoDiskUUIDFound
|
||||
}
|
||||
|
||||
func getVirtualDiskID(volPath string, vmDevices object.VirtualDeviceList) (string, error) {
|
||||
func formatVirtualDiskUUID(uuid string) string {
|
||||
uuidwithNoSpace := strings.Replace(uuid, " ", "", -1)
|
||||
uuidWithNoHypens := strings.Replace(uuidwithNoSpace, "-", "", -1)
|
||||
return strings.ToLower(uuidWithNoHypens)
|
||||
}
|
||||
|
||||
// Gets virtual disk UUID by datastore (namespace) path
|
||||
//
|
||||
// volPath can be namespace path (e.g. "[vsanDatastore] volumes/test.vmdk") or
|
||||
// uuid path (e.g. "[vsanDatastore] 59427457-6c5a-a917-7997-0200103eedbc/test.vmdk").
|
||||
// `volumes` in this case would be a symlink to
|
||||
// `59427457-6c5a-a917-7997-0200103eedbc`.
|
||||
//
|
||||
// We want users to use namespace path. It is good for attaching the disk,
|
||||
// but for detaching the API requires uuid path. Hence, to detach the right
|
||||
// device we have to convert the namespace path to uuid path.
|
||||
func getVirtualDiskUUIDByPath(volPath string, dc *object.Datacenter, client *govmomi.Client) (string, error) {
|
||||
if len(volPath) > 0 && filepath.Ext(volPath) != ".vmdk" {
|
||||
volPath += ".vmdk"
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
// VirtualDiskManager provides a way to manage and manipulate virtual disks on vmware datastores.
|
||||
vdm := object.NewVirtualDiskManager(client.Client)
|
||||
// Returns uuid of vmdk virtual disk
|
||||
diskUUID, err := vdm.QueryVirtualDiskUuid(ctx, volPath, dc)
|
||||
|
||||
if err != nil {
|
||||
return "", ErrNoDiskUUIDFound
|
||||
}
|
||||
|
||||
diskUUID = formatVirtualDiskUUID(diskUUID)
|
||||
|
||||
return diskUUID, nil
|
||||
}
|
||||
|
||||
// Returns a device id which is internal vSphere API identifier for the attached virtual disk.
|
||||
func getVirtualDiskID(volPath string, vmDevices object.VirtualDeviceList, dc *object.Datacenter, client *govmomi.Client) (string, error) {
|
||||
volumeUUID, err := getVirtualDiskUUIDByPath(volPath, dc, client)
|
||||
|
||||
if err != nil {
|
||||
glog.Warningf("disk uuid not found for %v ", volPath)
|
||||
return "", err
|
||||
}
|
||||
|
||||
// filter vm devices to retrieve disk ID for the given vmdk file
|
||||
for _, device := range vmDevices {
|
||||
if vmDevices.TypeName(device) == "VirtualDisk" {
|
||||
d := device.GetVirtualDevice()
|
||||
if b, ok := d.Backing.(types.BaseVirtualDeviceFileBackingInfo); ok {
|
||||
fileName := b.GetVirtualDeviceFileBackingInfo().FileName
|
||||
if fileName == volPath {
|
||||
return vmDevices.Name(device), nil
|
||||
}
|
||||
diskUUID, _ := getVirtualDiskUUID(device)
|
||||
if diskUUID == volumeUUID {
|
||||
return vmDevices.Name(device), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return "", ErrNoDiskIDFound
|
||||
}
|
||||
|
||||
// Detaches given virtual disk volume from the compute running kubelet.
|
||||
// DetachDisk detaches given virtual disk volume from the compute running kubelet.
|
||||
func (vs *VSphere) DetachDisk(volPath string, nodeName string) error {
|
||||
// Create context
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
@ -794,23 +858,24 @@ func (vs *VSphere) DetachDisk(volPath string, nodeName string) error {
|
|||
vSphereInstance = nodeName
|
||||
}
|
||||
|
||||
vm, vmDevices, _, err := getVirtualMachineDevices(vs.cfg, ctx, c, vSphereInstance)
|
||||
vm, vmDevices, _, dc, err := getVirtualMachineDevices(vs.cfg, ctx, c, vSphereInstance)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
diskID, err := getVirtualDiskID(volPath, vmDevices)
|
||||
diskID, err := getVirtualDiskID(volPath, vmDevices, dc, c)
|
||||
if err != nil {
|
||||
glog.Warningf("disk ID not found for %v ", volPath)
|
||||
return err
|
||||
}
|
||||
|
||||
// Remove disk from VM
|
||||
// Gets virtual disk device
|
||||
device := vmDevices.Find(diskID)
|
||||
if device == nil {
|
||||
return fmt.Errorf("device '%s' not found", diskID)
|
||||
}
|
||||
|
||||
// Detach disk from VM
|
||||
err = vm.RemoveDevice(ctx, true, device)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -819,7 +884,7 @@ func (vs *VSphere) DetachDisk(volPath string, nodeName string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Create a volume of given size (in KiB).
|
||||
// CreateVolume creates a volume of given size (in KiB).
|
||||
func (vs *VSphere) CreateVolume(name string, size int, tags *map[string]string) (volumePath string, err error) {
|
||||
// Create context
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
@ -865,7 +930,7 @@ func (vs *VSphere) CreateVolume(name string, size int, tags *map[string]string)
|
|||
return vmDiskPath, nil
|
||||
}
|
||||
|
||||
// Deletes a volume given volume name.
|
||||
// DeleteVolume deletes a volume given volume name.
|
||||
func (vs *VSphere) DeleteVolume(vmDiskPath string) error {
|
||||
// Create context
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
|
|
@ -292,11 +292,13 @@ func (v *vsphereVolumeUnmounter) TearDownAt(dir string) error {
|
|||
return fmt.Errorf("directory %s is not mounted", dir)
|
||||
}
|
||||
|
||||
mountPath := refs[0]
|
||||
// Assumption: No file or folder is named starting with '[' in datastore
|
||||
volumePath := mountPath[strings.LastIndex(mountPath, "["):]
|
||||
// space between datastore and vmdk name in volumePath is encoded as '\040' when returned by GetMountRefs().
|
||||
// volumePath eg: "[local] xxx.vmdk" provided to attach/mount
|
||||
// replacing \040 with space to match the actual volumePath
|
||||
mountPath := strings.Replace(path.Base(refs[0]), "\\040", " ", -1)
|
||||
v.volPath = mountPath
|
||||
v.volPath = strings.Replace(volumePath, "\\040", " ", -1)
|
||||
glog.V(4).Infof("Found volume %s mounted to %s", v.volPath, dir)
|
||||
|
||||
// Reload list of references, there might be SetUpAt finished in the meantime
|
||||
|
|
|
@ -1,5 +1,35 @@
|
|||
# changelog
|
||||
|
||||
### 0.8.0 (2016-06-30)
|
||||
|
||||
* Add session.Manager.AcquireLocalTicket
|
||||
|
||||
* Include StoragePod in Finder.FolderList
|
||||
|
||||
* Add Finder methods for finding by ManagedObjectReference: Element, ObjectReference
|
||||
|
||||
* Add mo.ManagedObjectReference methods: Reference, String, FromString
|
||||
|
||||
* Add support using SessionManagerGenericServiceTicket.HostName for Datastore HTTP access
|
||||
|
||||
### 0.7.1 (2016-06-03)
|
||||
|
||||
* Fix object.ObjectName method
|
||||
|
||||
### 0.7.0 (2016-06-02)
|
||||
|
||||
* Move InventoryPath field to object.Common
|
||||
|
||||
* Add HostDatastoreSystem.CreateLocalDatastore method
|
||||
|
||||
* Add DatastoreNamespaceManager methods: CreateDirectory, DeleteDirectory
|
||||
|
||||
* Add HostServiceSystem
|
||||
|
||||
* Add HostStorageSystem methods: MarkAsSdd, MarkAsNonSdd, MarkAsLocal, MarkAsNonLocal
|
||||
|
||||
* Add HostStorageSystem.RescanAllHba method
|
||||
|
||||
### 0.6.2 (2016-05-11)
|
||||
|
||||
* Get complete file details in Datastore.Stat
|
||||
|
|
|
@ -9,10 +9,8 @@ Change _$USER_ below to your github username if they are not the same.
|
|||
|
||||
``` shell
|
||||
export GOPATH=$HOME/govmomi
|
||||
mkdir -p $GOPATH/src/github.com/vmware
|
||||
cd $GOPATH/src/github.com/vmware
|
||||
git clone git@github.com:vmware/govmomi.git
|
||||
cd govmomi
|
||||
go get github.com/vmware/govmomi
|
||||
cd $GOPATH/src/github.com/vmware/govmomi
|
||||
git config push.default nothing # anything to avoid pushing to vmware/govmomi by default
|
||||
git remote rename origin vmware
|
||||
git remote add $USER git@github.com:$USER/govmomi.git
|
||||
|
@ -26,6 +24,7 @@ This is a rough outline of what a contributor's workflow looks like:
|
|||
- Create a topic branch from where you want to base your work.
|
||||
- Make commits of logical units.
|
||||
- Make sure your commit messages are in the proper format (see below).
|
||||
- Update CHANGELOG.md and/or govc/CHANGELOG.md when appropriate.
|
||||
- Push your changes to a topic branch in your fork of the repository.
|
||||
- Submit a pull request to vmware/govmomi.
|
||||
|
||||
|
|
|
@ -10,10 +10,12 @@ Arran Walker <arran.walker@zopa.com>
|
|||
Austin Parker <aparker@apprenda.com>
|
||||
Bob Killen <killen.bob@gmail.com>
|
||||
Bruce Downs <bdowns@vmware.com>
|
||||
Clint Greenwood <cgreenwood@vmware.com> <clint.greenwood@gmail.com>
|
||||
Cédric Blomart <cblomart@gmail.com>
|
||||
Christian Höltje <docwhat@gerf.org>
|
||||
Clint Greenwood <cgreenwood@vmware.com> <clint.greenwood@gmail.com>
|
||||
Danny Lockard <danny.lockard@banno.com>
|
||||
Dave Tucker <dave@dtucker.co.uk>
|
||||
David Stark <dave@davidstark.name>
|
||||
Doug MacEachern <dougm@vmware.com>
|
||||
Eloy Coto <eloy.coto@gmail.com>
|
||||
Eric Yutao <eric.yutao@gmail.com>
|
||||
|
@ -31,8 +33,8 @@ Pieter Noordhuis <pnoordhuis@vmware.com> <pcnoordhuis@gmail.com>
|
|||
runner.mei <runner.mei@gmail.com>
|
||||
S.Çağlar Onur <conur@vmware.com>
|
||||
Sergey Ignatov <sergey.ignatov@jetbrains.com>
|
||||
Takaaki Furukawa <takaaki.frkw@gmail.com> <takaaki.furukawa@mail.rakuten.com>
|
||||
Steve Purcell <steve@sanityinc.com>
|
||||
Takaaki Furukawa <takaaki.frkw@gmail.com> <takaaki.furukawa@mail.rakuten.com>
|
||||
Yang Yang <yangy@vmware.com>
|
||||
Yuya Kusakabe <yuya.kusakabe@gmail.com>
|
||||
Zach Tucker <ztucker@vmware.com>
|
||||
|
|
|
@ -4,21 +4,17 @@ all: check test
|
|||
|
||||
check: goimports govet
|
||||
|
||||
vendor:
|
||||
go get golang.org/x/tools/cmd/goimports
|
||||
go get github.com/davecgh/go-spew/spew
|
||||
go get golang.org/x/net/context
|
||||
|
||||
goimports: vendor
|
||||
goimports:
|
||||
@echo checking go imports...
|
||||
@go get golang.org/x/tools/cmd/goimports
|
||||
@! goimports -d . 2>&1 | egrep -v '^$$'
|
||||
|
||||
govet:
|
||||
@echo checking go vet...
|
||||
@go tool vet -structtags=false -methods=false .
|
||||
|
||||
test: vendor
|
||||
test:
|
||||
go test -v $(TEST_OPTS) ./...
|
||||
|
||||
install: vendor
|
||||
install:
|
||||
go install github.com/vmware/govmomi/govc
|
||||
|
|
|
@ -25,6 +25,7 @@ import (
|
|||
"github.com/vmware/govmomi/property"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
|
@ -192,6 +193,48 @@ func (f *Finder) managedObjectList(ctx context.Context, path string, tl bool) ([
|
|||
return f.find(ctx, fn, tl, path)
|
||||
}
|
||||
|
||||
// Element returns an Element for the given ManagedObjectReference
|
||||
// This method is only useful for looking up the InventoryPath of a ManagedObjectReference.
|
||||
func (f *Finder) Element(ctx context.Context, ref types.ManagedObjectReference) (*list.Element, error) {
|
||||
rl := func(_ context.Context) (object.Reference, error) {
|
||||
return ref, nil
|
||||
}
|
||||
|
||||
e, err := f.find(ctx, rl, false, ".")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(e) == 0 {
|
||||
return nil, &NotFoundError{ref.Type, ref.Value}
|
||||
}
|
||||
|
||||
if len(e) > 1 {
|
||||
panic("ManagedObjectReference must be unique")
|
||||
}
|
||||
|
||||
return &e[0], nil
|
||||
}
|
||||
|
||||
// ObjectReference converts the given ManagedObjectReference to a type from the object package via object.NewReference
|
||||
// with the object.Common.InventoryPath field set.
|
||||
func (f *Finder) ObjectReference(ctx context.Context, ref types.ManagedObjectReference) (object.Reference, error) {
|
||||
e, err := f.Element(ctx, ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r := object.NewReference(f.client, ref)
|
||||
|
||||
type common interface {
|
||||
SetInventoryPath(string)
|
||||
}
|
||||
|
||||
r.(common).SetInventoryPath(e.Path)
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (f *Finder) ManagedObjectList(ctx context.Context, path string) ([]list.Element, error) {
|
||||
return f.managedObjectList(ctx, path, false)
|
||||
}
|
||||
|
@ -210,7 +253,9 @@ func (f *Finder) DatacenterList(ctx context.Context, path string) ([]*object.Dat
|
|||
for _, e := range es {
|
||||
ref := e.Object.Reference()
|
||||
if ref.Type == "Datacenter" {
|
||||
dcs = append(dcs, object.NewDatacenter(f.client, ref))
|
||||
dc := object.NewDatacenter(f.client, ref)
|
||||
dc.InventoryPath = e.Path
|
||||
dcs = append(dcs, dc)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -772,7 +817,7 @@ func (f *Finder) FolderList(ctx context.Context, path string) ([]*object.Folder,
|
|||
|
||||
for _, e := range es {
|
||||
switch o := e.Object.(type) {
|
||||
case mo.Folder:
|
||||
case mo.Folder, mo.StoragePod:
|
||||
folder := object.NewFolder(f.client, o.Reference())
|
||||
folder.InventoryPath = e.Path
|
||||
folders = append(folders, folder)
|
||||
|
|
|
@ -25,8 +25,6 @@ import (
|
|||
|
||||
type ClusterComputeResource struct {
|
||||
ComputeResource
|
||||
|
||||
InventoryPath string
|
||||
}
|
||||
|
||||
func NewClusterComputeResource(c *vim25.Client, ref types.ManagedObjectReference) *ClusterComputeResource {
|
||||
|
|
|
@ -19,10 +19,12 @@ package object
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"github.com/vmware/govmomi/property"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/methods"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
@ -33,12 +35,20 @@ var (
|
|||
|
||||
// Common contains the fields and functions common to all objects.
|
||||
type Common struct {
|
||||
InventoryPath string
|
||||
|
||||
c *vim25.Client
|
||||
r types.ManagedObjectReference
|
||||
}
|
||||
|
||||
func (c Common) String() string {
|
||||
return fmt.Sprintf("%v", c.Reference())
|
||||
ref := fmt.Sprintf("%v", c.Reference())
|
||||
|
||||
if c.InventoryPath == "" {
|
||||
return ref
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s @ %s", ref, c.InventoryPath)
|
||||
}
|
||||
|
||||
func NewCommon(c *vim25.Client, r types.ManagedObjectReference) Common {
|
||||
|
@ -53,6 +63,36 @@ func (c Common) Client() *vim25.Client {
|
|||
return c.c
|
||||
}
|
||||
|
||||
// Name returns the base name of the InventoryPath field
|
||||
func (c Common) Name() string {
|
||||
if c.InventoryPath == "" {
|
||||
return ""
|
||||
}
|
||||
return path.Base(c.InventoryPath)
|
||||
}
|
||||
|
||||
func (c *Common) SetInventoryPath(p string) {
|
||||
c.InventoryPath = p
|
||||
}
|
||||
|
||||
// ObjectName returns the base name of the InventoryPath field if set,
|
||||
// otherwise fetches the mo.ManagedEntity.Name field via the property collector.
|
||||
func (c Common) ObjectName(ctx context.Context) (string, error) {
|
||||
var o mo.ManagedEntity
|
||||
|
||||
name := c.Name()
|
||||
if name != "" {
|
||||
return name, nil
|
||||
}
|
||||
|
||||
err := c.Properties(ctx, c.Reference(), []string{"name"}, &o)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return o.Name, nil
|
||||
}
|
||||
|
||||
func (c Common) Properties(ctx context.Context, r types.ManagedObjectReference, ps []string, dst interface{}) error {
|
||||
return property.DefaultCollector(c.c).RetrieveOne(ctx, r, ps, dst)
|
||||
}
|
||||
|
|
|
@ -29,8 +29,6 @@ import (
|
|||
|
||||
type ComputeResource struct {
|
||||
Common
|
||||
|
||||
InventoryPath string
|
||||
}
|
||||
|
||||
func NewComputeResource(c *vim25.Client, ref types.ManagedObjectReference) *ComputeResource {
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
|
@ -57,8 +58,6 @@ func (e DatastoreNoSuchFileError) Error() string {
|
|||
|
||||
type Datastore struct {
|
||||
Common
|
||||
|
||||
InventoryPath string
|
||||
}
|
||||
|
||||
func NewDatastore(c *vim25.Client, ref types.ManagedObjectReference) *Datastore {
|
||||
|
@ -67,10 +66,6 @@ func NewDatastore(c *vim25.Client, ref types.ManagedObjectReference) *Datastore
|
|||
}
|
||||
}
|
||||
|
||||
func (d Datastore) Name() string {
|
||||
return path.Base(d.InventoryPath)
|
||||
}
|
||||
|
||||
func (d Datastore) Path(path string) string {
|
||||
name := d.Name()
|
||||
if name == "" {
|
||||
|
@ -116,6 +111,42 @@ func (d Datastore) Browser(ctx context.Context) (*HostDatastoreBrowser, error) {
|
|||
return NewHostDatastoreBrowser(d.c, do.Browser), nil
|
||||
}
|
||||
|
||||
func (d Datastore) useServiceTicketHostName(name string) bool {
|
||||
// No need if talking directly to ESX.
|
||||
if !d.c.IsVC() {
|
||||
return false
|
||||
}
|
||||
|
||||
// If version happens to be < 5.1
|
||||
if name == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// If the HostSystem is using DHCP on a network without dynamic DNS,
|
||||
// HostSystem.Config.Network.DnsConfig.HostName is set to "localhost" by default.
|
||||
// This resolves to "localhost.localdomain" by default via /etc/hosts on ESX.
|
||||
// In that case, we will stick with the HostSystem.Name which is the IP address that
|
||||
// was used to connect the host to VC.
|
||||
if name == "localhost.localdomain" {
|
||||
return false
|
||||
}
|
||||
|
||||
// Still possible to have HostName that don't resolve via DNS,
|
||||
// so we default to false.
|
||||
key := "GOVMOMI_USE_SERVICE_TICKET_HOSTNAME"
|
||||
|
||||
val := d.c.URL().Query().Get(key)
|
||||
if val == "" {
|
||||
val = os.Getenv(key)
|
||||
}
|
||||
|
||||
if val == "1" || val == "true" {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// ServiceTicket obtains a ticket via AcquireGenericServiceTicket and returns it an http.Cookie with the url.URL
|
||||
// that can be used along with the ticket cookie to access the given path.
|
||||
func (d Datastore) ServiceTicket(ctx context.Context, path string, method string) (*url.URL, *http.Cookie, error) {
|
||||
|
@ -142,7 +173,7 @@ func (d Datastore) ServiceTicket(ctx context.Context, path string, method string
|
|||
|
||||
// Pick a random attached host
|
||||
host := hosts[rand.Intn(len(hosts))]
|
||||
name, err := host.Name(ctx)
|
||||
name, err := host.ObjectName(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -167,6 +198,10 @@ func (d Datastore) ServiceTicket(ctx context.Context, path string, method string
|
|||
Value: ticket.Id,
|
||||
}
|
||||
|
||||
if d.useServiceTicketHostName(ticket.HostName) {
|
||||
u.Host = ticket.HostName
|
||||
}
|
||||
|
||||
return u, cookie, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -17,8 +17,6 @@ limitations under the License.
|
|||
package object
|
||||
|
||||
import (
|
||||
"path"
|
||||
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
|
@ -27,8 +25,6 @@ import (
|
|||
|
||||
type DistributedVirtualPortgroup struct {
|
||||
Common
|
||||
|
||||
InventoryPath string
|
||||
}
|
||||
|
||||
func NewDistributedVirtualPortgroup(c *vim25.Client, ref types.ManagedObjectReference) *DistributedVirtualPortgroup {
|
||||
|
@ -36,9 +32,6 @@ func NewDistributedVirtualPortgroup(c *vim25.Client, ref types.ManagedObjectRefe
|
|||
Common: NewCommon(c, ref),
|
||||
}
|
||||
}
|
||||
func (p DistributedVirtualPortgroup) Name() string {
|
||||
return path.Base(p.InventoryPath)
|
||||
}
|
||||
|
||||
// EthernetCardBackingInfo returns the VirtualDeviceBackingInfo for this DistributedVirtualPortgroup
|
||||
func (p DistributedVirtualPortgroup) EthernetCardBackingInfo(ctx context.Context) (types.BaseVirtualDeviceBackingInfo, error) {
|
||||
|
|
|
@ -25,8 +25,6 @@ import (
|
|||
|
||||
type DistributedVirtualSwitch struct {
|
||||
Common
|
||||
|
||||
InventoryPath string
|
||||
}
|
||||
|
||||
func NewDistributedVirtualSwitch(c *vim25.Client, ref types.ManagedObjectReference) *DistributedVirtualSwitch {
|
||||
|
|
|
@ -26,8 +26,6 @@ import (
|
|||
|
||||
type Folder struct {
|
||||
Common
|
||||
|
||||
InventoryPath string
|
||||
}
|
||||
|
||||
func NewFolder(c *vim25.Client, ref types.ManagedObjectReference) *Folder {
|
||||
|
@ -113,6 +111,20 @@ func (f Folder) CreateFolder(ctx context.Context, name string) (*Folder, error)
|
|||
return NewFolder(f.c, res.Returnval), err
|
||||
}
|
||||
|
||||
func (f Folder) CreateStoragePod(ctx context.Context, name string) (*StoragePod, error) {
|
||||
req := types.CreateStoragePod{
|
||||
This: f.Reference(),
|
||||
Name: name,
|
||||
}
|
||||
|
||||
res, err := methods.CreateStoragePod(ctx, f.c, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewStoragePod(f.c, res.Returnval), err
|
||||
}
|
||||
|
||||
func (f Folder) AddStandaloneHost(ctx context.Context, spec types.HostConnectSpec, addConnected bool, license *string, compResSpec *types.BaseComputeResourceConfigSpec) (*Task, error) {
|
||||
req := types.AddStandaloneHost_Task{
|
||||
This: f.Reference(),
|
||||
|
|
|
@ -120,3 +120,14 @@ func (m HostConfigManager) OptionManager(ctx context.Context) (*OptionManager, e
|
|||
|
||||
return NewOptionManager(m.c, *h.ConfigManager.AdvancedOption), nil
|
||||
}
|
||||
|
||||
func (m HostConfigManager) ServiceSystem(ctx context.Context) (*HostServiceSystem, error) {
|
||||
var h mo.HostSystem
|
||||
|
||||
err := m.Properties(ctx, m.Reference(), []string{"configManager.serviceSystem"}, &h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewHostServiceSystem(m.c, *h.ConfigManager.ServiceSystem), nil
|
||||
}
|
||||
|
|
|
@ -33,6 +33,21 @@ func NewHostDatastoreSystem(c *vim25.Client, ref types.ManagedObjectReference) *
|
|||
}
|
||||
}
|
||||
|
||||
func (s HostDatastoreSystem) CreateLocalDatastore(ctx context.Context, name string, path string) (*Datastore, error) {
|
||||
req := types.CreateLocalDatastore{
|
||||
This: s.Reference(),
|
||||
Name: name,
|
||||
Path: path,
|
||||
}
|
||||
|
||||
res, err := methods.CreateLocalDatastore(ctx, s.Client(), &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewDatastore(s.Client(), res.Returnval), nil
|
||||
}
|
||||
|
||||
func (s HostDatastoreSystem) CreateNasDatastore(ctx context.Context, spec types.HostNasVolumeSpec) (*Datastore, error) {
|
||||
req := types.CreateNasDatastore{
|
||||
This: s.Reference(),
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package object
|
||||
|
||||
import (
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/methods"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type HostServiceSystem struct {
|
||||
Common
|
||||
}
|
||||
|
||||
func NewHostServiceSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostServiceSystem {
|
||||
return &HostServiceSystem{
|
||||
Common: NewCommon(c, ref),
|
||||
}
|
||||
}
|
||||
|
||||
func (s HostServiceSystem) Service(ctx context.Context) ([]types.HostService, error) {
|
||||
var ss mo.HostServiceSystem
|
||||
|
||||
err := s.Properties(ctx, s.Reference(), []string{"serviceInfo.service"}, &ss)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ss.ServiceInfo.Service, nil
|
||||
}
|
||||
|
||||
func (s HostServiceSystem) Start(ctx context.Context, id string) error {
|
||||
req := types.StartService{
|
||||
This: s.Reference(),
|
||||
Id: id,
|
||||
}
|
||||
|
||||
_, err := methods.StartService(ctx, s.Client(), &req)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s HostServiceSystem) Stop(ctx context.Context, id string) error {
|
||||
req := types.StopService{
|
||||
This: s.Reference(),
|
||||
Id: id,
|
||||
}
|
||||
|
||||
_, err := methods.StopService(ctx, s.Client(), &req)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s HostServiceSystem) Restart(ctx context.Context, id string) error {
|
||||
req := types.RestartService{
|
||||
This: s.Reference(),
|
||||
Id: id,
|
||||
}
|
||||
|
||||
_, err := methods.RestartService(ctx, s.Client(), &req)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s HostServiceSystem) UpdatePolicy(ctx context.Context, id string, policy string) error {
|
||||
req := types.UpdateServicePolicy{
|
||||
This: s.Reference(),
|
||||
Id: id,
|
||||
Policy: policy,
|
||||
}
|
||||
|
||||
_, err := methods.UpdateServicePolicy(ctx, s.Client(), &req)
|
||||
return err
|
||||
}
|
|
@ -78,3 +78,68 @@ func (s HostStorageSystem) UpdateDiskPartitionInfo(ctx context.Context, devicePa
|
|||
_, err := methods.UpdateDiskPartitions(ctx, s.c, &req)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s HostStorageSystem) RescanAllHba(ctx context.Context) error {
|
||||
req := types.RescanAllHba{
|
||||
This: s.Reference(),
|
||||
}
|
||||
|
||||
_, err := methods.RescanAllHba(ctx, s.c, &req)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s HostStorageSystem) MarkAsSsd(ctx context.Context, uuid string) (*Task, error) {
|
||||
req := types.MarkAsSsd_Task{
|
||||
This: s.Reference(),
|
||||
ScsiDiskUuid: uuid,
|
||||
}
|
||||
|
||||
res, err := methods.MarkAsSsd_Task(ctx, s.c, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewTask(s.c, res.Returnval), nil
|
||||
}
|
||||
|
||||
func (s HostStorageSystem) MarkAsNonSsd(ctx context.Context, uuid string) (*Task, error) {
|
||||
req := types.MarkAsNonSsd_Task{
|
||||
This: s.Reference(),
|
||||
ScsiDiskUuid: uuid,
|
||||
}
|
||||
|
||||
res, err := methods.MarkAsNonSsd_Task(ctx, s.c, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewTask(s.c, res.Returnval), nil
|
||||
}
|
||||
|
||||
func (s HostStorageSystem) MarkAsLocal(ctx context.Context, uuid string) (*Task, error) {
|
||||
req := types.MarkAsLocal_Task{
|
||||
This: s.Reference(),
|
||||
ScsiDiskUuid: uuid,
|
||||
}
|
||||
|
||||
res, err := methods.MarkAsLocal_Task(ctx, s.c, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewTask(s.c, res.Returnval), nil
|
||||
}
|
||||
|
||||
func (s HostStorageSystem) MarkAsNonLocal(ctx context.Context, uuid string) (*Task, error) {
|
||||
req := types.MarkAsNonLocal_Task{
|
||||
This: s.Reference(),
|
||||
ScsiDiskUuid: uuid,
|
||||
}
|
||||
|
||||
res, err := methods.MarkAsNonLocal_Task(ctx, s.c, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewTask(s.c, res.Returnval), nil
|
||||
}
|
||||
|
|
|
@ -29,15 +29,6 @@ import (
|
|||
|
||||
type HostSystem struct {
|
||||
Common
|
||||
|
||||
InventoryPath string
|
||||
}
|
||||
|
||||
func (h HostSystem) String() string {
|
||||
if h.InventoryPath == "" {
|
||||
return h.Common.String()
|
||||
}
|
||||
return fmt.Sprintf("%v @ %v", h.Common, h.InventoryPath)
|
||||
}
|
||||
|
||||
func NewHostSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostSystem {
|
||||
|
@ -46,17 +37,6 @@ func NewHostSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostSyste
|
|||
}
|
||||
}
|
||||
|
||||
func (h HostSystem) Name(ctx context.Context) (string, error) {
|
||||
var mh mo.HostSystem
|
||||
|
||||
err := h.Properties(ctx, h.Reference(), []string{"name"}, &mh)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return mh.Name, nil
|
||||
}
|
||||
|
||||
func (h HostSystem) ConfigManager() *HostConfigManager {
|
||||
return NewHostConfigManager(h.c, h.Reference())
|
||||
}
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package object
|
||||
|
||||
import (
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/methods"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type DatastoreNamespaceManager struct {
|
||||
Common
|
||||
}
|
||||
|
||||
func NewDatastoreNamespaceManager(c *vim25.Client) *DatastoreNamespaceManager {
|
||||
n := DatastoreNamespaceManager{
|
||||
Common: NewCommon(c, *c.ServiceContent.DatastoreNamespaceManager),
|
||||
}
|
||||
|
||||
return &n
|
||||
}
|
||||
|
||||
// CreateDirectory creates a top-level directory on the given vsan datastore, using
|
||||
// the given user display name hint and opaque storage policy.
|
||||
func (nm DatastoreNamespaceManager) CreateDirectory(ctx context.Context, ds *Datastore, displayName string, policy string) (string, error) {
|
||||
|
||||
req := &types.CreateDirectory{
|
||||
This: nm.Reference(),
|
||||
Datastore: ds.Reference(),
|
||||
DisplayName: displayName,
|
||||
Policy: policy,
|
||||
}
|
||||
|
||||
resp, err := methods.CreateDirectory(ctx, nm.c, req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return resp.Returnval, nil
|
||||
}
|
||||
|
||||
// DeleteDirectory deletes the given top-level directory from a vsan datastore.
|
||||
func (nm DatastoreNamespaceManager) DeleteDirectory(ctx context.Context, dc *Datacenter, datastorePath string) error {
|
||||
|
||||
req := &types.DeleteDirectory{
|
||||
This: nm.Reference(),
|
||||
DatastorePath: datastorePath,
|
||||
}
|
||||
|
||||
if dc != nil {
|
||||
ref := dc.Reference()
|
||||
req.Datacenter = &ref
|
||||
}
|
||||
|
||||
if _, err := methods.DeleteDirectory(ctx, nm.c, req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -17,8 +17,6 @@ limitations under the License.
|
|||
package object
|
||||
|
||||
import (
|
||||
"path"
|
||||
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"golang.org/x/net/context"
|
||||
|
@ -26,8 +24,6 @@ import (
|
|||
|
||||
type Network struct {
|
||||
Common
|
||||
|
||||
InventoryPath string
|
||||
}
|
||||
|
||||
func NewNetwork(c *vim25.Client, ref types.ManagedObjectReference) *Network {
|
||||
|
@ -36,10 +32,6 @@ func NewNetwork(c *vim25.Client, ref types.ManagedObjectReference) *Network {
|
|||
}
|
||||
}
|
||||
|
||||
func (n Network) Name() string {
|
||||
return path.Base(n.InventoryPath)
|
||||
}
|
||||
|
||||
// EthernetCardBackingInfo returns the VirtualDeviceBackingInfo for this Network
|
||||
func (n Network) EthernetCardBackingInfo(_ context.Context) (types.BaseVirtualDeviceBackingInfo, error) {
|
||||
name := n.Name()
|
||||
|
|
|
@ -17,26 +17,14 @@ limitations under the License.
|
|||
package object
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/methods"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type ResourcePool struct {
|
||||
Common
|
||||
|
||||
InventoryPath string
|
||||
}
|
||||
|
||||
func (p ResourcePool) String() string {
|
||||
if p.InventoryPath == "" {
|
||||
return p.Common.String()
|
||||
}
|
||||
return fmt.Sprintf("%v @ %v", p.Common, p.InventoryPath)
|
||||
}
|
||||
|
||||
func NewResourcePool(c *vim25.Client, ref types.ManagedObjectReference) *ResourcePool {
|
||||
|
@ -45,17 +33,6 @@ func NewResourcePool(c *vim25.Client, ref types.ManagedObjectReference) *Resourc
|
|||
}
|
||||
}
|
||||
|
||||
func (p ResourcePool) Name(ctx context.Context) (string, error) {
|
||||
var o mo.ResourcePool
|
||||
|
||||
err := p.Properties(ctx, p.Reference(), []string{"name"}, &o)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return o.Name, nil
|
||||
}
|
||||
|
||||
func (p ResourcePool) ImportVApp(ctx context.Context, spec types.BaseImportSpec, folder *Folder, host *HostSystem) (*HttpNfcLease, error) {
|
||||
req := types.ImportVApp{
|
||||
This: p.Reference(),
|
||||
|
|
|
@ -17,13 +17,10 @@ limitations under the License.
|
|||
package object
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/methods"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
|
@ -37,24 +34,6 @@ func NewVirtualApp(c *vim25.Client, ref types.ManagedObjectReference) *VirtualAp
|
|||
}
|
||||
}
|
||||
|
||||
func (p VirtualApp) String() string {
|
||||
if p.InventoryPath == "" {
|
||||
return p.Common.String()
|
||||
}
|
||||
return fmt.Sprintf("%v @ %v", p.Common, p.InventoryPath)
|
||||
}
|
||||
|
||||
func (p VirtualApp) Name(ctx context.Context) (string, error) {
|
||||
var o mo.VirtualApp
|
||||
|
||||
err := p.Properties(ctx, p.Reference(), []string{"name"}, &o)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return o.Name, nil
|
||||
}
|
||||
|
||||
func (p VirtualApp) CreateChildVM_Task(ctx context.Context, config types.VirtualMachineConfigSpec, host *HostSystem) (*Task, error) {
|
||||
req := types.CreateChildVM_Task{
|
||||
This: p.Reference(),
|
||||
|
|
|
@ -143,3 +143,27 @@ func (m VirtualDiskManager) DeleteVirtualDisk(ctx context.Context, name string,
|
|||
|
||||
return NewTask(m.c, res.Returnval), nil
|
||||
}
|
||||
|
||||
// Queries virtual disk uuid
|
||||
func (m VirtualDiskManager) QueryVirtualDiskUuid(ctx context.Context, name string, dc *Datacenter) (string, error) {
|
||||
req := types.QueryVirtualDiskUuid{
|
||||
This: m.Reference(),
|
||||
Name: name,
|
||||
}
|
||||
|
||||
if dc != nil {
|
||||
ref := dc.Reference()
|
||||
req.Datacenter = &ref
|
||||
}
|
||||
|
||||
res, err := methods.QueryVirtualDiskUuid(ctx, m.c, &req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if res == nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return res.Returnval, nil
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ package object
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/vmware/govmomi/property"
|
||||
|
@ -35,15 +34,6 @@ const (
|
|||
|
||||
type VirtualMachine struct {
|
||||
Common
|
||||
|
||||
InventoryPath string
|
||||
}
|
||||
|
||||
func (v VirtualMachine) String() string {
|
||||
if v.InventoryPath == "" {
|
||||
return v.Common.String()
|
||||
}
|
||||
return fmt.Sprintf("%v @ %v", v.Common, v.InventoryPath)
|
||||
}
|
||||
|
||||
func NewVirtualMachine(c *vim25.Client, ref types.ManagedObjectReference) *VirtualMachine {
|
||||
|
@ -52,17 +42,6 @@ func NewVirtualMachine(c *vim25.Client, ref types.ManagedObjectReference) *Virtu
|
|||
}
|
||||
}
|
||||
|
||||
func (v VirtualMachine) Name(ctx context.Context) (string, error) {
|
||||
var o mo.VirtualMachine
|
||||
|
||||
err := v.Properties(ctx, v.Reference(), []string{"name"}, &o)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return o.Name, nil
|
||||
}
|
||||
|
||||
func (v VirtualMachine) PowerState(ctx context.Context) (types.VirtualMachinePowerState, error) {
|
||||
var o mo.VirtualMachine
|
||||
|
||||
|
|
|
@ -161,3 +161,17 @@ func (sm *Manager) AcquireGenericServiceTicket(ctx context.Context, spec types.B
|
|||
|
||||
return &res.Returnval, nil
|
||||
}
|
||||
|
||||
func (sm *Manager) AcquireLocalTicket(ctx context.Context, userName string) (*types.SessionManagerLocalTicket, error) {
|
||||
req := types.AcquireLocalTicket{
|
||||
This: sm.Reference(),
|
||||
UserName: userName,
|
||||
}
|
||||
|
||||
res, err := methods.AcquireLocalTicket(ctx, sm.client, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &res.Returnval, nil
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ limitations under the License.
|
|||
package mo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"golang.org/x/net/context"
|
||||
|
@ -76,6 +78,24 @@ func Ancestors(ctx context.Context, rt soap.RoundTripper, pc, obj types.ManagedO
|
|||
// Find entity we're looking for given the last entity in the current tree.
|
||||
for _, iface := range ifaces {
|
||||
me := iface.(IsManagedEntity).GetManagedEntity()
|
||||
|
||||
if me.Name == "" {
|
||||
// The types below have their own 'Name' field, so ManagedEntity.Name (me.Name) is empty.
|
||||
// We only hit this case when the 'obj' param is one of these types.
|
||||
// In most cases, 'obj' is a Folder so Name isn't collected in this call.
|
||||
switch x := iface.(type) {
|
||||
case Network:
|
||||
me.Name = x.Name
|
||||
case DistributedVirtualSwitch:
|
||||
me.Name = x.Name
|
||||
case DistributedVirtualPortgroup:
|
||||
me.Name = x.Name
|
||||
default:
|
||||
// ManagedEntity always has a Name, if we hit this point we missed a case above.
|
||||
panic(fmt.Sprintf("%#v Name is empty", me.Reference()))
|
||||
}
|
||||
}
|
||||
|
||||
if me.Parent == nil {
|
||||
out = append(out, me)
|
||||
break
|
||||
|
|
|
@ -36,6 +36,10 @@ func (m DistributedVirtualSwitch) GetManagedEntity() ManagedEntity {
|
|||
return m.ManagedEntity
|
||||
}
|
||||
|
||||
func (m DistributedVirtualPortgroup) GetManagedEntity() ManagedEntity {
|
||||
return m.ManagedEntity
|
||||
}
|
||||
|
||||
func (m Folder) GetManagedEntity() ManagedEntity {
|
||||
return m.ManagedEntity
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ type Fault struct {
|
|||
Code string `xml:"faultcode"`
|
||||
String string `xml:"faultstring"`
|
||||
Detail struct {
|
||||
Fault types.AnyType `xml:",any"`
|
||||
Fault types.AnyType `xml:",any,typeattr"`
|
||||
} `xml:"detail"`
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@ limitations under the License.
|
|||
|
||||
package types
|
||||
|
||||
import "strings"
|
||||
|
||||
func NewBool(v bool) *bool {
|
||||
return &v
|
||||
}
|
||||
|
@ -23,3 +25,24 @@ func NewBool(v bool) *bool {
|
|||
func NewReference(r ManagedObjectReference) *ManagedObjectReference {
|
||||
return &r
|
||||
}
|
||||
|
||||
func (r ManagedObjectReference) Reference() ManagedObjectReference {
|
||||
return r
|
||||
}
|
||||
|
||||
func (r ManagedObjectReference) String() string {
|
||||
return strings.Join([]string{r.Type, r.Value}, ":")
|
||||
}
|
||||
|
||||
func (r *ManagedObjectReference) FromString(o string) bool {
|
||||
s := strings.SplitN(o, ":", 2)
|
||||
|
||||
if len(s) < 2 {
|
||||
return false
|
||||
}
|
||||
|
||||
r.Type = s[0]
|
||||
r.Value = s[1]
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue