Как выполнить команду запуска govc / pyvmomi, которая отображает вывод сервера на локальный компьютер - PullRequest
0 голосов
/ 26 февраля 2020

Я могу перечислить все виртуальные машины, используя 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)
...