python-3.x - 如何执行列出本地 pc 上服务器输出的 govc/pyvmomi 运行命令
问题描述
我可以使用 govmomi 列出所有虚拟机(不是 govc,它是终端中的一行命令),但我正在尝试实现这一点:
govc guest.run -vm $vm_name cat sample.txt
从头开始,而不是通过 govc 运行它。文档似乎令人困惑。有谁知道它是如何在下面实现的?在 pyvmomi 中是否有与此类似的东西?使用 Pyvmomi,我能够从本地 pc 在服务器上执行命令,然后将输出存储在服务器上的文件中,然后将文件从服务器传输到本地 pc。但在后期,我遇到govc guest.run -vm $vm_name cat sample.txt
了在本地 pc 控制台上提供输出的命令。它是否也在后台将输出临时存储在服务器上?如果没有,那么如何实现呢?
这是我在尝试使用 govmomi 列出所有 vm 时尝试过的,我想扩展它以便它可以实现 govc 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()
}
这段代码是在 golang 中实现 govc 的愚蠢尝试,基本上使用 bash 之类的 shell 命令。
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 实现,它执行命令并将其存储在服务器上的一个文件中,然后我将该文件从服务器带到本地 pc,我不想在服务器上存储任何东西,即使是暂时的:
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)
解决方案
推荐阅读
- c++ - C++ 二叉树对象,带有 1 个参数的“插入”方法
- javascript - HTML - 更改复选框选择时的 div 最大宽度属性
- ssl - 如何在 IIS 上使用自签名证书在 localhost 上配置 SSL?
- h2o - 从 python 重用 h2o 模型 mojo 或 pojo 文件
- javascript - Jquery删除动态下拉删除整个父div
- javascript - 如何在Javascript字符串中转义斜杠?
- macos - Microsoft 添加 ins 功能区自定义选项卡在 Outlook 中不起作用
- java - HashSet 代替 ArrayList 在性能上的缺点
- clojure - Clojure:实现一些功能
- angular - 离子原生联系人“plugin_not_installed”