Beispiel #1
1
// Mkdir creates directories.
func (d *Helper) Mkdir(ctx context.Context, createParentDirectories bool, dirs ...string) (string, error) {

	upth := path.Join(dirs...)
	upth = path.Join(d.RootURL, upth)

	log.Infof("Creating directory %s", upth)

	if err := d.fm.MakeDirectory(ctx, upth, d.s.Datacenter, createParentDirectories); err != nil {

		log.Debugf("Creating %s error: %s", upth, err)

		if err != nil {
			if soap.IsSoapFault(err) {
				soapFault := soap.ToSoapFault(err)
				if _, ok := soapFault.VimFault().(types.FileAlreadyExists); ok {
					return "", os.ErrExist
				}
			}
		}

		return "", err
	}

	return upth, nil
}
Beispiel #2
0
func isTaskInProgress(err error) bool {
	if soap.IsSoapFault(err) {
		switch f := soap.ToSoapFault(err).VimFault().(type) {
		case types.TaskInProgress:
			return true
		default:
			logSoapFault(f)
		}
	}

	if soap.IsVimFault(err) {
		switch f := soap.ToVimFault(err).(type) {
		case *types.TaskInProgress:
			return true
		default:
			logFault(f)
		}
	}

	switch err := err.(type) {
	case task.Error:
		if _, ok := err.Fault().(*types.TaskInProgress); ok {
			return true
		}
		logFault(err.Fault())
	default:
		if f, ok := err.(types.HasFault); ok {
			logFault(f.Fault())
		} else {
			logError(err)
		}
	}
	return false
}
Beispiel #3
0
func (flag *ClientFlag) loadClient() (*vim25.Client, error) {
	c := new(vim25.Client)
	ok, err := flag.restoreClient(c)
	if err != nil {
		return nil, err
	}

	if !ok || !c.Valid() {
		return nil, nil
	}

	// Add retry functionality before making any calls
	c.RoundTripper = attachRetries(c.RoundTripper)

	m := session.NewManager(c)
	u, err := m.UserSession(context.TODO())
	if err != nil {
		if soap.IsSoapFault(err) {
			fault := soap.ToSoapFault(err).VimFault()
			// If the PropertyCollector is not found, the saved session for this URL is not valid
			if _, ok := fault.(types.ManagedObjectNotFound); ok {
				return nil, nil
			}
		}

		return nil, err
	}

	// If the session is nil, the client is not authenticated
	if u == nil {
		return nil, nil
	}

	return c, nil
}
Beispiel #4
0
func (flag *SearchFlag) searchByUUID(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) {
	isVM := false
	switch flag.t {
	case SearchVirtualMachines:
		isVM = true
	case SearchHosts:
	default:
		panic("unsupported type")
	}

	var ref object.Reference
	var err error

	for _, iu := range []*bool{nil, types.NewBool(true)} {
		ref, err = flag.searchIndex(c).FindByUuid(context.TODO(), dc, flag.byUUID, isVM, iu)
		if err != nil {
			if soap.IsSoapFault(err) {
				fault := soap.ToSoapFault(err).VimFault()
				if _, ok := fault.(types.InvalidArgument); ok {
					continue
				}
			}
			return nil, err
		}
		if ref != nil {
			break
		}
	}

	return ref, nil
}
Beispiel #5
0
func isInvalidLogin(err error) bool {
	if soap.IsSoapFault(err) {
		switch soap.ToSoapFault(err).VimFault().(type) {
		case types.InvalidLogin:
			return true
		}
	}
	return false
}
Beispiel #6
0
func isNotAuthenticated(err error) bool {
	if soap.IsSoapFault(err) {
		switch soap.ToSoapFault(err).VimFault().(type) {
		case types.NotAuthenticated:
			return true
		}
	}
	return false
}
Beispiel #7
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
}
Beispiel #8
0
func (m *Manager) isDuplicateName(err error) bool {
	if soap.IsSoapFault(err) {
		fault := soap.ToSoapFault(err)
		if _, ok := fault.VimFault().(types.DuplicateName); ok {
			return true
		}
	}
	return false
}
Beispiel #9
0
// This creates the root directory in the datastore and sets the rooturl and
// rootdir in the datastore struct so we can reuse it for other routines.  This
// handles vsan + vc, vsan + esx, and esx.  The URI conventions are not the
// same for each and this tries to create the directory and stash the relevant
// result so the URI doesn't need to be recomputed for every datastore
// operation.
func (d *Helper) mkRootDir(ctx context.Context, rootdir string) error {
	if rootdir == "" {
		return fmt.Errorf("root directory is empty")
	}

	if path.IsAbs(rootdir) {
		return fmt.Errorf("root directory (%s) must not be an absolute path", rootdir)
	}

	// Handle vsan
	// Vsan will complain if the root dir exists.  Just call it directly and
	// swallow the error if it's already there.
	if d.IsVSAN(ctx) {
		comps := strings.Split(rootdir, "/")

		nm := object.NewDatastoreNamespaceManager(d.s.Vim25())

		// This returns the vmfs path (including the datastore and directory
		// UUIDs).  Use the directory UUID in future operations because it is
		// the stable path which we can use regardless of vsan state.
		uuid, err := nm.CreateDirectory(ctx, d.ds, comps[0], "")
		if err != nil {
			if !soap.IsSoapFault(err) {
				return err
			}

			soapFault := soap.ToSoapFault(err)
			if _, ok := soapFault.VimFault().(types.FileAlreadyExists); !ok {
				return err
			}

			// XXX UGLY HACK until we move this into the installer.  Use the
			// display name if the dir exists since we can't get the UUID after the
			// directory is created.
			uuid = comps[0]
			err = nil
		}

		rootdir = path.Join(path.Base(uuid), path.Join(comps[1:]...))
	}

	rooturl := d.ds.Path(rootdir)

	// create the rest of the root dir in case of vSAN, otherwise
	// create the full path
	if _, err := mkdir(ctx, d.s, d.fm, true, rooturl); err != nil {
		if !os.IsExist(err) {
			return err
		}

		log.Infof("datastore root %s already exists", rooturl)
	}

	d.RootURL = rooturl
	return nil
}
Beispiel #10
0
func isToolsUnavailable(err error) bool {
	if soap.IsSoapFault(err) {
		soapFault := soap.ToSoapFault(err)
		if _, ok := soapFault.VimFault().(types.ToolsUnavailable); ok {
			return ok
		}
	}

	return false
}
Beispiel #11
0
// This creates the root directory in the datastore and sets the rooturl and
// rootdir in the datastore struct so we can reuse it for other routines.  This
// handles vsan + vc, vsan + esx, and esx.  The URI conventions are not the
// same for each and this tries to create the directory and stash the relevant
// result so the URI doesn't need to be recomputed for every datastore
// operation.
func (d *Helper) mkRootDir(ctx context.Context, rootdir string) error {

	// Handle vsan
	// Vsan will complain if the root dir exists.  Just call it directly and
	// swallow the error if it's already there.
	if d.IsVSAN(ctx) {
		nm := object.NewDatastoreNamespaceManager(d.s.Vim25())

		// This returns the vmfs path (including the datastore and directory
		// UUIDs).  Use the directory UUID in future operations because it is
		// the stable path which we can use regardless of vsan state.
		uuid, err := nm.CreateDirectory(ctx, d.ds, rootdir, "")
		if err != nil {
			if !soap.IsSoapFault(err) {
				return err
			}

			soapFault := soap.ToSoapFault(err)
			_, ok := soapFault.VimFault().(types.FileAlreadyExists)
			if ok {
				// XXX UGLY HACK until we move this into the installer.  Use the
				// display name if the dir exists since we can't get the UUID after the
				// directory is created.

				uuid = rootdir
				err = nil
			} else {
				return err
			}
		}

		// set the root url to the UUID of the dir we created
		d.RootURL = d.ds.Path(path.Base(uuid))
		log.Infof("Created store parent directory (%s) at %s", rootdir, d.RootURL)
	} else {

		// Handle regular local datastore
		// check if it already exists

		d.RootURL = d.ds.Path(rootdir)
		if _, err := d.Mkdir(ctx, true); err != nil {
			if os.IsExist(err) {
				log.Debugf("%s already exists", d.RootURL)
				return nil
			}
			return err
		}
	}

	return nil
}
Beispiel #12
0
func mkdir(ctx context.Context, sess *session.Session, fm *object.FileManager, createParentDirectories bool, path string) (string, error) {
	log.Infof("Creating directory %s", path)

	if err := fm.MakeDirectory(ctx, path, sess.Datacenter, createParentDirectories); err != nil {
		if soap.IsSoapFault(err) {
			soapFault := soap.ToSoapFault(err)
			if _, ok := soapFault.VimFault().(types.FileAlreadyExists); ok {
				log.Debugf("File already exists: %s", path)
				return "", os.ErrExist
			}
		}
		log.Debugf("Creating %s error: %s", path, err)
		return "", err
	}

	return path, nil
}
Beispiel #13
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
}
Beispiel #14
0
func (cmd *create) Run(f *flag.FlagSet) error {
	var ctx = context.Background()

	hosts, err := cmd.HostSystems(f.Args())
	if err != nil {
		return err
	}

	object := types.ManagedObjectReference{
		Type:  "Datastore",
		Value: fmt.Sprintf("%s:%s", cmd.RemoteHost, cmd.RemotePath),
	}

	for _, host := range hosts {
		ds, err := host.ConfigManager().DatastoreSystem(ctx)
		if err != nil {
			return err
		}

		_, err = ds.CreateNasDatastore(ctx, cmd.HostNasVolumeSpec)
		if err != nil {
			if soap.IsSoapFault(err) {
				switch fault := soap.ToSoapFault(err).VimFault().(type) {
				case types.PlatformConfigFault:
					if len(fault.FaultMessage) != 0 {
						return errors.New(fault.FaultMessage[0].Message)
					}
				case types.DuplicateName:
					if cmd.Force && fault.Object == object {
						fmt.Fprintf(os.Stderr, "%s: '%s' already mounted\n",
							host.InventoryPath, cmd.LocalPath)
						continue
					}
				}
			}

			return fmt.Errorf("%s: %s", host.InventoryPath, err)
		}
	}

	return nil
}
Beispiel #15
0
func (cmd *mkdir) Run(ctx context.Context, f *flag.FlagSet) error {
	m, err := cmd.FileManager()
	if err != nil {
		return err
	}

	err = m.MakeDirectory(context.TODO(), cmd.Auth(), f.Arg(0), 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
}
Beispiel #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
}
Beispiel #17
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
}
Beispiel #18
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
}