first commit again
This commit is contained in:
5
go.mod
Normal file
5
go.mod
Normal file
@@ -0,0 +1,5 @@
|
||||
module orphanreport
|
||||
|
||||
go 1.21.6
|
||||
|
||||
require github.com/vmware/govmomi v0.34.2
|
14
go.sum
Normal file
14
go.sum
Normal file
@@ -0,0 +1,14 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/vmware/govmomi v0.34.2 h1:o6ydkTVITOkpQU6HAf6tP5GvHFCNJlNUNlMsvFK77X4=
|
||||
github.com/vmware/govmomi v0.34.2/go.mod h1:qWWT6n9mdCr/T9vySsoUqcI04sSEj4CqHXxtk/Y+Los=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
238
main.go
Normal file
238
main.go
Normal file
@@ -0,0 +1,238 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/vmware/govmomi"
|
||||
"github.com/vmware/govmomi/view"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
var (
|
||||
c *govmomi.Client
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
location *time.Location
|
||||
sha1ver string // sha1 revision used to build the program
|
||||
buildTime string // when the executable was built
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
// Command line flags
|
||||
vURL := flag.String("url", "", "The URL of a vCenter server, eg https://server.domain.example/sdk")
|
||||
vUser := flag.String("user", "", "The username to use when connecting to vCenter")
|
||||
vPass := flag.String("password", "", "The password to use when connecting to vCenter")
|
||||
vTZ := flag.String("tz", "Australia/Sydney", "The timezone to use when converting vCenter UTC times")
|
||||
vInsecure := flag.Bool("insecure", true, "Allow insecure connections to vCenter")
|
||||
//begin := flag.Duration("b", time.Hour, "Begin time") // default BeginTime is 1h ago
|
||||
flag.Parse()
|
||||
|
||||
var err error
|
||||
fmt.Printf("Starting execution. Built on %s from sha1 %s\n", buildTime, sha1ver)
|
||||
|
||||
// So we can convert vCenter UTC to our local timezone
|
||||
fmt.Printf("Setting timezone to '%s'\n", *vTZ)
|
||||
location, err = time.LoadLocation(*vTZ)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error setting timezone to %s : %s\n", *vTZ, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
u, err := url.Parse(*vURL)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error parsing url %s : %s\n", *vURL, err)
|
||||
os.Exit(1)
|
||||
} else {
|
||||
if !strings.HasSuffix(u.Path, "/sdk") {
|
||||
u.Path, _ = url.JoinPath(u.Path, "/sdk")
|
||||
log.Printf("Updated vCenter URL to '%v'\n", u)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("Connecting to vCenter %s\n", u)
|
||||
u.User = url.UserPassword(*vUser, *vPass)
|
||||
|
||||
ctx, cancel = context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
// Login to vcenter
|
||||
c, err = govmomi.NewClient(ctx, u, *vInsecure)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Logging in error: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer c.Logout(ctx)
|
||||
|
||||
// TODO : Refactor to iterate through all datacenters
|
||||
/*
|
||||
// Create a finder
|
||||
finder := find.NewFinder(c.Client, true)
|
||||
// Find one and only datacenter, not sure how VMware linked mode will work
|
||||
dc, err := finder.DatacenterOrDefault(ctx, "")
|
||||
if err != nil {
|
||||
fmt.Printf("No Datacenter instance could be found inside of vCenter : '%v'\n", err)
|
||||
}
|
||||
fmt.Printf("Looking at datacenter %s\n", dc.Name())
|
||||
|
||||
// Make future calls local to this datacenter
|
||||
finder.SetDatacenter(dc)
|
||||
|
||||
// Find all datastores
|
||||
datastores, err := finder.DatastoreList(ctx, "*")
|
||||
if err != nil {
|
||||
fmt.Printf("DatastoreList err: %v\n", err)
|
||||
}
|
||||
|
||||
// Retrieve ManagedObjectReference for each datastore
|
||||
var datastoreRefs []types.ManagedObjectReference
|
||||
for _, ds := range datastores {
|
||||
ref := ds.Reference()
|
||||
datastoreRefs = append(datastoreRefs, ref)
|
||||
}
|
||||
*/
|
||||
|
||||
datastoreRefs, err := getDatastoreRefs(ctx, c)
|
||||
if err != nil {
|
||||
fmt.Printf("err: %v\n", err)
|
||||
}
|
||||
|
||||
for i, val := range datastoreRefs {
|
||||
fmt.Printf("val %d: %v\n", i, val)
|
||||
}
|
||||
|
||||
/*
|
||||
// Find a host
|
||||
hostObj, err := finder.DefaultHostSystem(ctx)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("Failed to find host:", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Find all datastores on the host
|
||||
datastores, err := hostObj.Datastores(ctx)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("Failed to retrieve datastores:", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Iterate over each datastore
|
||||
|
||||
for _, ds := range datastores {
|
||||
fmt.Println("Datastore:", ds.Name())
|
||||
|
||||
// Get the host's datastore browser
|
||||
hostBrowser, err := hostObj.ConfigManager().DatastoreBrowser(ctx)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to get datastore browser for datastore %s: %v\n", ds.Name(), err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Recursively list files and folders in the datastore
|
||||
dsPath := "[" + ds.Name() + "]"
|
||||
err = listFilesRecursively(ctx, hostBrowser, dsPath, ds.Name())
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to list files in datastore %s: %v\n", ds.Name(), err)
|
||||
continue
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// getDatastoreRefs returns a list of ManagedObjectReference objects corresponding to every datastore in the vCenter.
|
||||
func getDatastoreRefs(ctx context.Context, client *govmomi.Client) ([]types.ManagedObjectReference, error) {
|
||||
var results []types.ManagedObjectReference
|
||||
m := view.NewManager(client.Client)
|
||||
view, err := m.CreateContainerView(ctx, client.ServiceContent.RootFolder, []string{"Datastore"}, true)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create view: %v", err)
|
||||
}
|
||||
defer view.Destroy(ctx)
|
||||
|
||||
var refs []mo.Datastore
|
||||
err = view.Retrieve(ctx, []string{"Datastore"}, []string{"name", "summary"}, &refs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to retrieve datastores: %v", err)
|
||||
}
|
||||
|
||||
for i := range refs {
|
||||
//fmt.Printf("refs[i]: %v\n", refs[i])
|
||||
fmt.Printf("Datastore '%s', Shared : '%t'\n", refs[i].Name, *refs[i].Summary.MultipleHostAccess)
|
||||
results = append(results, refs[i].Reference())
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
/*
|
||||
func listFilesRecursively(ctx context.Context, browser *host.DatastoreBrowser, path string, datastoreName string) error {
|
||||
searchResult, err := browser.SearchDatastoreSubFolders(ctx, path, "*", true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, file := range searchResult.File {
|
||||
fmt.Printf("File: %s\n", file.Path)
|
||||
}
|
||||
for _, folder := range searchResult.Folder {
|
||||
fmt.Printf("Folder: %s\n", folder.Path)
|
||||
err := listFilesRecursively(ctx, browser, folder.Path, datastoreName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
func listFilesRecursively(ctx context.Context, browser *object.HostDatastoreBrowser, path string, datastoreName string) error {
|
||||
var files []mo.FileInfo
|
||||
err := browser.List(ctx, path, &files)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get list of VMs on the datastore
|
||||
var vms []mo.VirtualMachine
|
||||
browser.
|
||||
err = browser.Datastore().VirtualMachines(ctx, &vms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create a map to store VM file paths
|
||||
vmFilePaths := make(map[string]bool)
|
||||
for _, vm := range vms {
|
||||
for _, filePath := range vm.LayoutEx.File {
|
||||
vmFilePaths[filePath.Name] = true
|
||||
}
|
||||
}
|
||||
|
||||
// Compare file list with VM file paths
|
||||
for _, fileInfo := range files {
|
||||
if !vmFilePaths[fileInfo.Path] {
|
||||
fmt.Printf("File %s on datastore %s is not owned by any VM\n", fileInfo.Path, datastoreName)
|
||||
}
|
||||
if fileInfo.IsDir {
|
||||
err := listFilesRecursively(ctx, browser, fileInfo.Path, datastoreName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
*/
|
Reference in New Issue
Block a user