Esempio n. 1
0
// NewVMHost connects to a ESXi or vCenter instance and returns a *VMHost
func NewVMHost(insecure bool, hostURL_param, user, pass string) (*VMHost, error) {
	ctx, _ := context.WithCancel(context.Background())
	hostURL, err := url.Parse("https://" + hostURL_param + "/sdk")
	hostURL.User = url.UserPassword(user, pass)

	cli, err := govmomi.NewClient(ctx, hostURL, insecure)
	if err != nil {
		return nil, err
	}

	mac, err := getLocalMAC()
	if err != nil {
		return nil, err
	}

	vmh := &VMHost{
		client: cli,
		Ctx:    ctx,
		mac:    mac,
	}

	vm, err := vmh.findVM(vmh.mac)
	if err != nil {
		return nil, err
	}
	vmh.Vm = vm

	return vmh, nil
}
func TestClusterESX(t *testing.T) {
	content := esx.ServiceContent
	s := New(NewServiceInstance(content, esx.RootFolder))

	ts := s.NewServer()
	defer ts.Close()

	ctx := context.Background()
	c, err := govmomi.NewClient(ctx, ts.URL, true)
	if err != nil {
		t.Fatal(err)
	}

	dc := object.NewDatacenter(c.Client, esx.Datacenter.Reference())

	folders, err := dc.Folders(ctx)
	if err != nil {
		t.Fatal(err)
	}

	_, err = folders.HostFolder.CreateCluster(ctx, "cluster1", types.ClusterConfigSpecEx{})
	if err == nil {
		t.Fatal("expected error")
	}
}
func TestClusterVC(t *testing.T) {
	content := vc.ServiceContent
	s := New(NewServiceInstance(content, vc.RootFolder))

	ts := s.NewServer()
	defer ts.Close()

	ctx := context.Background()
	c, err := govmomi.NewClient(ctx, ts.URL, true)
	if err != nil {
		t.Fatal(err)
	}

	f := object.NewRootFolder(c.Client)

	dc, err := f.CreateDatacenter(ctx, "foo")
	if err != nil {
		t.Error(err)
	}

	folders, err := dc.Folders(ctx)
	if err != nil {
		t.Fatal(err)
	}

	cluster, err := folders.HostFolder.CreateCluster(ctx, "cluster1", types.ClusterConfigSpecEx{})
	if err != nil {
		t.Fatal(err)
	}

	_, err = folders.HostFolder.CreateCluster(ctx, "cluster1", types.ClusterConfigSpecEx{})
	if err == nil {
		t.Error("expected DuplicateName error")
	}

	spec := types.HostConnectSpec{}

	for _, fail := range []bool{true, false} {
		task, err := cluster.AddHost(ctx, spec, true, nil, nil)
		if err != nil {
			t.Fatal(err)
		}

		_, err = task.WaitForResult(ctx, nil)

		if fail {
			if err == nil {
				t.Error("expected error")
			}
			spec.HostName = "localhost"
		} else {
			if err != nil {
				t.Error(err)
			}
		}
	}
}
Esempio n. 4
0
func TestWaitForUpdates(t *testing.T) {
	folder := esx.RootFolder
	s := New(NewServiceInstance(esx.ServiceContent, folder))

	ts := s.NewServer()
	defer ts.Close()

	ctx := context.Background()

	c, err := govmomi.NewClient(ctx, ts.URL, true)
	if err != nil {
		t.Fatal(err)
	}

	cb := func(once bool) func([]types.PropertyChange) bool {
		return func(pc []types.PropertyChange) bool {
			if len(pc) != 1 {
				t.Fail()
			}

			c := pc[0]
			if c.Op != types.PropertyChangeOpAssign {
				t.Fail()
			}
			if c.Name != "name" {
				t.Fail()
			}
			if c.Val.(string) != folder.Name {
				t.Fail()
			}

			return once
		}
	}

	pc := property.DefaultCollector(c.Client)
	props := []string{"name"}

	err = property.Wait(ctx, pc, folder.Reference(), props, cb(true))
	if err != nil {
		t.Error(err)
	}

	// incremental updates not yet suppported
	err = property.Wait(ctx, pc, folder.Reference(), props, cb(false))
	if err == nil {
		t.Error("expected error")
	}

	// test object not found
	Map.Remove(folder.Reference())

	err = property.Wait(ctx, pc, folder.Reference(), props, cb(true))
	if err == nil {
		t.Error("expected error")
	}
}
Esempio n. 5
0
// Connect establishes the connection for the session but nothing more
func (s *Session) Connect(ctx context.Context) (*Session, error) {
	soapURL, err := soap.ParseURL(s.Service)
	if soapURL == nil || err != nil {
		return nil, errors.Errorf("SDK URL (%s) could not be parsed: %s", s.Service, err)
	}

	// update the service URL with the resolved soapURL
	s.Service = soapURL.String()

	// we can't set a keep alive if we log in directly with client creation
	user := soapURL.User
	soapURL.User = nil

	// 1st connect without any userinfo to get the API type
	s.Client, err = govmomi.NewClient(ctx, soapURL, s.Insecure)
	if err != nil {
		return nil, errors.Errorf("Failed to connect to %s: %s", soapURL.String(), err)
	}

	if s.HasCertificate() && s.Client.IsVC() {
		// load the certificates
		cert, err2 := tls.X509KeyPair([]byte(s.ExtensionCert), []byte(s.ExtensionKey))
		if err2 != nil {
			return nil, errors.Errorf("Unable to load X509 key pair(%s,%s): %s",
				s.ExtensionCert, s.ExtensionKey, err2)
		}

		// create the new client
		s.Client, err = govmomi.NewClientWithCertificate(ctx, soapURL, s.Insecure, cert)
		if err != nil {
			return nil, errors.Errorf("Failed to connect to %s: %s", soapURL.String(), err)
		}
	}

	if s.Keepalive != 0 {
		// now that we've verified everything, enable keepalive
		s.RoundTripper = session.KeepAlive(s.Client.RoundTripper, s.Keepalive)
	}

	// and now that the keepalive is registered we can log in to trigger it
	if !s.IsVC() || !s.HasCertificate() {
		log.Debugf("Trying to log in with username/password in lieu of cert")
		err = s.Client.Login(ctx, user)
	} else {
		log.Debugf("Logging into extension %s", s.ExtensionName)
		err = s.LoginExtensionByCertificate(ctx, s.ExtensionName, "")
	}
	if err != nil {
		return nil, errors.Errorf("Failed to log in to %s: %s", soapURL.String(), err)
	}

	s.Finder = find.NewFinder(s.Vim25(), true)
	// log high-level environement information
	s.logEnvironmentInfo()
	return s, nil
}
Esempio n. 6
0
func (i *vSphereInstanceManager) createClient(ctx context.Context) (*govmomi.Client, error) {
	client, err := govmomi.NewClient(ctx, i.vSphereURL, true)
	if err != nil {
		return nil, err
	}

	client.Client.RoundTripper = vim25.Retry(client.Client.RoundTripper, vim25.TemporaryNetworkError(3))

	return client, nil
}
Esempio n. 7
0
func TestServeHTTP(t *testing.T) {
	configs := []struct {
		content types.ServiceContent
		folder  mo.Folder
	}{
		{esx.ServiceContent, esx.RootFolder},
		{vc.ServiceContent, vc.RootFolder},
	}

	for _, config := range configs {
		s := New(NewServiceInstance(config.content, config.folder))
		ts := s.NewServer()
		defer ts.Close()

		ctx := context.Background()
		client, err := govmomi.NewClient(ctx, ts.URL, true)
		if err != nil {
			t.Fatal(err)
		}

		err = client.Login(ctx, nil)
		if err == nil {
			t.Fatal("expected invalid login error")
		}

		err = client.Login(ctx, url.UserPassword("user", "pass"))
		if err != nil {
			t.Fatal(err)
		}

		// Testing http client + reflect client
		clients := []soap.RoundTripper{client, s.client}
		for _, c := range clients {
			now, err := methods.GetCurrentTime(ctx, c)
			if err != nil {
				t.Fatal(err)
			}

			if now.After(time.Now()) {
				t.Fail()
			}

			// test the fail/Fault path
			_, err = methods.QueryVMotionCompatibility(ctx, c, &types.QueryVMotionCompatibility{})
			if err == nil {
				t.Errorf("expected error")
			}
		}

		err = client.Logout(ctx)
		if err != nil {
			t.Error(err)
		}
	}
}
Esempio n. 8
0
func (c *Config) Client() (*vim25.Client, error) {
	u, err := url.Parse(fmt.Sprintf("https://%s:%s@%s/sdk", c.User, c.Password, c.vCenter))
	if err != nil {
		return nil, fmt.Errorf("Incorrect vCenter server address: %s", err)
	}
	client, err := govmomi.NewClient(context.TODO(), u, c.Insecure)
	if err != nil {
		return nil, fmt.Errorf("Error setting up client: %s", err)
	}
	log.Printf("[INFO] vSphere Client configured")
	return client.Client, nil
}
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:", u)

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

	// Connect and log in to ESX or vCenter
	client, err := govmomi.NewClient(ctx, u, *insecureFlag)
	if err != nil {
		exit(err)
	}

	if client.IsVC() {
		fmt.Println("connected to vCenter")
	} else {
		fmt.Println("connected to ESXi host")
	}

	var perfManager mo.PerformanceManager
	err = client.RetrieveOne(ctx, *client.ServiceContent.PerfManager, nil, &perfManager)
	perfCounters := perfManager.PerfCounter

	counterDetails := make([][]string, 0)

	for _, perfCounter := range perfCounters {
		groupInfo := perfCounter.GroupInfo.GetElementDescription()
		nameInfo := perfCounter.NameInfo.GetElementDescription()

		fullName := groupInfo.Key + "." + nameInfo.Key + "." + fmt.Sprint(perfCounter.RollupType)
		counterDetails = append(counterDetails, []string{fullName, fmt.Sprint(perfCounter.Level), nameInfo.Summary})
	}

	outputFile, err := os.Create("performanceCounters.csv")
	csvWriter := csv.NewWriter(outputFile)
	csvWriter.WriteAll(counterDetails)

	if err := csvWriter.Error(); err != nil {
		log.Fatalln("error writing csv:", err)
	}
}
Esempio n. 10
0
// Initialize establishes a connection to the remote vSphere API endpoint.
func (bv *BaseVSphere) Initialize() error {
	bv.ctx, bv.cancel = context.WithCancel(context.Background())

	// Connect and login to the VMWare vSphere API endpoint
	c, err := govmomi.NewClient(bv.ctx, bv.url, bv.Insecure)
	if err != nil {
		return err
	}

	bv.client = c
	bv.finder = find.NewFinder(bv.client.Client, true)

	return nil
}
Esempio n. 11
0
// Client() returns a new client for accessing VMWare vSphere.
func (c *Config) Client() (*govmomi.Client, error) {
	u, err := url.Parse("https://" + c.VSphereServer + "/sdk")
	if err != nil {
		return nil, fmt.Errorf("Error parse url: %s", err)
	}

	u.User = url.UserPassword(c.User, c.Password)

	client, err := govmomi.NewClient(context.TODO(), u, c.InsecureFlag)
	if err != nil {
		return nil, fmt.Errorf("Error setting up client: %s", err)
	}

	log.Printf("[INFO] VMWare vSphere Client configured for URL: %s", u)

	return client, nil
}
Esempio n. 12
0
// Returns a client which communicates with vCenter.
// This client can used to perform further vCenter operations.
func vsphereLogin(cfg *VSphereConfig, ctx context.Context) (*govmomi.Client, error) {
	// Parse URL from string
	u, err := url.Parse(fmt.Sprintf("https://%s:%s/sdk", cfg.Global.VCenterIP, cfg.Global.VCenterPort))
	if err != nil {
		return nil, err
	}
	// set username and password for the URL
	u.User = url.UserPassword(cfg.Global.User, cfg.Global.Password)

	// Connect and log in to ESX or vCenter
	c, err := govmomi.NewClient(ctx, u, cfg.Global.InsecureFlag)
	if err != nil {
		return nil, err
	}

	return c, nil
}
Esempio n. 13
0
func (d *Driver) vsphereLogin(ctx context.Context) (*govmomi.Client, error) {

	// Parse URL from string
	u, err := url.Parse(fmt.Sprintf("https://%s:%d/sdk", d.IP, d.Port))
	if err != nil {
		return nil, err
	}
	// set username and password for the URL
	u.User = url.UserPassword(d.Username, d.Password)

	// Connect and log in to ESX or vCenter
	c, err := govmomi.NewClient(ctx, u, true)
	if err != nil {
		return nil, err
	}

	return c, nil
}
Esempio n. 14
0
func TestFolderESX(t *testing.T) {
	content := esx.ServiceContent
	s := New(NewServiceInstance(content, esx.RootFolder))

	ts := s.NewServer()
	defer ts.Close()

	ctx := context.Background()
	c, err := govmomi.NewClient(ctx, ts.URL, true)
	if err != nil {
		t.Fatal(err)
	}

	f := object.NewRootFolder(c.Client)

	_, err = f.CreateFolder(ctx, "foo")
	if err == nil {
		t.Error("expected error")
	}

	_, err = f.CreateDatacenter(ctx, "foo")
	if err == nil {
		t.Error("expected error")
	}

	finder := find.NewFinder(c.Client, false)
	dc, err := finder.DatacenterOrDefault(ctx, "")
	if err != nil {
		t.Fatal(err)
	}

	folders, err := dc.Folders(ctx)
	if err != nil {
		t.Fatal(err)
	}

	spec := types.HostConnectSpec{}
	_, err = addStandaloneHost(folders.HostFolder, spec)
	if err == nil {
		t.Fatal("expected error")
	}
}
Esempio n. 15
0
func newClient(cfg *VSphereConfig, ctx context.Context) (*govmomi.Client, error) {
	// Parse URL from string
	u, err := url.Parse(fmt.Sprintf("https://%s:%s/sdk", cfg.Global.VCenterIP, cfg.Global.VCenterPort))
	if err != nil {
		return nil, err
	}
	// set username and password for the URL
	u.User = url.UserPassword(cfg.Global.User, cfg.Global.Password)

	// Connect and log in to ESX or vCenter
	c, err := govmomi.NewClient(ctx, u, cfg.Global.InsecureFlag)
	if err != nil {
		return nil, err
	}

	// Add retry functionality
	c.RoundTripper = vim25.Retry(c.RoundTripper, vim25.TemporaryNetworkError(int(cfg.Global.RoundTripperCount)))

	return c, nil
}
Esempio n. 16
0
func TestDefaultESX(t *testing.T) {
	s := New(NewServiceInstance(esx.ServiceContent, esx.RootFolder))

	ts := s.NewServer()
	defer ts.Close()

	ctx := context.Background()

	client, err := govmomi.NewClient(ctx, ts.URL, true)
	if err != nil {
		t.Fatal(err)
	}

	finder := find.NewFinder(client.Client, false)

	dc, err := finder.DatacenterOrDefault(ctx, "")
	if err != nil {
		t.Fatal(err)
	}

	finder.SetDatacenter(dc)

	host, err := finder.HostSystemOrDefault(ctx, "*")
	if err != nil {
		t.Fatal(err)
	}

	if host.Name() != esx.HostSystem.Summary.Config.Name {
		t.Fail()
	}

	pool, err := finder.ResourcePoolOrDefault(ctx, "*")
	if err != nil {
		t.Fatal(err)
	}

	if pool.Name() != "Resources" {
		t.Fail()
	}
}
Esempio n. 17
0
func TestCreateVm(t *testing.T) {
	ctx := context.Background()

	for _, model := range []*Model{ESX(), VPX()} {
		defer model.Remove()
		err := model.Create()
		if err != nil {
			t.Fatal(err)
		}

		s := model.Service.NewServer()
		defer s.Close()

		c, err := govmomi.NewClient(ctx, s.URL, true)
		if err != nil {
			t.Fatal(err)
		}

		spec := types.VirtualMachineConfigSpec{
			// Note: real ESX allows the VM to be created without a GuestId,
			// but will power on will fail.
			GuestId: string(types.VirtualMachineGuestOsIdentifierOtherGuest),
		}

		steps := []func(){
			func() {
				spec.Name = "test"
			},
			func() {
				spec.Files = &types.VirtualMachineFileInfo{
					VmPathName: fmt.Sprintf("[LocalDS_0] %s/%s.vmx", spec.Name, spec.Name),
				}
			},
		}

		finder := find.NewFinder(c.Client, false)

		dc, err := finder.DefaultDatacenter(ctx)
		if err != nil {
			t.Fatal(err)
		}

		finder.SetDatacenter(dc)

		folders, err := dc.Folders(ctx)
		if err != nil {
			t.Fatal(err)
		}

		hosts, err := finder.HostSystemList(ctx, "*/*")
		if err != nil {
			t.Fatal(err)
		}

		nhosts := len(hosts)
		host := hosts[rand.Intn(nhosts)]
		pool, err := host.ResourcePool(ctx)
		if err != nil {
			t.Fatal(err)
		}

		if nhosts == 1 {
			// test the default path against the ESX model
			host = nil
		}

		vmFolder := folders.VmFolder
		// expecting CreateVM to fail until all steps are taken
		for _, step := range steps {
			task, cerr := vmFolder.CreateVM(ctx, spec, pool, host)
			if cerr != nil {
				t.Fatal(err)
			}

			_, cerr = task.WaitForResult(ctx, nil)
			if cerr == nil {
				t.Error("expected error")
			}

			step()
		}

		task, err := vmFolder.CreateVM(ctx, spec, pool, host)
		if err != nil {
			t.Fatal(err)
		}

		info, err := task.WaitForResult(ctx, nil)
		if err != nil {
			t.Fatal(err)
		}

		vm := object.NewVirtualMachine(c.Client, info.Result.(types.ManagedObjectReference))

		name, err := vm.ObjectName(ctx)
		if err != nil {
			t.Fatal(err)
		}

		if name != spec.Name {
			t.Errorf("name=%s", name)
		}

		_, err = vm.Device(ctx)
		if err != nil {
			t.Fatal(err)
		}

		recreate := func(context.Context) (*object.Task, error) {
			return vmFolder.CreateVM(ctx, spec, pool, nil)
		}

		ops := []struct {
			method func(context.Context) (*object.Task, error)
			state  types.VirtualMachinePowerState
			fail   bool
		}{
			// Powered off by default
			{nil, types.VirtualMachinePowerStatePoweredOff, false},
			// Create with same .vmx path should fail
			{recreate, "", true},
			// Off -> On  == ok
			{vm.PowerOn, types.VirtualMachinePowerStatePoweredOn, false},
			// On  -> On  == fail
			{vm.PowerOn, types.VirtualMachinePowerStatePoweredOn, true},
			// On  -> Off == ok
			{vm.PowerOff, types.VirtualMachinePowerStatePoweredOff, false},
			// Off -> Off == fail
			{vm.PowerOff, types.VirtualMachinePowerStatePoweredOff, true},
			// Off -> On  == ok
			{vm.PowerOn, types.VirtualMachinePowerStatePoweredOn, false},
			// Destroy == fail (power is On)
			{vm.Destroy, types.VirtualMachinePowerStatePoweredOn, true},
			// On  -> Off == ok
			{vm.PowerOff, types.VirtualMachinePowerStatePoweredOff, false},
			// Destroy == ok (power is Off)
			{vm.Destroy, "", false},
		}

		for i, op := range ops {
			if op.method != nil {
				task, err = op.method(ctx)
				if err != nil {
					t.Fatal(err)
				}

				err = task.Wait(ctx)
				if op.fail {
					if err == nil {
						t.Errorf("%d: expected error", i)
					}
				} else {
					if err != nil {
						t.Errorf("%d: %s", i, err)
					}
				}
			}

			if len(op.state) != 0 {
				state, err := vm.PowerState(ctx)
				if err != nil {
					t.Fatal(err)
				}

				if state != op.state {
					t.Errorf("state=%s", state)
				}
			}
		}
	}
}
Esempio n. 18
0
func TestServeHTTPErrors(t *testing.T) {
	s := New(NewServiceInstance(esx.ServiceContent, esx.RootFolder))

	ts := s.NewServer()
	defer ts.Close()

	ctx := context.Background()
	client, err := govmomi.NewClient(ctx, ts.URL, true)
	if err != nil {
		t.Fatal(err)
	}

	// unregister type, covering the ServeHTTP UnmarshalBody error path
	typeFunc = func(name string) (reflect.Type, bool) {
		return nil, false
	}

	_, err = methods.GetCurrentTime(ctx, client)
	if err == nil {
		t.Error("expected error")
	}

	typeFunc = types.TypeFunc() // reset

	// cover the does not implement method error path
	Map.objects[serviceInstance] = &errorNoSuchMethod{}
	_, err = methods.GetCurrentTime(ctx, client)
	if err == nil {
		t.Error("expected error")
	}

	// cover the xml encode error path
	Map.objects[serviceInstance] = &errorMarshal{}
	_, err = methods.GetCurrentTime(ctx, client)
	if err == nil {
		t.Error("expected error")
	}

	// cover the no such object path
	Map.Remove(serviceInstance)
	_, err = methods.GetCurrentTime(ctx, client)
	if err == nil {
		t.Error("expected error")
	}

	// verify we properly marshal the fault
	fault := soap.ToSoapFault(err).VimFault()
	f, ok := fault.(types.ManagedObjectNotFound)
	if !ok {
		t.Fatalf("fault=%#v", fault)
	}
	if f.Obj != serviceInstance.Reference() {
		t.Errorf("obj=%#v", f.Obj)
	}

	// cover the method not supported path
	res, err := http.Get(ts.URL.String())
	if err != nil {
		log.Fatal(err)
	}

	if res.StatusCode != http.StatusMethodNotAllowed {
		t.Errorf("expected status %d, got %s", http.StatusMethodNotAllowed, res.Status)
	}

	// cover the ioutil.ReadAll error path
	s.readAll = func(io.Reader) ([]byte, error) {
		return nil, io.ErrShortBuffer
	}
	res, err = http.Post(ts.URL.String(), "none", nil)
	if err != nil {
		log.Fatal(err)
	}

	if res.StatusCode != http.StatusBadRequest {
		t.Errorf("expected status %d, got %s", http.StatusBadRequest, res.Status)
	}
}
func doRegistration(ui packer.Ui, config Config, vmx string, clonerequired bool) error {

	sdkURL, err := url.Parse(fmt.Sprintf("https://%s:%s@%s/sdk",
		url.QueryEscape(config.Username),
		url.QueryEscape(config.Password),
		config.Host))
	if err != nil {
		return err
	}

	client, err := govmomi.NewClient(context.TODO(), sdkURL, true)

	if err != nil {
		return err
	}

	finder := find.NewFinder(client.Client, false)
	datacenter, err := finder.DefaultDatacenter(context.TODO())
	finder.SetDatacenter(datacenter)
	if err != nil {
		return err
	}

	folders, err := datacenter.Folders(context.TODO())
	if err != nil {
		return err
	}

	resourcePool, err := finder.DefaultResourcePool(context.TODO())

	if err != nil {
		return err
	}

	splitString := strings.Split(vmx, "/")
	last := splitString[len(splitString)-1]
	vmName := strings.TrimSuffix(last, ".vmx")

	datastoreString := fmt.Sprintf("[%s] %s/%s.vmx", config.Datastore, config.VMFolder, vmName)

	ui.Message(fmt.Sprintf("Registering %s from %s", vmName, datastoreString))
	task, err := folders.VmFolder.RegisterVM(context.TODO(), datastoreString, vmName, false, resourcePool, nil)
	if err != nil {
		return err
	}
	_, err = task.WaitForResult(context.TODO(), nil)
	if err != nil {
		return err
	}
	ui.Message(fmt.Sprintf("Registererd VM %s", vmName))

	vm, err := finder.VirtualMachine(context.TODO(), vmName)

	rpRef := resourcePool.Reference()

	if clonerequired {
		cloneSpec := types.VirtualMachineCloneSpec{
			Location: types.VirtualMachineRelocateSpec{
				Pool: &rpRef,
			},
		}

		cloneVmName := fmt.Sprintf("%s-vm", vmName)

		ui.Message(fmt.Sprintf("Cloning VM %s", cloneVmName))
		task, err = vm.Clone(context.TODO(), folders.VmFolder, cloneVmName, cloneSpec)

		if err != nil {
			return err
		}

		_, err = task.WaitForResult(context.TODO(), nil)

		if err != nil {
			return err
		}

		clonedVM, err := finder.VirtualMachine(context.TODO(), cloneVmName)

		if err != nil {
			return err
		}

		ui.Message(fmt.Sprintf("Powering on %s", cloneVmName))
		task, err = clonedVM.PowerOn(context.TODO())

		if err != nil {
			return err
		}

		_, err = task.WaitForResult(context.TODO(), nil)
		if err != nil {
			return err
		}

		ui.Message(fmt.Sprintf("Powered on %s", cloneVmName))

		timeout := time.After(5 * time.Minute)
		tick := time.Tick(500 * time.Millisecond)

	LoopWaitForVMToolsRunning:
		for {
			select {
			case <-timeout:
				task, err = clonedVM.PowerOff(context.TODO())
				if err != nil {
					return err
				}
				_, err = task.WaitForResult(context.TODO(), nil)
				if err != nil {
					return err
				}
				return fmt.Errorf("Timed out while waiting for VM Tools to be recogonized")
			case <-tick:
				running, err := clonedVM.IsToolsRunning(context.TODO())
				if err != nil {
					return err
				}
				if running {
					break LoopWaitForVMToolsRunning
				}
			}
		}

		ui.Message(fmt.Sprintf("Powering off %s", cloneVmName))
		task, err = clonedVM.PowerOff(context.TODO())

		if err != nil {
			return err
		}

		_, err = task.WaitForResult(context.TODO(), nil)

		if err != nil {
			return err
		}
		ui.Message(fmt.Sprintf("Powered off %s", cloneVmName))

		ui.Message(fmt.Sprintf("Marking as template %s", cloneVmName))
		err = clonedVM.MarkAsTemplate(context.TODO())

		if err != nil {
			return err
		}

		ui.Message(fmt.Sprintf("Destroying %s", cloneVmName))
		task, err = vm.Destroy(context.TODO())

		_, err = task.WaitForResult(context.TODO(), nil)

		if err != nil {
			return err
		}
		ui.Message(fmt.Sprintf("Destroyed %s", cloneVmName))
	} else {
		ui.Message(fmt.Sprintf("Marking as template %s", vmName))
		err = vm.MarkAsTemplate(context.TODO())

		if err != nil {
			return err
		}
		ui.Message(fmt.Sprintf("%s is now a template", vmName))
	}

	return nil
}
func doRegistration(ui packer.Ui, config Config, vmx string, clonerequired bool) (err error) {

	sdkURL, err := url.Parse(fmt.Sprintf("https://%s:%s@%s/sdk",
		url.QueryEscape(config.Username),
		url.QueryEscape(config.Password),
		config.Host))
	if err != nil {
		return err
	}

	client, err := govmomi.NewClient(context.TODO(), sdkURL, true)

	if err != nil {
		return err
	}

	finder := find.NewFinder(client.Client, false)
	datacenter, err := finder.DefaultDatacenter(context.TODO())
	finder.SetDatacenter(datacenter)
	if err != nil {
		return err
	}

	folders, err := datacenter.Folders(context.TODO())
	if err != nil {
		return err
	}

	resourcePool, err := finder.DefaultResourcePool(context.TODO())

	if err != nil {
		return err
	}

	splitString := strings.Split(vmx, "/")
	last := splitString[len(splitString)-1]
	vmName := strings.TrimSuffix(last, ".vmx")

	datastoreString := fmt.Sprintf("[%s] %s/%s.vmx", config.Datastore, config.VMFolder, vmName)

	ui.Message(fmt.Sprintf("Registering %s from %s", vmName, datastoreString))
	task, err := folders.VmFolder.RegisterVM(context.TODO(), datastoreString, vmName, false, resourcePool, nil)
	if err != nil {
		return err
	}
	_, err = task.WaitForResult(context.TODO(), nil)
	if err != nil {
		return err
	}
	ui.Message(fmt.Sprintf("Registererd VM %s", vmName))

	vm, err := finder.VirtualMachine(context.TODO(), vmName)

	rpRef := resourcePool.Reference()

	if clonerequired {
		cloneSpec := types.VirtualMachineCloneSpec{
			Location: types.VirtualMachineRelocateSpec{
				Pool: &rpRef,
			},
		}

		cloneVmName := fmt.Sprintf("%s-vm", vmName)

		ui.Message(fmt.Sprintf("Cloning VM %s", cloneVmName))
		task, err = vm.Clone(context.TODO(), folders.VmFolder, cloneVmName, cloneSpec)

		if err != nil {
			return err
		}

		_, err = task.WaitForResult(context.TODO(), nil)

		if err != nil {
			return err
		}

		clonedVM, err := finder.VirtualMachine(context.TODO(), cloneVmName)

		if err != nil {
			return err
		}

		ui.Message(fmt.Sprintf("Powering on %s", cloneVmName))
		task, err = clonedVM.PowerOn(context.TODO())

		if err != nil {
			return err
		}

		_, err = task.WaitForResult(context.TODO(), nil)
		if err != nil {
			return err
		}

		ui.Message(fmt.Sprintf("Powered on %s", cloneVmName))

		time.Sleep(150000 * time.Millisecond) // This is really dirty, but I need to make sure the VM gets fully powered on before I turn it off, otherwise vmware tools won't register on the cloning side.

		ui.Message(fmt.Sprintf("Powering off %s", cloneVmName))
		task, err = clonedVM.PowerOff(context.TODO())

		if err != nil {
			return err
		}

		_, err = task.WaitForResult(context.TODO(), nil)

		if err != nil {
			return err
		}
		ui.Message(fmt.Sprintf("Powered off %s", cloneVmName))

		ui.Message(fmt.Sprintf("Marking as template %s", cloneVmName))
		err = clonedVM.MarkAsTemplate(context.TODO())

		if err != nil {
			return err
		}

		ui.Message(fmt.Sprintf("Destroying %s", cloneVmName))
		task, err = vm.Destroy(context.TODO())

		_, err = task.WaitForResult(context.TODO(), nil)

		if err != nil {
			return err
		}
		ui.Message(fmt.Sprintf("Destroyed %s", cloneVmName))
	} else {
		ui.Message(fmt.Sprintf("Marking as template %s", vmName))
		err = vm.MarkAsTemplate(context.TODO())

		if err != nil {
			return err
		}
		ui.Message(fmt.Sprintf("%s is now a template", vmName))
	}

	return nil
}
Esempio n. 21
0
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)
	}

	// 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, "*")
	if err != nil {
		exit(err)
	}

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

	// Print name per virtual machine
	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()
}
Esempio n. 22
0
func TestFolderVC(t *testing.T) {
	content := vc.ServiceContent
	s := New(NewServiceInstance(content, vc.RootFolder))

	ts := s.NewServer()
	defer ts.Close()

	ctx := context.Background()
	c, err := govmomi.NewClient(ctx, ts.URL, true)
	if err != nil {
		t.Fatal(err)
	}

	f := object.NewRootFolder(c.Client)

	ff, err := f.CreateFolder(ctx, "foo")
	if err != nil {
		t.Error(err)
	}

	dc, err := f.CreateDatacenter(ctx, "bar")
	if err != nil {
		t.Error(err)
	}

	for _, ref := range []object.Reference{ff, dc} {
		o := Map.Get(ref.Reference())
		if o == nil {
			t.Fatalf("failed to find %#v", ref)
		}

		e := o.(mo.Entity).Entity()
		if *e.Parent != f.Reference() {
			t.Fail()
		}
	}

	dc, err = ff.CreateDatacenter(ctx, "biz")
	if err != nil {
		t.Error(err)
	}

	folders, err := dc.Folders(ctx)
	if err != nil {
		t.Fatal(err)
	}

	tests := []struct {
		name  string
		state types.TaskInfoState
	}{
		{"", types.TaskInfoStateError},
		{"foo.local", types.TaskInfoStateSuccess},
	}

	for _, test := range tests {
		spec := types.HostConnectSpec{
			HostName: test.name,
		}

		task, err := addStandaloneHost(folders.HostFolder, spec)
		if err != nil {
			t.Fatal(err)
		}

		res, err := task.WaitForResult(ctx, nil)
		if test.state == types.TaskInfoStateError {
			if err == nil {
				t.Error("expected error")
			}

			if res.Result != nil {
				t.Error("expected nil")
			}
		} else {
			if err != nil {
				t.Fatal(err)
			}

			ref, ok := res.Result.(types.ManagedObjectReference)
			if !ok {
				t.Errorf("expected moref, got type=%T", res.Result)
			}
			host := Map.Get(ref).(*HostSystem)
			if host.Name != test.name {
				t.Fail()
			}

			if ref == esx.HostSystem.Self {
				t.Error("expected new host Self reference")
			}

			pool := Map.Get(*host.Parent).(*mo.ComputeResource).ResourcePool
			if *pool == esx.ResourcePool.Self {
				t.Error("expected new pool Self reference")
			}
		}

		if res.State != test.state {
			t.Fatalf("%s", res.State)
		}
	}
}
Esempio n. 23
0
func TestServeHTTPS(t *testing.T) {
	s := New(NewServiceInstance(esx.ServiceContent, esx.RootFolder))
	s.TLS = new(tls.Config)
	ts := s.NewServer()
	defer ts.Close()

	ctx := context.Background()
	// insecure=true OK
	client, err := govmomi.NewClient(ctx, ts.URL, true)
	if err != nil {
		t.Fatal(err)
	}

	err = client.Login(ctx, ts.URL.User)
	if err != nil {
		t.Fatal(err)
	}

	// insecure=false should FAIL
	_, err = govmomi.NewClient(ctx, ts.URL, false)
	if err == nil {
		t.Fatal("expected error")
	}

	uerr, ok := err.(*url.Error)
	if !ok {
		t.Fatalf("err type=%T", err)
	}

	_, ok = uerr.Err.(x509.UnknownAuthorityError)
	if !ok {
		t.Fatalf("err type=%T", uerr.Err)
	}

	sinfo := ts.CertificateInfo()

	// Test thumbprint validation
	sc := soap.NewClient(ts.URL, false)
	// Add host with thumbprint mismatch should fail
	sc.SetThumbprint(ts.URL.Host, "nope")
	_, err = vim25.NewClient(ctx, sc)
	if err == nil {
		t.Error("expected error")
	}
	// Add host with thumbprint match should pass
	sc.SetThumbprint(ts.URL.Host, sinfo.ThumbprintSHA1)
	_, err = vim25.NewClient(ctx, sc)
	if err != nil {
		t.Fatal(err)
	}

	var pinfo object.HostCertificateInfo
	err = pinfo.FromURL(ts.URL, nil)
	if err != nil {
		t.Fatal(err)
	}
	if pinfo.ThumbprintSHA1 != sinfo.ThumbprintSHA1 {
		t.Error("thumbprint mismatch")
	}

	// Test custom RootCAs list
	sc = soap.NewClient(ts.URL, false)
	caFile, err := ts.CertificateFile()
	if err != nil {
		t.Fatal(err)
	}
	if err = sc.SetRootCAs(caFile); err != nil {
		t.Fatal(err)
	}

	_, err = vim25.NewClient(ctx, sc)
	if err != nil {
		t.Fatal(err)
	}
}
func (s *StepFixNetwork) Run(state multistep.StateBag) multistep.StepAction {
	ui := state.Get("ui").(packer.Ui)
	ui.Say("Waiting for vm")
	time.Sleep(20 * time.Second)

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// Parse URL from string
	// url.
	u, err := url.Parse(s.VCenterSDKURL)
	if err != nil {
		ui.Error(err.Error())
		return multistep.ActionHalt
	}
	// Connect and log in to ESX or vCenter
	c, err := govmomi.NewClient(ctx, u, true)
	if err != nil {
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	f := find.NewFinder(c.Client, true)

	ui.Say("Getting DataCenter ")

	// Find one and only datacenter
	dc, err := f.Datacenter(ctx, s.DataCenter)
	if err != nil {
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	ui.Message(fmt.Sprintf("DataCenter Name : %s", dc.String()))

	// Make future calls local to this datacenter
	f.SetDatacenter(dc)

	var qualifiedVMName = "/" + s.DataCenter + "/vm/Discovered virtual machine/" + s.VMName

	fmt.Printf("qualifiedVMName VM %s", qualifiedVMName)

	// Find vm in datacenter
	vm, err := f.VirtualMachine(ctx, qualifiedVMName)
	if err != nil {
		ui.Message(fmt.Sprintf("Retrying to get VM using QualifiedVMName VM %s", s.QualifiedVMName))
		vm, err = f.VirtualMachine(ctx, s.QualifiedVMName)

		if err != nil {
			ui.Error(err.Error())
			return multistep.ActionHalt
		}
	}

	err = delVNIC(ui, f, ctx, vm)

	if err != nil {
		ui.Error(err.Error())
		return multistep.ActionHalt
	}
	ui.Say("Waiting for delete nic")
	time.Sleep(20 * time.Second)

	err = addVNIC(ui, f, ctx, c, vm, s.Network, s.NetworkType)
	if err != nil {
		ui.Error(err.Error())
		return multistep.ActionHalt
	}
	ui.Say("Waiting for add nic")
	time.Sleep(20 * time.Second)

	return multistep.ActionContinue
}
Esempio n. 25
0
func TestRetrieveProperties(t *testing.T) {
	configs := []struct {
		folder  mo.Folder
		content types.ServiceContent
		dc      *types.ManagedObjectReference
	}{
		{esx.RootFolder, esx.ServiceContent, &esx.Datacenter.Self},
		{vc.RootFolder, vc.ServiceContent, nil},
	}

	for _, config := range configs {
		s := New(NewServiceInstance(config.content, config.folder))

		ts := s.NewServer()
		defer ts.Close()

		ctx := context.Background()

		client, err := govmomi.NewClient(ctx, ts.URL, true)
		if err != nil {
			t.Fatal(err)
		}

		if config.dc == nil {
			dc, cerr := object.NewRootFolder(client.Client).CreateDatacenter(ctx, "dc1")
			if cerr != nil {
				t.Fatal(cerr)
			}
			ref := dc.Reference()
			config.dc = &ref
		}

		// Retrieve a specific property
		f := mo.Folder{}
		err = client.RetrieveOne(ctx, config.content.RootFolder, []string{"name"}, &f)
		if err != nil {
			t.Fatal(err)
		}

		if f.Name != config.folder.Name {
			t.Fail()
		}

		// Retrieve all properties
		f = mo.Folder{}
		err = client.RetrieveOne(ctx, config.content.RootFolder, nil, &f)
		if err != nil {
			t.Fatal(err)
		}

		if f.Name != config.folder.Name {
			t.Fatalf("'%s' vs '%s'", f.Name, config.folder.Name)
		}

		// Retrieve an ArrayOf property
		f = mo.Folder{}
		err = client.RetrieveOne(ctx, config.content.RootFolder, []string{"childEntity"}, &f)
		if err != nil {
			t.Fatal(err)
		}

		if len(f.ChildEntity) != 1 {
			t.Fail()
		}

		es, err := mo.Ancestors(ctx, client.Client, config.content.PropertyCollector, config.content.RootFolder)
		if err != nil {
			t.Fatal(err)
		}

		if len(es) != 1 {
			t.Fail()
		}

		finder := find.NewFinder(client.Client, false)
		dc, err := finder.DatacenterOrDefault(ctx, "")
		if err != nil {
			t.Fatal(err)
		}

		if dc.Reference() != *config.dc {
			t.Fail()
		}

		finder.SetDatacenter(dc)

		es, err = mo.Ancestors(ctx, client.Client, config.content.PropertyCollector, dc.Reference())
		if err != nil {
			t.Fatal(err)
		}

		expect := map[string]types.ManagedObjectReference{
			"Folder":     config.folder.Reference(),
			"Datacenter": dc.Reference(),
		}

		if len(es) != len(expect) {
			t.Fail()
		}

		for _, e := range es {
			ref := e.Reference()
			if r, ok := expect[ref.Type]; ok {
				if r != ref {
					t.Errorf("%#v vs %#v", r, ref)
				}
			} else {
				t.Errorf("unexpected object %#v", e.Reference())
			}
		}

		// finder tests
		ls, err := finder.ManagedObjectListChildren(ctx, ".")
		if err != nil {
			t.Error(err)
		}

		folders, err := dc.Folders(ctx)
		if err != nil {
			t.Fatal(err)
		}

		// Validated name properties are recursively retrieved for the datacenter and its folder children
		ipaths := []string{
			folders.VmFolder.InventoryPath,
			folders.HostFolder.InventoryPath,
			folders.DatastoreFolder.InventoryPath,
			folders.NetworkFolder.InventoryPath,
		}

		var lpaths []string
		for _, p := range ls {
			lpaths = append(lpaths, p.Path)
		}

		if !reflect.DeepEqual(ipaths, lpaths) {
			t.Errorf("%#v != %#v\n", ipaths, lpaths)
		}

		// We have no VMs, expect NotFoundError
		_, err = finder.VirtualMachineList(ctx, "*")
		if err == nil {
			t.Error("expected error")
		} else {
			if _, ok := err.(*find.NotFoundError); !ok {
				t.Error(err)
			}
		}

		// Retrieve a missing property
		mdc := mo.Datacenter{}
		err = client.RetrieveOne(ctx, dc.Reference(), []string{"enoent"}, &mdc)
		if err == nil {
			t.Error("expected error")
		} else {
			switch fault := soap.ToVimFault(err).(type) {
			case *types.InvalidProperty:
				// ok
			default:
				t.Errorf("unexpected fault: %#v", fault)
			}
		}

		// Retrieve a nested property
		Map.Get(dc.Reference()).(*mo.Datacenter).Configuration.DefaultHardwareVersionKey = "foo"
		mdc = mo.Datacenter{}
		err = client.RetrieveOne(ctx, dc.Reference(), []string{"configuration.defaultHardwareVersionKey"}, &mdc)
		if err != nil {
			t.Fatal(err)
		}
		if mdc.Configuration.DefaultHardwareVersionKey != "foo" {
			t.Fail()
		}

		// Retrieve a missing nested property
		mdc = mo.Datacenter{}
		err = client.RetrieveOne(ctx, dc.Reference(), []string{"configuration.enoent"}, &mdc)
		if err == nil {
			t.Error("expected error")
		} else {
			switch fault := soap.ToVimFault(err).(type) {
			case *types.InvalidProperty:
				// ok
			default:
				t.Errorf("unexpected fault: %#v", fault)
			}
		}

		// Retrieve an empty property
		err = client.RetrieveOne(ctx, dc.Reference(), []string{""}, &mdc)
		if err != nil {
			t.Error(err)
		}

		// Expect ManagedObjectNotFoundError
		Map.Remove(dc.Reference())
		err = client.RetrieveOne(ctx, dc.Reference(), []string{"name"}, &mdc)
		if err == nil {
			t.Fatal("expected error")
		}
	}
}
Esempio n. 26
0
func TestHostDatastoreSystem(t *testing.T) {
	s := New(NewServiceInstance(esx.ServiceContent, esx.RootFolder))

	ts := s.NewServer()
	defer ts.Close()

	ctx := context.Background()

	c, err := govmomi.NewClient(ctx, ts.URL, true)
	if err != nil {
		t.Fatal(err)
	}

	host := object.NewHostSystem(c.Client, esx.HostSystem.Reference())

	dss, err := host.ConfigManager().DatastoreSystem(ctx)
	if err != nil {
		t.Error(err)
	}

	pwd, err := os.Getwd()
	if err != nil {
		t.Fatal(err)
	}

	spec := types.HostNasVolumeSpec{
		Type:       string(types.HostFileSystemVolumeFileSystemTypeNFS),
		RemoteHost: "localhost",
	}

	tests := []func(string) (*object.Datastore, error){
		func(dir string) (*object.Datastore, error) {
			spec.LocalPath = dir
			spec.RemotePath = dir
			return dss.CreateNasDatastore(ctx, spec)
		},
		func(dir string) (*object.Datastore, error) {
			return dss.CreateLocalDatastore(ctx, filepath.Base(dir), dir)
		},
	}

	for _, create := range tests {
		for _, fail := range []bool{false, true} {
			if fail {
				_, err = create(pwd)
				if err == nil {
					t.Error("expected error")
				}

				// TODO: hds.Remove(ds)
				pwd = filepath.Join(pwd, "esx")
			} else {
				_, err = create(pwd)
				if err != nil {
					t.Error(err)
				}
			}
		}
	}

	for _, create := range tests {
		for _, dir := range []string{"./enoent", "host_datastore_system.go"} {
			_, err = create(dir)

			if err == nil {
				t.Error("expected error")
			}
		}
	}
}
Esempio n. 27
0
func main() {

	vcUrl := flag.String("url", GetEnvString(envURL, ""), fmt.Sprintf("vCenter Connect URL [%s]", envURL))
	insecure := flag.Bool("insecure", GetEnvBool(envInsecure, false), fmt.Sprintf("Don't verify Certificate [%s]", envInsecure))

	flag.Parse()

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	url, err := url.Parse(*vcUrl)
	if err != nil {
		exit(err)
	}

	client, err := govmomi.NewClient(ctx, url, *insecure)
	if err != nil {
		exit(err)
	}

	finder := find.NewFinder(client.Client, false)

	dc, err := finder.DefaultDatacenter(ctx)

	if err != nil {
		exit(err)
	}

	filter := types.EventFilterSpec{
		Entity: &types.EventFilterSpecByEntity{
			Entity:    dc.Reference(),
			Recursion: types.EventFilterSpecRecursionOptionAll,
		},
	}

	eventManager := event.NewManager(client.Client)

	collector, err := eventManager.CreateCollectorForEvents(ctx, filter)
	defer collector.Destroy(ctx)

	collector.SetPageSize(ctx, 0)
	collector.Reset(ctx)

	for true {
		items, err := collector.ReadNextEvents(ctx, 10)

		if err != nil {
			exit(err)
		}

		for _, e := range items {
			category, _ := eventManager.EventCategory(ctx, e)
			event := e.GetEvent()
			msg := strings.TrimSpace(event.FullFormattedMessage)
			m := make(map[string]string)
			t := event.CreatedTime
			m["time"] = strconv.FormatInt(t.Unix(), 10)
			m["type"] = "Event"
			if t, ok := e.(*types.TaskEvent); ok {
				m["type"] = "Task"
				m["targetType"] = t.Info.Entity.Type
				m["targetName"] = t.Info.EntityName
			}
			m["message"] = msg
			m["category"] = category
			if event.Host != nil && event.Host.Name != "" {
				m["host"] = event.Host.Name
			}
			if event.Vm != nil && event.Vm.Name != "" {
				m["vm"] = event.Vm.Name
			}
			if event.UserName != "" {
				m["username"] = event.UserName
			}
			s, _ := json.Marshal(m)
			fmt.Printf("%s\n", string(s))
		}
		time.Sleep(10 * 1000 * 1000 * 1000)

	}
}
Esempio n. 28
0
func TestDatastoreHTTP(t *testing.T) {
	ctx := context.Background()
	src := "datastore_test.go"
	dst := "tmp.go"

	for _, model := range []*Model{ESX(), VPX()} {
		defer model.Remove()
		err := model.Create()
		if err != nil {
			t.Fatal(err)
		}

		s := model.Service.NewServer()
		defer s.Close()

		c, err := govmomi.NewClient(ctx, s.URL, true)
		if err != nil {
			t.Fatal(err)
		}

		finder := find.NewFinder(c.Client, false)

		dc, err := finder.DefaultDatacenter(ctx)
		if err != nil {
			t.Fatal(err)
		}

		finder.SetDatacenter(dc)

		ds, err := finder.DefaultDatastore(ctx)
		if err != nil {
			t.Fatal(err)
		}

		dsPath := ds.Path

		if !c.IsVC() {
			dc = nil // test using the default
		}

		fm := object.NewFileManager(c.Client)
		browser, err := ds.Browser(ctx)
		if err != nil {
			t.Fatal(err)
		}

		download := func(name string, fail bool) {
			st, serr := ds.Stat(ctx, name)

			_, _, err = ds.Download(ctx, name, nil)
			if fail {
				if err == nil {
					t.Fatal("expected Download error")
				}
				if serr == nil {
					t.Fatal("expected Stat error")
				}
			} else {
				if err != nil {
					t.Errorf("Download error: %s", err)
				}
				if serr != nil {
					t.Errorf("Stat error: %s", serr)
				}

				p := st.GetFileInfo().Path
				if p != name {
					t.Errorf("path=%s", p)
				}
			}
		}

		upload := func(name string, fail bool, method string) {
			f, err := os.Open(src)
			if err != nil {
				t.Fatal(err)
			}
			defer f.Close()

			p := soap.DefaultUpload
			p.Method = method

			err = ds.Upload(ctx, f, name, &p)
			if fail {
				if err == nil {
					t.Fatalf("%s %s: expected error", method, name)
				}
			} else {
				if err != nil {
					t.Fatal(err)
				}
			}
		}

		rm := func(name string, fail bool) {
			task, err := fm.DeleteDatastoreFile(ctx, dsPath(name), dc)
			if err != nil {
				t.Fatal(err)
			}

			err = task.Wait(ctx)
			if fail {
				if err == nil {
					t.Fatalf("rm %s: expected error", name)
				}
			} else {
				if err != nil {
					t.Fatal(err)
				}
			}
		}

		mv := func(src string, dst string, fail bool, force bool) {
			task, err := fm.MoveDatastoreFile(ctx, dsPath(src), dc, dsPath(dst), dc, force)
			if err != nil {
				t.Fatal(err)
			}

			err = task.Wait(ctx)
			if fail {
				if err == nil {
					t.Fatalf("mv %s %s: expected error", src, dst)
				}
			} else {
				if err != nil {
					t.Fatal(err)
				}
			}
		}

		mkdir := func(name string, fail bool, p bool) {
			err := fm.MakeDirectory(ctx, dsPath(name), dc, p)
			if fail {
				if err == nil {
					t.Fatalf("mkdir %s: expected error", name)
				}
			} else {
				if err != nil {
					t.Fatal(err)
				}
			}
		}

		stat := func(name string, fail bool) {
			_, err := ds.Stat(ctx, name)
			if fail {
				if err == nil {
					t.Fatalf("stat %s: expected error", name)
				}
			} else {
				if err != nil {
					t.Fatal(err)
				}
			}
		}

		ls := func(name string, fail bool) []types.BaseFileInfo {
			spec := types.HostDatastoreBrowserSearchSpec{
				MatchPattern: []string{"*"},
			}

			task, err := browser.SearchDatastore(ctx, dsPath(name), &spec)
			if err != nil {
				t.Fatal(err)
			}

			info, err := task.WaitForResult(ctx, nil)
			if err != nil {
				if fail {
					if err == nil {
						t.Fatalf("ls %s: expected error", name)
					}
				} else {
					if err != nil {
						t.Fatal(err)
					}
				}
				return nil
			}

			return info.Result.(types.HostDatastoreBrowserSearchResults).File
		}

		// GET file does not exist = fail
		download(dst, true)
		stat(dst, true)
		ls(dst, true)

		// delete file does not exist = fail
		rm(dst, true)

		// PUT file = ok
		upload(dst, false, "PUT")
		stat(dst, false)

		// GET file exists = ok
		download(dst, false)

		// POST file exists = fail
		upload(dst, true, "POST")

		// delete existing file = ok
		rm(dst, false)
		stat(dst, true)

		// GET file does not exist = fail
		download(dst, true)

		// POST file does not exist = ok
		upload(dst, false, "POST")

		// PATCH method not supported = fail
		upload(dst+".patch", true, "PATCH")

		// PUT path is directory = fail
		upload("", true, "PUT")

		// mkdir parent does not exist = fail
		mkdir("foo/bar", true, false)

		// mkdir -p parent does not exist = ok
		mkdir("foo/bar", false, true)

		// mkdir = ok
		mkdir("foo/bar/baz", false, false)

		target := path.Join("foo", dst)

		// mv dst not exist = ok
		mv(dst, target, false, false)

		// POST file does not exist = ok
		upload(dst, false, "POST")

		// mv dst exists = fail
		mv(dst, target, true, false)

		// mv dst exists, force=true = ok
		mv(dst, target, false, true)

		// mv src does not exist = fail
		mv(dst, target, true, true)

		invalid := []string{
			"",       //InvalidDatastorePath
			"[nope]", // InvalidDatastore
		}

		// test FileType details
		mkdir("exts", false, false)
		stat("exts", false)
		exts := []string{"img", "iso", "log", "nvram", "vmdk", "vmx"}
		for _, ext := range exts {
			name := dst + "." + ext
			upload(name, false, "POST")
			stat(name, false)
		}

		for _, p := range invalid {
			dsPath = func(name string) string {
				return p
			}
			mv(target, dst, true, false)
			mkdir("sorry", true, false)
			rm(target, true)
			ls(target, true)
		}

		// cover the dst failure path
		for _, p := range invalid {
			dsPath = func(name string) string {
				if name == dst {
					return p
				}
				return ds.Path(name)
			}
			mv(target, dst, true, false)
		}

		dsPath = func(name string) string {
			return ds.Path("enoent")
		}
		ls(target, true)

		// cover the case where datacenter or datastore lookup fails
		for _, q := range []string{"dcName=nope", "dsName=nope"} {
			u := *s.URL
			u.RawQuery = q
			u.Path = path.Join(folderPrefix, dst)

			r, err := http.Get(u.String())
			if err != nil {
				t.Fatal(err)
			}

			if r.StatusCode == http.StatusOK {
				t.Error("expected failure")
			}
		}
	}
}
Esempio n. 29
0
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)
	}

	// 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 datastores in datacenter
	dss, err := f.DatastoreList(ctx, "*")
	if err != nil {
		exit(err)
	}

	pc := property.DefaultCollector(c.Client)

	// Convert datastores into list of references
	var refs []types.ManagedObjectReference
	for _, ds := range dss {
		refs = append(refs, ds.Reference())
	}

	// Retrieve summary property for all datastores
	var dst []mo.Datastore
	err = pc.Retrieve(ctx, refs, []string{"summary"}, &dst)
	if err != nil {
		exit(err)
	}

	// Print summary per datastore
	tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
	fmt.Fprintf(tw, "Name:\tType:\tCapacity:\tFree:\n")
	for _, ds := range dst {
		fmt.Fprintf(tw, "%s\t", ds.Summary.Name)
		fmt.Fprintf(tw, "%s\t", ds.Summary.Type)
		fmt.Fprintf(tw, "%s\t", Humanize(ds.Summary.Capacity))
		fmt.Fprintf(tw, "%s\t", Humanize(ds.Summary.FreeSpace))
		fmt.Fprintf(tw, "\n")
	}
	tw.Flush()
}
Esempio n. 30
0
// TestSoapFaults covers the various soap fault checking paths
func TestSoapFaults(t *testing.T) {
	ctx := context.Background()

	// Nothing VC specific in this test, so we use the simpler ESX model
	model := simulator.ESX()
	defer model.Remove()
	err := model.Create()
	if err != nil {
		t.Fatal(err)
	}

	server := model.Service.NewServer()
	defer server.Close()

	client, err := govmomi.NewClient(ctx, server.URL, true)
	if err != nil {
		t.Fatal(err)
	}

	// Any VM will do
	finder := find.NewFinder(client.Client, false)
	vm, err := finder.VirtualMachine(ctx, "/ha-datacenter/vm/*_VM0")
	if err != nil {
		t.Fatal(err)
	}

	// Test the success path
	err = Wait(ctx, func(ctx context.Context) (Task, error) {
		return vm.PowerOn(ctx)
	})
	if err != nil {
		t.Fatal(err)
	}

	// Wrap existing vm MO with faultyVirtualMachine
	ref := simulator.Map.Get(vm.Reference())
	fvm := &faultyVirtualMachine{*ref.(*simulator.VirtualMachine), nil}
	simulator.Map.Put(fvm)

	// Inject TaskInProgress fault
	fvm.fault = new(types.TaskInProgress)
	task, err := vm.PowerOff(ctx)
	if err != nil {
		t.Fatal(err)
	}

	// Test the task.Error path
	res, err := task.WaitForResult(ctx, nil)
	if !isTaskInProgress(err) {
		t.Error(err)
	}

	// Test the soap.IsVimFault() path
	if !isTaskInProgress(soap.WrapVimFault(res.Error.Fault)) {
		t.Errorf("fault=%#v", res.Error.Fault)
	}

	// Test the soap.IsSoapFault() path
	err = vm.MarkAsTemplate(ctx)
	if !isTaskInProgress(err) {
		t.Error(err)
	}

	// Test a fault other than TaskInProgress
	fvm.fault = &types.QuestionPending{
		Text: "now why would you want to do such a thing?",
	}

	err = Wait(ctx, func(ctx context.Context) (Task, error) {
		return vm.PowerOff(ctx)
	})
	if err == nil {
		t.Error("expected error")
	}
	if isTaskInProgress(err) {
		t.Error(err)
	}

	// Test with retry
	fvm.fault = new(types.TaskInProgress)
	called := 0

	err = Wait(ctx, func(ctx context.Context) (Task, error) {
		called++
		if called > 1 {
			simulator.Map.Put(ref) // remove fault injection
		}

		return vm.PowerOff(ctx)
	})
	if err != nil {
		t.Error(err)
	}
	if called != 2 {
		t.Errorf("called=%d", called)
	}
}