douwu3763 2019-03-28 06:43
浏览 282

使用govmomi库在golang中设置零点

I'm trying to use the govmomi library (https://github.com/vmware/govmomi) to make some automated changes to a VM but I can't seem to get around the nil pointer exceptions on line 134 and 136 for the last few hours. I got it to work at one point but then I'm not sure what I'm doing wrong now as I've tried so many combos but nothing seems to work now...

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))
}

the 2 lines that are throwing errors are:

spec.VPMCEnabled = &flip

and

vm, err := cmd.VirtualMachine()

both seem to throw the same panic: runtime error: invalid memory address or nil pointer dereference. If I comment out the first one throwing the error, the second one throws it then.

I think both are unrelated but I can't quite figure how how to do the dereferencing correctly.

----UPDATE EDIT 1--------------

I made some changes to this with the below response but still can't get around the error on at 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))

}

the full error I'm getting is this:

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

----UPDATE EDIT 2----------

I changed somethings around and used the answer provided below but now I'm getting the error again but at this part: task, err := vm.Reconfigure(ctx, spec1)

Error:

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

Code:

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条回答 默认 最新

  • doufeng1249 2019-03-28 07:01
    关注
        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()
    
    评论

报告相同问题?

悬赏问题

  • ¥15 is not in the mmseg::model registry。报错,模型注册表找不到自定义模块。
  • ¥15 安装quartus II18.1时弹出此error,怎么解决?
  • ¥15 keil官网下载psn序列号在哪
  • ¥15 想用adb命令做一个通话软件,播放录音
  • ¥30 Pytorch深度学习服务器跑不通问题解决?
  • ¥15 部分客户订单定位有误的问题
  • ¥15 如何在maya程序中利用python编写领子和褶裥的模型的方法
  • ¥15 Bug traq 数据包 大概什么价
  • ¥15 在anaconda上pytorch和paddle paddle下载报错
  • ¥25 自动填写QQ腾讯文档收集表