使用govmomi库在golang中设置零点

时间:2019-03-28 06:43:58

标签: go govmomi

我正在尝试使用govmomi库(https://github.com/vmware/govmomi)对VM进行一些自动更改,但最近几个小时似乎无法绕过第134和136行的nil指针异常。我一开始就可以使用它,但是后来我不确定我在做什么错,因为我尝试了很多组合,但是现在似乎什么也没有用...

package main

import (
    "context"
    "flag"
    "github.com/vmware/govmomi"
    "github.com/vmware/govmomi/vim25"
    "github.com/vmware/govmomi/vim25/soap"
    "net/url"
    "os"
    "strings"

    "fmt"

    "github.com/vmware/govmomi/govc/flags"

    "github.com/vmware/govmomi/vim25/types"
    "log"
)


type change struct {
    *flags.VirtualMachineFlag
}

const (
    envURL      = "GOVC_URL"
    envUserName = "GOVC_USERNAME"
    envPassword = "GOVC_PASSWORD"
    envInsecure = "GOVC_INSECURE"
)

// getEnvString returns string from environment variable.
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
}

var urlDescription = fmt.Sprintf("ESX or vCenter URL [%s]", envURL)
var urlFlag = flag.String("url", getEnvString(envURL, "https://username:password@host"+vim25.Path), urlDescription)

var insecureDescription = fmt.Sprintf("Don't verify the server's certificate chain [%s]", envInsecure)
var insecureFlag = flag.Bool("insecure", getEnvBool(envInsecure, false), 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 NewClient(ctx context.Context) (*govmomi.Client, error) {
    flag.Parse()

    // Parse URL from string
    u, err := soap.ParseURL(*urlFlag)
    if err != nil {
        return nil, err
    }

    // Override username and/or password as required
    processOverride(u)

    // Connect and log in to ESX or vCenter
    return govmomi.NewClient(ctx, u, *insecureFlag)
}

func main() {

    ctx := context.Background()

    // Connect and login to ESX or vCenter
    c, err := NewClient(ctx)
    if err != nil {
        log.Fatal(err)
    }

    defer c.Logout(ctx)

    var spec *types.VirtualMachineConfigSpec

    var cmd *change

    var flip bool

    flip = false

    spec.VPMCEnabled = &flip

    vm, err := cmd.VirtualMachine()

    task, err := vm.Reconfigure(ctx, *spec)
    if err != nil {
        println(err)
    }

    fmt.Println(task.Wait(ctx))
}

引发错误的2行是:

spec.VPMCEnabled = &flip

vm, err := cmd.VirtualMachine()

两者似乎都抛出相同的panic: runtime error: invalid memory address or nil pointer dereference。如果我注释掉第一个抛出错误的错误,那么第二个则抛出错误。

我认为两者无关,但是我不太清楚如何正确地进行取消引用。

----更新编辑1 --------------

我通过以下响应对此进行了一些更改,但仍然无法解决task, err := vm.Reconfigure(ctx, *spec)上的错误...

package main

import (
    "context"
    "flag"
    "github.com/vmware/govmomi"
    "github.com/vmware/govmomi/object"
    "github.com/vmware/govmomi/vim25"
    "github.com/vmware/govmomi/vim25/soap"
    "net/url"
    "os"
    "strings"

    "fmt"

    "github.com/vmware/govmomi/vim25/types"
    "log"
)


const (
    envURL      = "GOVC_URL"
    envUserName = "GOVC_USERNAME"
    envPassword = "GOVC_PASSWORD"
    envInsecure = "GOVC_INSECURE"
)

// getEnvString returns string from environment variable.
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
}

var urlDescription = fmt.Sprintf("ESX or vCenter URL [%s]", envURL)
var urlFlag = flag.String("url", getEnvString(envURL, "https://username:password@host"+vim25.Path), urlDescription)

var insecureDescription = fmt.Sprintf("Don't verify the server's certificate chain [%s]", envInsecure)
var insecureFlag = flag.Bool("insecure", getEnvBool(envInsecure, false), 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 NewClient(ctx context.Context) (*govmomi.Client, error) {
    flag.Parse()

    // Parse URL from string
    u, err := soap.ParseURL(*urlFlag)
    if err != nil {
        return nil, err
    }

    // Override username and/or password as required
    processOverride(u)

    // Connect and log in to ESX or vCenter
    return govmomi.NewClient(ctx, u, *insecureFlag)
}

func main() {

    ctx := context.Background()

    // Connect and login to ESX or vCenter
    c, err := NewClient(ctx)
    if err != nil {
        log.Fatal(err)
    }

    defer c.Logout(ctx)

    var spec *types.VirtualMachineConfigSpec
    spec = new(types.VirtualMachineConfigSpec)


    var flip bool

    flip = false

    spec.VPMCEnabled = &flip

    var vm *object.VirtualMachine
    vm = new(object.VirtualMachine)


    task, err := vm.Reconfigure(ctx, *spec)
    if err != nil {
        println(err)
    }

    fmt.Println(task.Wait(ctx))

}

我得到的全部错误是:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x280 pc=0x14e18f6]

goroutine 1 [running]:
github.com/vmware/govmomi/vim25.(*Client).RoundTrip(0x0, 0x1886f00, 0xc000016088, 0x1884140, 0xc000298720, 0x1884140, 0xc000298740, 0x300, 0x16e8ac0)
        /Users/ronakpatel/go/src/github.com/vmware/govmomi/vim25/client.go:89 +0x26
github.com/vmware/govmomi/vim25/methods.ReconfigVM_Task(0x1886f00, 0xc000016088, 0x1884060, 0x0, 0xc0002d0000, 0xc000288000, 0xc000080400, 0x0)
        /Users/ronakpatel/go/src/github.com/vmware/govmomi/vim25/methods/methods.go:10879 +0xb8
github.com/vmware/govmomi/object.VirtualMachine.Reconfigure(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1886f00, 0xc000016088, 0x0, ...)
        /Users/ronakpatel/go/src/github.com/vmware/govmomi/object/virtual_machine.go:207 +0x19b
main.main()
        /Users/ronakpatel/go/src/awesomeProject1/main.go:143 +0x1ec
exit status 2

----更新编辑2 ----------

我改变了一些地方,并使用了下面提供的答案,但是现在我再次遇到错误,但在这一部分:task, err := vm.Reconfigure(ctx, spec1)

错误:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x153d05a]

goroutine 1 [running]:
main.main()
        /Users/ronakpatel/go/src/awesomeProject1/main.go:134 +0x19a
exit status 2

代码:

spec1 := types.VirtualMachineConfigSpec{
    VPMCEnabled: &[]bool{false}[0],
}

var vm *object.VirtualMachine

var vmf *flags.VirtualMachineFlag

vmf, ctx = flags.NewVirtualMachineFlag(ctx)

vm, _ = vmf.VirtualMachine()

task, err := vm.Reconfigure(ctx, spec1)
if err != nil {
    println(err)
}

fmt.Println(task.Wait(ctx))

1 个答案:

答案 0 :(得分:3)

    var spec *types.VirtualMachineConfigSpec // error: spec is nil pointer
    spec = new(types.VirtualMachineConfigSpec) // fix: spec is not nil

    var cmd *change

    var flip bool

    flip = false

    // used here
    spec.VPMCEnabled = &flip

    vm, err := cmd.VirtualMachine()