// Run returns JSON responses to each command or an error
func (mockCmd MockVmdkCmd) Run(cmd string, name string, opts map[string]string) ([]byte, error) {
	// We store no in memory state, so just try to recreate backingRoot every time
	rootName := fmt.Sprintf("%s/%d", backingRoot, os.Getpid())
	err := fs.Mkdir(rootName)
	if err != nil {
		return nil, err
	}
	log.WithFields(log.Fields{"cmd": cmd}).Debug("Running Mock Cmd")
	switch cmd {
	case "create":
		err := createBlockDevice(name, opts)
		return nil, err
	case "list":
		return list()
	case "get":
		return nil, get(name)
	case "attach":
		return getBlockDeviceForName(name)
	case "detach":
		return nil, nil
	case "remove":
		err := remove(name)
		return nil, err
	}
	return []byte("null"), nil
}
// Request attach and them mounts the volume.
// Actual mount - send attach to ESX and do the in-guest magic
// Returns mount point and  error (or nil)
func (d *vmdkDriver) mountVolume(name string, fstype string, isReadOnly bool) (string, error) {
	mountpoint := getMountPoint(name)

	// First, make sure  that mountpoint exists.
	err := fs.Mkdir(mountpoint)
	if err != nil {
		log.WithFields(
			log.Fields{"name": name, "dir": mountpoint},
		).Error("Failed to make directory for volume mount ")
		return mountpoint, err
	}

	skipInotify := false

	watcher, err := inotify.NewWatcher()

	if err != nil {
		log.WithFields(
			log.Fields{"name": name, "dir": mountpoint},
		).Error("Failed to create watcher, skip inotify ")
		skipInotify = true
	} else {
		err = watcher.Watch(watchPath)
		if err != nil {
			log.WithFields(
				log.Fields{"name": name, "dir": mountpoint},
			).Error("Failed to watch /dev, skip inotify ")
			skipInotify = true
		}
	}

	// Have ESX attach the disk
	dev, err := d.ops.Attach(name, nil)
	if err != nil {
		return mountpoint, err
	}

	if d.useMockEsx {
		return mountpoint, fs.Mount(mountpoint, fstype, string(dev[:]), false)
	}

	device, err := fs.GetDevicePath(dev)
	if err != nil {
		return mountpoint, err
	}

	if skipInotify {
		time.Sleep(sleepBeforeMount)
		return mountpoint, fs.Mount(mountpoint, fstype, device, false)
	}
loop:
	for {
		select {
		case ev := <-watcher.Event:
			log.Debug("event: ", ev)
			if ev.Name == device {
				// Log when the device is discovered
				log.WithFields(
					log.Fields{"name": name, "event": ev},
				).Info("Attach complete ")
				break loop
			}
		case err := <-watcher.Error:
			log.WithFields(
				log.Fields{"name": name, "device": device, "error": err},
			).Error("Hit error during watch ")
			break loop
		case <-time.After(devWaitTimeout):
			log.WithFields(
				log.Fields{"name": name, "timeout": devWaitTimeout, "device": device},
			).Warning("Reached timeout while waiting for device, trying to mount anyways ")
			break loop
		}
	}

	return mountpoint, fs.Mount(mountpoint, fstype, device, isReadOnly)
}