Я могу перечислить все виртуальные машины, используя govmomi (не gov c, который является однострочной командой в терминале), но я пытаюсь реализовать это:
govc guest.run -vm $vm_name cat sample.txt
с нуля, а не запускать его через правительство c. Документы, кажется, сбивают с толку. Кто-нибудь знает, как это было реализовано под ним? И есть ли что-то похожее на это в pyvmomi? Используя Pyvmomi, я смог выполнить команду на сервере с локального p c, а затем сохранить вывод в файле на сервере и затем передать файл с сервера на локальный p c. Но на более позднем этапе я наткнулся на команду govc guest.run -vm $vm_name cat sample.txt
, которая выдает на консоли локальный вывод p c. Это также за сценой временно хранит вывод на сервере? Если нет, то как это реализовать?
Это то, что я пробовал, пытаясь составить список всех виртуальных машин, использующих govmomi, я хочу расширить его, чтобы он мог реализовать команду gov c run.
package main
import (
"flag"
"fmt"
"net/url"
"os"
"strings"
"text/tabwriter"
"sort"
"github.com/vmware/govmomi"
"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context"
)
func GetEnvString(v string, def string) string {
r := os.Getenv(v)
if r == "" {
return def
}
return r
}
// GetEnvBool returns boolean from environment variable.
func GetEnvBool(v string, def bool) bool {
r := os.Getenv(v)
if r == "" {
return def
}
switch strings.ToLower(r[0:1]) {
case "t", "y", "1":
return true
}
return false
}
const (
envURL = "vcenter's_ip"
envUserName = "username@organisation.org"
envPassword = "pwd"
envInsecure = "true"
)
var urlDescription = fmt.Sprintf("ESX or vCenter URL [%s]", envURL)
var urlFlag = flag.String("url", GetEnvString(envURL, "https://username@organisation.org:pwd@ip_of_vcenter/sdk"), urlDescription)
var insecureDescription = fmt.Sprintf("Don't verify the server's certificate chain [%s]", envInsecure)
var insecureFlag = flag.Bool("insecure", GetEnvBool(envInsecure, true), insecureDescription)
func processOverride(u *url.URL) {
envUsername := os.Getenv(envUserName)
envPassword := os.Getenv(envPassword)
// Override username if provided
if envUsername != "" {
var password string
var ok bool
if u.User != nil {
password, ok = u.User.Password()
}
if ok {
u.User = url.UserPassword(envUsername, password)
} else {
u.User = url.User(envUsername)
}
}
// Override password if provided
if envPassword != "" {
var username string
if u.User != nil {
username = u.User.Username()
}
u.User = url.UserPassword(username, envPassword)
}
}
func exit(err error) {
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
os.Exit(1)
}
type ByName []mo.VirtualMachine
func (n ByName) Len() int { return len(n) }
func (n ByName) Swap(i, j int) { n[i], n[j] = n[j], n[i] }
func (n ByName) Less(i, j int) bool { return n[i].Name < n[j].Name }
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
flag.Parse()
// Parse URL from string
u, err := url.Parse(*urlFlag)
if err != nil {
exit(err)
}
fmt.Println(u)
// Override username and/or password as required
processOverride(u)
// Connect and log in to ESX or vCenter
c, err := govmomi.NewClient(ctx, u, *insecureFlag)
if err != nil {
exit(err)
}
f := find.NewFinder(c.Client, true)
// Find one and only datacenter
dc, err := f.DefaultDatacenter(ctx)
if err != nil {
exit(err)
}
// Make future calls local to this datacenter
f.SetDatacenter(dc)
// Find virtual machines in datacenter
vms, err := f.VirtualMachineList(ctx, "in-temp-vm-2")// if instead of "in-temp-vm-2" *, then it lists down all the vm's
//fmt.Println(vms)
if err != nil {
exit(err)
}
//fmt.Println(vms);
pc := property.DefaultCollector(c.Client)
// Convert datastores into list of references
var refs []types.ManagedObjectReference
for _, vm := range vms {
refs = append(refs, vm.Reference())
}
// Retrieve name property for all vms
var vmt []mo.VirtualMachine
err = pc.Retrieve(ctx, refs, []string{"name"}, &vmt)
if err != nil {
exit(err)
}
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
fmt.Println("Virtual machines found:", len(vmt))
sort.Sort(ByName(vmt))
for _, vm := range vmt {
fmt.Fprintf(tw, "%s\n", vm.Name)
}
tw.Flush()
}
Этот код - глупая sh попытка реализовать gov c в golang, в основном с использованием команд оболочки, таких как bash.
package main
import (
"bytes"
"fmt"
"log"
//"os"
"os/exec"
)
const ShellToUse = "bash"
func Shellout(command string) (error, string, string) {
var stdout bytes.Buffer
var stderr bytes.Buffer
cmd := exec.Command(ShellToUse, "-c", command)
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Run()
return err, stdout.String(), stderr.String()
}
func main() {
err, out, errout := Shellout("govc guest.run -vm $vm_name python3 sample.py")
if err != nil {
log.Printf("error: %v\n", err)
}
fmt.Println("--- stdout ---")
fmt.Println(out)
// fmt.Println("--- stderr ---")
fmt.Println(errout)
}
И это мое python реализация, которая выполняет команду и сохраняет ее на сервере в файле, а затем я беру этот файл с сервера на локальный сервер p c, я не хочу хранить что-либо на сервере даже временно:
from pyVim import connect
from config import *
from pyVmomi import vim, vmodl
import ssl
import os
import requests
service_instance = connect.SmartConnect(host="xxxx", port=aaa,user="yyy" , pwd=pwd,sslContext=ssl._create_unverified_context())
content = service_instance.RetrieveContent()
# # Find a VM
vm = searcher.FindByIp(ip="aaaa", vmSearch=True)
creds = vim.vm.guest.NamePasswordAuthentication(username='root', password=vmpwd)
pm = service_instance.content.guestOperationsManager.processManager
#executes and saves sample.txt into server
ps = vim.vm.guest.ProcessManager.ProgramSpec(programPath='/usr/bin/python', arguments='--version &> sample.txt')
res = pm.StartProgramInGuest(vm, creds, ps)
dest="/Users/username/Desktop/vcenter/sample.txt" #My local pc
src="/root/sample.txt" #Server's directory
fti = content.guestOperationsManager.fileManager.InitiateFileTransferFromGuest(vm, creds, src)
resp=requests.get(fti.url, verify=False)
#Writes into file
with open(dest, 'wb') as f:
f.write(resp.content)