func deleteFile(client *govmomi.Client, f *file) error {

	dc, err := getDatacenter(client, f.datacenter)
	if err != nil {
		return err
	}

	finder := find.NewFinder(client.Client, true)
	finder = finder.SetDatacenter(dc)

	ds, err := getDatastore(finder, f.datastore)
	if err != nil {
		return fmt.Errorf("error %s", err)
	}

	fm := object.NewFileManager(client.Client)
	task, err := fm.DeleteDatastoreFile(context.TODO(), ds.Path(f.destinationFile), dc)
	if err != nil {
		return err
	}

	_, err = task.WaitForResult(context.TODO(), nil)
	if err != nil {
		return err
	}
	return nil
}
Exemple #2
0
// NewDatastore returns a Datastore.
// ctx is a context,
// s is an authenticated session
// ds is the vsphere datastore
// rootdir is the top level directory to root all data.  If root does not exist,
// it will be created.  If it already exists, NOOP. This cannot be empty.
func NewDatastore(ctx context.Context, s *session.Session, ds *object.Datastore, rootdir string) (*Datastore, error) {

	d := &Datastore{
		ds: ds,
		s:  s,
		fm: object.NewFileManager(s.Vim25()),
	}

	if strings.HasPrefix(rootdir, "/") {
		rootdir = strings.TrimPrefix(rootdir, "/")
	}

	// Get the root directory element split from the rest of the path (if there is one)
	root := strings.SplitN(rootdir, "/", 2)

	// Create the first element.  This handles vsan vmfs top level dirs.
	if err := d.mkRootDir(ctx, root[0]); err != nil {
		log.Infof("error creating root directory %s: %s", rootdir, err)
		return nil, err
	}

	// Create the rest conventionally
	if len(root) > 1 {
		r, err := d.Mkdir(ctx, true, root[1])
		if err != nil {
			return nil, err
		}
		d.RootURL = r
	}

	log.Infof("Datastore path is %s", d.RootURL)
	return d, nil
}
Exemple #3
0
func (d *Dispatcher) deleteDatastoreFiles(ds *object.Datastore, path string, force bool) (bool, error) {
	defer trace.End(trace.Begin(fmt.Sprintf("path %q, force %t", path, force)))

	// refuse to delete everything on the datstore, ignore force
	if path == "" {
		dsn, _ := ds.ObjectName(d.ctx)
		msg := fmt.Sprintf("refusing to remove datastore files for path \"\" on datastore %q", dsn)
		return false, errors.New(msg)
	}

	var empty bool
	dsPath := ds.Path(path)

	res, err := d.lsFolder(ds, dsPath)
	if err != nil {
		if !types.IsFileNotFound(err) {
			err = errors.Errorf("Failed to browse folder %q: %s", dsPath, err)
			return empty, err
		}
		log.Debugf("Folder %q is not found", dsPath)
		empty = true
		return empty, nil
	}
	if len(res.File) > 0 && !force {
		log.Debugf("Folder %q is not empty, leave it there", dsPath)
		return empty, nil
	}

	m := object.NewFileManager(ds.Client())
	if err = d.deleteFilesIteratively(m, ds, dsPath); err != nil {
		return empty, err
	}
	return true, nil
}
func resourceVSphereFileUpdate(d *schema.ResourceData, meta interface{}) error {

	log.Printf("[DEBUG] updating file: %#v", d)
	if d.HasChange("destination_file") {
		oldDestinationFile, newDestinationFile := d.GetChange("destination_file")
		f := file{}

		if v, ok := d.GetOk("datacenter"); ok {
			f.datacenter = v.(string)
		}

		if v, ok := d.GetOk("datastore"); ok {
			f.datastore = v.(string)
		} else {
			return fmt.Errorf("datastore argument is required")
		}

		if v, ok := d.GetOk("source_file"); ok {
			f.sourceFile = v.(string)
		} else {
			return fmt.Errorf("source_file argument is required")
		}

		if v, ok := d.GetOk("destination_file"); ok {
			f.destinationFile = v.(string)
		} else {
			return fmt.Errorf("destination_file argument is required")
		}

		client := meta.(*govmomi.Client)
		dc, err := getDatacenter(client, f.datacenter)
		if err != nil {
			return err
		}

		finder := find.NewFinder(client.Client, true)
		finder = finder.SetDatacenter(dc)

		ds, err := getDatastore(finder, f.datastore)
		if err != nil {
			return fmt.Errorf("error %s", err)
		}

		fm := object.NewFileManager(client.Client)
		task, err := fm.MoveDatastoreFile(context.TODO(), ds.Path(oldDestinationFile.(string)), dc, ds.Path(newDestinationFile.(string)), dc, true)
		if err != nil {
			return err
		}

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

	}

	return nil
}
Exemple #5
0
func (cmd *mkdir) Run(ctx context.Context, f *flag.FlagSet) error {
	args := f.Args()
	if len(args) == 0 {
		return errors.New("missing operand")
	}

	c, err := cmd.Client()
	if err != nil {
		return err
	}

	if cmd.isNamespace {
		var uuid string
		var ds *object.Datastore

		if ds, err = cmd.Datastore(); err != nil {
			return err
		}

		path := args[0]

		nm := object.NewDatastoreNamespaceManager(c)
		if uuid, err = nm.CreateDirectory(ctx, ds, path, ""); err != nil {
			return err
		}

		fmt.Println(uuid)
	} else {
		var dc *object.Datacenter
		var path string

		dc, err = cmd.Datacenter()
		if err != nil {
			return err
		}

		path, err = cmd.DatastorePath(args[0])
		if err != nil {
			return err
		}

		m := object.NewFileManager(c)
		err = m.MakeDirectory(ctx, path, dc, cmd.createParents)

		// ignore EEXIST if -p flag is given
		if err != nil && cmd.createParents {
			if soap.IsSoapFault(err) {
				soapFault := soap.ToSoapFault(err)
				if _, ok := soapFault.VimFault().(types.FileAlreadyExists); ok {
					return nil
				}
			}
		}
	}

	return err
}
Exemple #6
0
func rm(t *testing.T, client *session.Session, name string) {
	t.Logf("deleting %s", name)
	fm := object.NewFileManager(client.Vim25())
	task, err := fm.DeleteDatastoreFile(context.TODO(), name, client.Datacenter)
	if !assert.NoError(t, err) {
		return
	}
	_, _ = task.WaitForResult(context.TODO(), nil)
}
Exemple #7
0
func testDeleteDatastoreFiles(v *validate.Validator, t *testing.T) {
	d := &Dispatcher{
		session: v.Session,
		ctx:     v.Context,
		isVC:    v.Session.IsVC(),
		force:   false,
	}

	ds := v.Session.Datastore
	m := object.NewFileManager(ds.Client())
	err := m.MakeDirectory(v.Context, ds.Path("Test/folder/data"), v.Session.Datacenter, true)
	if err != nil {
		t.Errorf("Failed to create datastore dir: %s", err)
		return
	}
	err = m.MakeDirectory(v.Context, ds.Path("Test/folder/metadata"), v.Session.Datacenter, true)
	if err != nil {
		t.Errorf("Failed to create datastore dir: %s", err)
		return
	}
	err = m.MakeDirectory(v.Context, ds.Path("Test/folder/file"), v.Session.Datacenter, true)
	if err != nil {
		t.Errorf("Failed to create datastore dir: %s", err)
		return
	}

	isVSAN := d.isVSAN(ds)
	t.Logf("datastore is vsan: %t", isVSAN)

	if err = createDatastoreFiles(d, ds, t); err != nil {
		t.Errorf("Failed to upload file: %s", err)
		return
	}

	if err = d.deleteFilesIteratively(m, ds, ds.Path("Test")); err != nil {
		t.Errorf("Failed to delete recursively: %s", err)
	}

	err = m.MakeDirectory(v.Context, ds.Path("Test/folder/data"), v.Session.Datacenter, true)
	if err != nil {
		t.Errorf("Failed to create datastore dir: %s", err)
		return
	}

	if err = createDatastoreFiles(d, ds, t); err != nil {
		t.Errorf("Failed to upload file: %s", err)
		return
	}

	if _, err = d.deleteDatastoreFiles(ds, "Test", true); err != nil {
		t.Errorf("Failed to delete recursively: %s", err)
	}
}
Exemple #8
0
func (cmd *rm) Run(ctx context.Context, f *flag.FlagSet) error {
	args := f.Args()
	if len(args) == 0 {
		return errors.New("missing operand")
	}

	c, err := cmd.Client()
	if err != nil {
		return err
	}

	var dc *object.Datacenter
	dc, err = cmd.Datacenter()
	if err != nil {
		return err
	}

	if cmd.isNamespace {
		path := args[0]

		nm := object.NewDatastoreNamespaceManager(c)
		err = nm.DeleteDirectory(ctx, dc, path)
	} else {
		var path string
		var task *object.Task

		// TODO(PN): Accept multiple args
		path, err = cmd.DatastorePath(args[0])
		if err != nil {
			return err
		}

		m := object.NewFileManager(c)
		task, err = m.DeleteDatastoreFile(ctx, path, dc)
		if err != nil {
			return err
		}

		err = task.Wait(ctx)
	}

	if err != nil {
		if types.IsFileNotFound(err) && cmd.force {
			// Ignore error
			return nil
		}
	}

	return err
}
func vmCleanup(dc *object.Datacenter, ds *object.Datastore, vmName string) error {
	client := testAccProvider.Meta().(*govmomi.Client)
	fileManager := object.NewFileManager(client.Client)
	task, err := fileManager.DeleteDatastoreFile(context.TODO(), ds.Path(vmName), dc)
	if err != nil {
		log.Printf("[ERROR] checkForDisk - Couldn't delete vm folder '%v': %v", vmName, err)
		return err
	}

	_, err = task.WaitForResult(context.TODO(), nil)
	if err != nil {
		log.Printf("[ERROR] checForDisk - Failed while deleting vm folder '%v': %v", vmName, err)
		return err
	}
	return nil
}
Exemple #10
0
// Creates a folder using the specified name.
// If the intermediate level folders do not exist,
// and the parameter createParents is true,
// all the non-existent folders are created.
func makeDirectoryInDatastore(c *govmomi.Client, dc *object.Datacenter, path string, createParents bool) error {

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

	fileManager := object.NewFileManager(c.Client)
	err := fileManager.MakeDirectory(ctx, path, dc, createParents)
	if err != nil {
		if soap.IsSoapFault(err) {
			soapFault := soap.ToSoapFault(err)
			if _, ok := soapFault.VimFault().(types.FileAlreadyExists); ok {
				return ErrFileAlreadyExist
			}
		}
	}

	return err
}
Exemple #11
0
// PrepareDestination makes sure that the destination VMDK does not yet exist.
// If the force flag is passed, it removes the existing VMDK. This functions
// exists to give a meaningful error if the remote VMDK already exists.
//
// CopyVirtualDisk can return a "<src> file does not exist" error while in fact
// the source file *does* exist and the *destination* file also exist.
//
func (cmd *vmdk) PrepareDestination(i importable) error {
	ctx := context.TODO()
	vmdkPath := i.RemoteDstVMDK()
	res, err := cmd.Datastore.Stat(ctx, vmdkPath)
	if err != nil {
		switch err.(type) {
		case object.DatastoreNoSuchDirectoryError:
			// The base path doesn't exist. Create it.
			dsPath := cmd.Datastore.Path(path.Dir(vmdkPath))
			m := object.NewFileManager(cmd.Client)
			return m.MakeDirectory(ctx, dsPath, cmd.Datacenter, true)
		case object.DatastoreNoSuchFileError:
			// Destination path doesn't exist; all good to continue with import.
			return nil
		}

		return err
	}

	// Check that the returned entry has the right type.
	switch res.(type) {
	case *types.VmDiskFileInfo:
	default:
		expected := "VmDiskFileInfo"
		actual := reflect.TypeOf(res)
		panic(fmt.Sprintf("Expected: %s, actual: %s", expected, actual))
	}

	if !cmd.force {
		dsPath := cmd.Datastore.Path(vmdkPath)
		err = fmt.Errorf("File %s already exists", dsPath)
		return err
	}

	// Delete existing disk.
	err = cmd.DeleteDisk(vmdkPath)
	if err != nil {
		return err
	}

	return nil
}
func checkForDisk(datacenter string, datastore string, vmName string, path string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		client := testAccProvider.Meta().(*govmomi.Client)
		finder := find.NewFinder(client.Client, true)

		dc, err := getDatacenter(client, datacenter)
		if err != nil {
			return err
		}
		finder.SetDatacenter(dc)

		ds, err := finder.Datastore(context.TODO(), datastore)
		if err != nil {
			log.Printf("[ERROR] checkForDisk - Couldn't find Datastore '%v': %v", datastore, err)
			return err
		}

		diskPath := vmName + "/" + path

		_, err = ds.Stat(context.TODO(), diskPath)
		if err != nil {
			log.Printf("[ERROR] checkForDisk - Couldn't stat file '%v': %v", diskPath, err)
			return err
		}

		// Cleanup
		fileManager := object.NewFileManager(client.Client)
		task, err := fileManager.DeleteDatastoreFile(context.TODO(), ds.Path(vmName), dc)
		if err != nil {
			log.Printf("[ERROR] checkForDisk - Couldn't delete vm folder '%v': %v", vmName, err)
			return err
		}

		_, err = task.WaitForResult(context.TODO(), nil)
		if err != nil {
			log.Printf("[ERROR] checForDisk - Failed while deleting vm folder '%v': %v", vmName, err)
			return err
		}

		return nil
	}
}
Exemple #13
0
func (d *Dispatcher) deleteUpgradeImages(ds *object.Datastore, settings *data.InstallerData) {
	defer trace.End(trace.Begin(""))

	log.Infof("Deleting upgrade images")

	// do clean up aggressively, even the previous operation failed with context deadline excceeded.
	d.ctx = context.Background()

	m := object.NewFileManager(ds.Client())

	file := ds.Path(path.Join(d.vmPathName, settings.ApplianceISO))
	if err := d.deleteVMFSFiles(m, ds, file); err != nil {
		log.Warnf("Image file %q is not removed for %s. Use the vSphere UI to delete content", file, err)
	}

	file = ds.Path(path.Join(d.vmPathName, settings.BootstrapISO))
	if err := d.deleteVMFSFiles(m, ds, file); err != nil {
		log.Warnf("Image file %q is not removed for %s. Use the vSphere UI to delete content", file, err)
	}
}
Exemple #14
0
func (cmd *rm) Run(f *flag.FlagSet) error {
	args := f.Args()
	if len(args) == 0 {
		return errors.New("missing operand")
	}

	c, err := cmd.Client()
	if err != nil {
		return err
	}

	dc, err := cmd.Datacenter()
	if err != nil {
		return err
	}

	// TODO(PN): Accept multiple args
	path, err := cmd.DatastorePath(args[0])
	if err != nil {
		return err
	}

	m := object.NewFileManager(c)
	task, err := m.DeleteDatastoreFile(context.TODO(), path, dc)
	if err != nil {
		return err
	}

	err = task.Wait(context.TODO())
	if err != nil {
		if types.IsFileNotFound(err) && cmd.force {
			// Ignore error
			return nil
		}
	}

	return err
}
Exemple #15
0
// GetDatastores returns a map of datastores given a map of names and urls
func GetDatastores(ctx context.Context, s *session.Session, dsURLs map[string]*url.URL) (map[string]*Helper, error) {
	stores := make(map[string]*Helper)

	fm := object.NewFileManager(s.Vim25())
	for name, dsURL := range dsURLs {

		vsDs, err := s.Finder.DatastoreOrDefault(ctx, s.DatastorePath)
		if err != nil {
			return nil, err
		}

		d := &Helper{
			ds:      vsDs,
			s:       s,
			fm:      fm,
			RootURL: dsURL.Path,
		}

		stores[name] = d
	}

	return stores, nil
}
Exemple #16
0
func (cmd *mkdir) Run(f *flag.FlagSet) error {
	args := f.Args()
	if len(args) == 0 {
		return errors.New("missing operand")
	}

	c, err := cmd.Client()
	if err != nil {
		return err
	}

	dc, err := cmd.Datacenter()
	if err != nil {
		return err
	}

	// TODO(PN): Accept multiple args
	path, err := cmd.DatastorePath(args[0])
	if err != nil {
		return err
	}

	m := object.NewFileManager(c)
	err = m.MakeDirectory(context.TODO(), path, dc, cmd.createParents)

	// ignore EEXIST if -p flag is given
	if err != nil && cmd.createParents {
		if soap.IsSoapFault(err) {
			soapFault := soap.ToSoapFault(err)
			if _, ok := soapFault.VimFault().(types.FileAlreadyExists); ok {
				return nil
			}
		}
	}

	return err
}
Exemple #17
0
// NewDatastore returns a Datastore.
// ctx is a context,
// s is an authenticated session
// ds is the vsphere datastore
// rootdir is the top level directory to root all data.  If root does not exist,
// it will be created.  If it already exists, NOOP. This cannot be empty.
func NewHelper(ctx context.Context, s *session.Session, ds *object.Datastore, rootdir string) (*Helper, error) {

	d := &Helper{
		ds: ds,
		s:  s,
		fm: object.NewFileManager(s.Vim25()),
	}

	if path.IsAbs(rootdir) {
		rootdir = rootdir[1:]
	}

	if err := d.mkRootDir(ctx, rootdir); err != nil {
		log.Infof("error creating root directory %s: %s", rootdir, err)
		return nil, err
	}

	if d.RootURL == "" {
		return nil, fmt.Errorf("failed to create root directory")
	}

	log.Infof("Datastore path is %s", d.RootURL)
	return d, nil
}
Exemple #18
0
func (cmd *mv) Run(f *flag.FlagSet) error {
	args := f.Args()
	if len(args) != 2 {
		return errors.New("SRC and DST arguments are required")
	}

	c, err := cmd.Client()
	if err != nil {
		return err
	}

	dc, err := cmd.Datacenter()
	if err != nil {
		return err
	}

	// TODO: support cross-datacenter move

	src, err := cmd.DatastorePath(args[0])
	if err != nil {
		return err
	}

	dst, err := cmd.DatastorePath(args[1])
	if err != nil {
		return err
	}

	m := object.NewFileManager(c)
	task, err := m.MoveDatastoreFile(context.TODO(), src, dc, dst, dc, cmd.force)
	if err != nil {
		return err
	}

	return task.Wait(context.TODO())
}
func (d *Driver) Remove() error {
	machineState, err := d.GetState()
	if err != nil {
		return err
	}
	if machineState == state.Running {
		if err = d.Kill(); err != nil {
			return fmt.Errorf("can't stop VM: %s", err)
		}
	}
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	c, err := d.vsphereLogin(ctx)
	if err != nil {
		return err
	}
	defer c.Logout(ctx)

	// Create a new finder
	f := find.NewFinder(c.Client, true)

	dc, err := f.DatacenterOrDefault(ctx, d.Datacenter)
	if err != nil {
		return err
	}

	f.SetDatacenter(dc)

	dss, err := f.DatastoreOrDefault(ctx, d.Datastore)
	if err != nil {
		return err
	}

	// Remove B2D Iso from VM folder
	m := object.NewFileManager(c.Client)
	task, err := m.DeleteDatastoreFile(ctx, dss.Path(fmt.Sprintf("%s/%s", d.MachineName, isoFilename)), dc)
	if err != nil {
		return err
	}

	err = task.Wait(ctx)
	if err != nil {
		if types.IsFileNotFound(err) {
			// Ignore error
			return nil
		}
	}

	vm, err := d.fetchVM(c, ctx, d.MachineName)
	if err != nil {
		return err
	}

	task, err = vm.Destroy(ctx)
	if err != nil {
		return err
	}

	_, err = task.WaitForResult(ctx, nil)
	if err != nil {
		return err
	}
	return nil
}
Exemple #20
0
func (c *Container) Remove(ctx context.Context, sess *session.Session) error {
	defer trace.End(trace.Begin("Container.Remove"))
	c.Lock()
	defer c.Unlock()

	if c.vm == nil {
		return NotFoundError{}
	}

	// check state first
	if c.State == StateRunning {
		return RemovePowerError{fmt.Errorf("Container is powered on")}
	}

	// get existing state and set to removing
	// if there's a failure we'll revert to existing
	existingState := c.State
	c.State = StateRemoving

	// get the folder the VM is in
	url, err := c.vm.DSPath(ctx)
	if err != nil {

		// handle the out-of-band removal case
		if soap.IsSoapFault(err) {
			fault := soap.ToSoapFault(err).VimFault()
			if _, ok := fault.(types.ManagedObjectNotFound); ok {
				containers.Remove(c.ExecConfig.ID)
				return NotFoundError{}
			}
		}

		log.Errorf("Failed to get datastore path for %s: %s", c.ExecConfig.ID, err)
		c.State = existingState
		return err
	}
	// FIXME: was expecting to find a utility function to convert to/from datastore/url given
	// how widely it's used but couldn't - will ask around.
	dsPath := fmt.Sprintf("[%s] %s", url.Host, url.Path)

	//removes the vm from vsphere, but detaches the disks first
	_, err = tasks.WaitForResult(ctx, func(ctx context.Context) (tasks.ResultWaiter, error) {
		return c.vm.DeleteExceptDisks(ctx)
	})
	if err != nil {
		c.State = existingState
		return err
	}

	// remove from datastore
	fm := object.NewFileManager(c.vm.Client.Client)

	if _, err = tasks.WaitForResult(ctx, func(ctx context.Context) (tasks.ResultWaiter, error) {
		return fm.DeleteDatastoreFile(ctx, dsPath, sess.Datacenter)
	}); err != nil {
		c.State = existingState
		log.Debugf("Failed to delete %s, %s", dsPath, err)
	}

	//remove container from cache
	containers.Remove(c.ExecConfig.ID)
	return nil
}
Exemple #21
0
// Create a disk, make an ext filesystem on it, set the label, mount it,
// unmount it, then clean up.
func TestCreateFS(t *testing.T) {
	log.SetLevel(log.DebugLevel)

	client := Session(context.Background(), t)
	if client == nil {
		return
	}

	imagestore := client.Datastore.Path(datastore.TestName("diskTest"))

	fm := object.NewFileManager(client.Vim25())

	// create a directory in the datastore
	// eat the error because we dont care if it exists
	fm.MakeDirectory(context.TODO(), imagestore, nil, true)

	// Nuke the image store
	defer func() {
		task, err := fm.DeleteDatastoreFile(context.TODO(), imagestore, nil)
		if err != nil && err.Error() == "can't find the hosting vm" {
			t.Skip("Skipping: test must be run in a VM")
		}
		if !assert.NoError(t, err) {
			return
		}
		_, err = task.WaitForResult(context.TODO(), nil)
		if !assert.NoError(t, err) {
			return
		}
	}()

	op := trace.NewOperation(context.TODO(), "test")

	vdm, err := NewDiskManager(op, client)
	if err != nil && err.Error() == "can't find the hosting vm" {
		t.Skip("Skipping: test must be run in a VM")
	}
	if !assert.NoError(t, err) || !assert.NotNil(t, vdm) {
		return
	}

	diskSize := int64(1 << 10)
	d, err := vdm.CreateAndAttach(op, path.Join(imagestore, "scratch.vmdk"), "", diskSize, os.O_RDWR)
	if !assert.NoError(t, err) {
		return
	}

	// make the filesysetem
	if err = d.Mkfs("foo"); !assert.NoError(t, err) {
		return
	}

	// set the label
	if err = d.SetLabel("foo"); !assert.NoError(t, err) {
		return
	}

	// make a tempdir to mount the fs to
	dir, err := ioutil.TempDir("", "mnt")
	if !assert.NoError(t, err) {
		return
	}
	defer os.RemoveAll(dir)

	// do the mount
	err = d.Mount(dir, nil)
	if !assert.NoError(t, err) {
		return
	}

	// boom
	if mounted, err := mount.Mounted(dir); !assert.NoError(t, err) || !assert.True(t, mounted) {
		return
	}

	//  clean up
	err = d.Unmount()
	if !assert.NoError(t, err) {
		return
	}

	err = vdm.Detach(op, d)
	if !assert.NoError(t, err) {
		return
	}
}
Exemple #22
0
// Remove removes a containerVM after detaching the disks
func (c *Container) Remove(ctx context.Context, sess *session.Session) error {
	defer trace.End(trace.Begin(c.ExecConfig.ID))
	c.m.Lock()
	defer c.m.Unlock()

	if c.vm == nil {
		return NotFoundError{}
	}

	// check state first
	if c.state == StateRunning {
		return RemovePowerError{fmt.Errorf("Container is powered on")}
	}

	// get existing state and set to removing
	// if there's a failure we'll revert to existing
	existingState := c.updateState(StateRemoving)

	// get the folder the VM is in
	url, err := c.vm.DSPath(ctx)
	if err != nil {

		// handle the out-of-band removal case
		if soap.IsSoapFault(err) {
			fault := soap.ToSoapFault(err).VimFault()
			if _, ok := fault.(types.ManagedObjectNotFound); ok {
				Containers.Remove(c.ExecConfig.ID)
				return NotFoundError{}
			}
		}

		log.Errorf("Failed to get datastore path for %s: %s", c.ExecConfig.ID, err)
		c.updateState(existingState)
		return err
	}
	// FIXME: was expecting to find a utility function to convert to/from datastore/url given
	// how widely it's used but couldn't - will ask around.
	dsPath := fmt.Sprintf("[%s] %s", url.Host, url.Path)

	//removes the vm from vsphere, but detaches the disks first
	_, err = c.vm.WaitForResult(ctx, func(ctx context.Context) (tasks.Task, error) {
		return c.vm.DeleteExceptDisks(ctx)
	})
	if err != nil {
		f, ok := err.(types.HasFault)
		if !ok {
			c.updateState(existingState)
			return err
		}
		switch f.Fault().(type) {
		case *types.InvalidState:
			log.Warnf("container VM is in invalid state, unregistering")
			if err := c.vm.Unregister(ctx); err != nil {
				log.Errorf("Error while attempting to unregister container VM: %s", err)
				return err
			}
		default:
			log.Debugf("Fault while attempting to destroy vm: %#v", f.Fault())
			c.updateState(existingState)
			return err
		}
	}

	// remove from datastore
	fm := object.NewFileManager(c.vm.Client.Client)

	if _, err = tasks.WaitForResult(ctx, func(ctx context.Context) (tasks.Task, error) {
		return fm.DeleteDatastoreFile(ctx, dsPath, sess.Datacenter)
	}); err != nil {
		// at this phase error doesn't matter. Just log it.
		log.Debugf("Failed to delete %s, %s", dsPath, err)
	}

	//remove container from cache
	Containers.Remove(c.ExecConfig.ID)
	return nil
}
Exemple #23
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")
			}
		}
	}
}
Exemple #24
0
// Create a lineage of disks inheriting from eachother, write portion of a
// string to each, the confirm the result is the whole string
func TestCreateAndDetach(t *testing.T) {
	log.SetLevel(log.DebugLevel)

	client := Session(context.Background(), t)
	if client == nil {
		return
	}

	imagestore := client.Datastore.Path(datastore.TestName("diskManagerTest"))

	fm := object.NewFileManager(client.Vim25())

	// create a directory in the datastore
	// eat the error because we dont care if it exists
	fm.MakeDirectory(context.TODO(), imagestore, nil, true)

	vdm, err := NewDiskManager(context.TODO(), client)
	if err != nil && err.Error() == "can't find the hosting vm" {
		t.Skip("Skipping: test must be run in a VM")
	}

	if !assert.NoError(t, err) || !assert.NotNil(t, vdm) {
		return
	}

	diskSize := int64(1 << 10)
	parent, err := vdm.Create(context.TODO(), path.Join(imagestore, "scratch.vmdk"), diskSize)
	if !assert.NoError(t, err) {
		return
	}

	numChildren := 3
	children := make([]*VirtualDisk, numChildren)

	testString := "Ground control to Major Tom"
	writeSize := len(testString) / numChildren
	// Create children which inherit from eachother
	for i := 0; i < numChildren; i++ {

		p := path.Join(imagestore, fmt.Sprintf("child%d.vmdk", i))
		child, cerr := vdm.CreateAndAttach(context.TODO(), p, parent.DatastoreURI, 0, os.O_RDWR)
		if !assert.NoError(t, cerr) {
			return
		}

		children[i] = child

		// Write directly to the disk
		f, cerr := os.OpenFile(child.DevicePath, os.O_RDWR, os.FileMode(0777))
		if !assert.NoError(t, cerr) {
			return
		}

		start := i * writeSize
		end := start + writeSize

		if i == numChildren-1 {
			// last chunk, write to the end.
			_, cerr = f.WriteAt([]byte(testString[start:]), int64(start))
			if !assert.NoError(t, cerr) || !assert.NoError(t, f.Sync()) {
				return
			}

			// Try to read the whole string
			b := make([]byte, len(testString))
			f.Seek(0, 0)
			_, cerr = f.Read(b)
			if !assert.NoError(t, cerr) {
				return
			}

			//check against the test string
			if !assert.Equal(t, testString, string(b)) {
				return
			}

		} else {
			_, cerr = f.WriteAt([]byte(testString[start:end]), int64(start))
			if !assert.NoError(t, cerr) || !assert.NoError(t, f.Sync()) {
				return
			}
		}

		f.Close()

		cerr = vdm.Detach(context.TODO(), child)
		if !assert.NoError(t, cerr) {
			return
		}

		// use this image as the next parent
		parent = child
	}

	//	// Nuke the images
	//	for i := len(children) - 1; i >= 0; i-- {
	//		err = vdm.Delete(context.TODO(), children[i])
	//		if !assert.NoError(t, err) {
	//			return
	//		}
	//	}

	// Nuke the image store
	_, err = tasks.WaitForResult(context.TODO(), func(ctx context.Context) (tasks.ResultWaiter, error) {
		return fm.DeleteDatastoreFile(ctx, imagestore, nil)
	})

	if !assert.NoError(t, err) {
		return
	}
}
func resourceVSphereFileUpdate(d *schema.ResourceData, meta interface{}) error {

	log.Printf("[DEBUG] updating file: %#v", d)

	if d.HasChange("destination_file") || d.HasChange("datacenter") || d.HasChange("datastore") {
		// File needs to be moved, get old and new destination changes
		var oldDataceneter, newDatacenter, oldDatastore, newDatastore, oldDestinationFile, newDestinationFile string
		if d.HasChange("datacenter") {
			tmpOldDataceneter, tmpNewDatacenter := d.GetChange("datacenter")
			oldDataceneter = tmpOldDataceneter.(string)
			newDatacenter = tmpNewDatacenter.(string)
		} else {
			if v, ok := d.GetOk("datacenter"); ok {
				oldDataceneter = v.(string)
				newDatacenter = oldDataceneter
			}
		}
		if d.HasChange("datastore") {
			tmpOldDatastore, tmpNewDatastore := d.GetChange("datastore")
			oldDatastore = tmpOldDatastore.(string)
			newDatastore = tmpNewDatastore.(string)
		} else {
			oldDatastore = d.Get("datastore").(string)
			newDatastore = oldDatastore
		}
		if d.HasChange("destination_file") {
			tmpOldDestinationFile, tmpNewDestinationFile := d.GetChange("destination_file")
			oldDestinationFile = tmpOldDestinationFile.(string)
			newDestinationFile = tmpNewDestinationFile.(string)
		} else {
			oldDestinationFile = d.Get("destination_file").(string)
			newDestinationFile = oldDestinationFile
		}

		// Get old and new dataceter and datastore
		client := meta.(*govmomi.Client)
		dcOld, err := getDatacenter(client, oldDataceneter)
		if err != nil {
			return err
		}
		dcNew, err := getDatacenter(client, newDatacenter)
		if err != nil {
			return err
		}
		finder := find.NewFinder(client.Client, true)
		finder = finder.SetDatacenter(dcOld)
		dsOld, err := getDatastore(finder, oldDatastore)
		if err != nil {
			return fmt.Errorf("error %s", err)
		}
		finder = finder.SetDatacenter(dcNew)
		dsNew, err := getDatastore(finder, newDatastore)
		if err != nil {
			return fmt.Errorf("error %s", err)
		}

		// Move file between old/new dataceter, datastore and path (destination_file)
		fm := object.NewFileManager(client.Client)
		task, err := fm.MoveDatastoreFile(context.TODO(), dsOld.Path(oldDestinationFile), dcOld, dsNew.Path(newDestinationFile), dcNew, true)
		if err != nil {
			return err
		}
		_, err = task.WaitForResult(context.TODO(), nil)
		if err != nil {
			return err
		}
	}

	return nil
}
Exemple #26
0
func TestVolumeCreateListAndRestart(t *testing.T) {
	client := datastore.Session(context.TODO(), t)
	if client == nil {
		return
	}

	ctx := context.TODO()

	// Create the backing store on vsphere
	vsVolumeStore, err := NewVolumeStore(ctx, client)
	if !assert.NoError(t, err) || !assert.NotNil(t, vsVolumeStore) {
		return
	}

	// Root our datastore
	testStorePath := datastore.TestName("voltest")
	ds, err := datastore.NewHelper(ctx, client, client.Datastore, testStorePath)
	if !assert.NoError(t, err) || !assert.NotNil(t, ds) {
		return
	}

	// Add a volume store and give it a name ("testStoreName")
	volumeStore, err := vsVolumeStore.AddStore(ctx, ds, "testStoreName")
	if !assert.NoError(t, err) || !assert.NotNil(t, volumeStore) {
		return
	}

	// test we can list it
	m, err := vsVolumeStore.VolumeStoresList(ctx)
	if !assert.NoError(t, err) || !assert.NotNil(t, m) {
		return
	}

	// test the returned url matches
	s, ok := m["testStoreName"]
	if !assert.True(t, ok) || !assert.Equal(t, testStorePath, filepath.Base(s.String())) {
		return
	}

	// Clean up the mess
	defer func() {
		fm := object.NewFileManager(client.Vim25())
		tasks.WaitForResult(context.TODO(), func(ctx context.Context) (tasks.ResultWaiter, error) {
			return fm.DeleteDatastoreFile(ctx, client.Datastore.Path(testStorePath), client.Datacenter)
		})
	}()

	// Create the cache
	cache, err := portlayer.NewVolumeLookupCache(ctx, vsVolumeStore)
	if !assert.NoError(t, err) || !assert.NotNil(t, cache) {
		return
	}

	// Create the volumes (in parallel)
	numVols := 5
	wg := &sync.WaitGroup{}
	wg.Add(numVols)
	volumes := make(map[string]*portlayer.Volume)
	for i := 0; i < numVols; i++ {
		go func(idx int) {
			defer wg.Done()
			ID := fmt.Sprintf("testvolume-%d", idx)

			// add some metadata if i is even
			var info map[string][]byte

			if idx%2 == 0 {
				info = make(map[string][]byte)
				info[ID] = []byte(ID)
			}

			outVol, err := cache.VolumeCreate(ctx, ID, volumeStore, 10240, info)
			if !assert.NoError(t, err) || !assert.NotNil(t, outVol) {
				return
			}

			volumes[ID] = outVol
		}(i)
	}

	wg.Wait()

	// list using the datastore (skipping the cache)
	outVols, err := vsVolumeStore.VolumesList(ctx)
	if !assert.NoError(t, err) || !assert.NotNil(t, outVols) || !assert.Equal(t, numVols, len(outVols)) {
		return
	}

	for _, outVol := range outVols {
		if !assert.Equal(t, volumes[outVol.ID], outVol) {
			return
		}
	}

	// Test restart

	// Create a new vs and cache to the same datastore (simulating restart) and compare
	secondVStore, err := NewVolumeStore(ctx, client)
	if !assert.NoError(t, err) || !assert.NotNil(t, vsVolumeStore) {
		return
	}

	volumeStore, err = secondVStore.AddStore(ctx, ds, "testStoreName")
	if !assert.NoError(t, err) || !assert.NotNil(t, volumeStore) {
		return
	}
	secondCache, err := portlayer.NewVolumeLookupCache(ctx, secondVStore)
	if !assert.NoError(t, err) || !assert.NotNil(t, cache) {
		return
	}

	secondOutVols, err := secondCache.VolumesList(ctx)
	if !assert.NoError(t, err) || !assert.NotNil(t, secondOutVols) || !assert.Equal(t, numVols, len(secondOutVols)) {
		return
	}

	for _, outVol := range secondOutVols {
		// XXX we could compare the Volumes, but the paths are different the
		// second time around on vsan since the vsan UUID is not included.
		if !assert.NotEmpty(t, volumes[outVol.ID].Device.DiskPath()) {
			return
		}
	}
}
func createFile(client *govmomi.Client, f *file) error {

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

	dc, err := finder.Datacenter(context.TODO(), f.datacenter)
	if err != nil {
		return fmt.Errorf("error %s", err)
	}
	finder = finder.SetDatacenter(dc)

	ds, err := getDatastore(finder, f.datastore)
	if err != nil {
		return fmt.Errorf("error %s", err)
	}

	if f.copyFile {
		// Copying file from withing vSphere
		source_dc, err := finder.Datacenter(context.TODO(), f.sourceDatacenter)
		if err != nil {
			return fmt.Errorf("error %s", err)
		}
		finder = finder.SetDatacenter(dc)

		source_ds, err := getDatastore(finder, f.sourceDatastore)
		if err != nil {
			return fmt.Errorf("error %s", err)
		}

		fm := object.NewFileManager(client.Client)
		if f.createDirectories {
			directoryPathIndex := strings.LastIndex(f.destinationFile, "/")
			path := f.destinationFile[0:directoryPathIndex]
			err = fm.MakeDirectory(context.TODO(), ds.Path(path), dc, true)
			if err != nil {
				return fmt.Errorf("error %s", err)
			}
		}
		task, err := fm.CopyDatastoreFile(context.TODO(), source_ds.Path(f.sourceFile), source_dc, ds.Path(f.destinationFile), dc, true)

		if err != nil {
			return fmt.Errorf("error %s", err)
		}

		_, err = task.WaitForResult(context.TODO(), nil)
		if err != nil {
			return fmt.Errorf("error %s", err)
		}

	} else {
		// Uploading file to vSphere
		dsurl, err := ds.URL(context.TODO(), dc, f.destinationFile)
		if err != nil {
			return fmt.Errorf("error %s", err)
		}

		p := soap.DefaultUpload
		err = client.Client.UploadFile(f.sourceFile, dsurl, &p)
		if err != nil {
			return fmt.Errorf("error %s", err)
		}
	}

	return nil
}