Ejemplo n.º 1
0
// DeviceAttachTimeout gets the configured device attach timeout.
func DeviceAttachTimeout(config gofig.Config) time.Duration {
	return utils.DeviceAttachTimeout(
		config.GetString(types.ConfigDeviceAttachTimeout))
}
Ejemplo n.º 2
0
// Run runs the executor CLI.
func Run() {

	args := os.Args
	if len(args) < 3 {
		printUsageAndExit()
	}

	d, err := registry.NewStorageExecutor(args[1])
	if err != nil {
		fmt.Fprintf(os.Stderr, "error: %v\n", err)
		os.Exit(1)
	}

	driverName := strings.ToLower(d.Name())

	config, err := apiconfig.NewConfig()
	if err != nil {
		fmt.Fprintf(os.Stderr, "error: %v\n", err)
		os.Exit(1)
	}

	apiconfig.UpdateLogLevel(config)
	ctx := context.Background()

	if err := d.Init(ctx, config); err != nil {
		fmt.Fprintf(os.Stderr, "error: %v\n", err)
		os.Exit(1)
	}

	cmd := cmdRx.FindString(args[2])
	if cmd == "" {
		printUsageAndExit()
	}
	store := utils.NewStore()

	var (
		result   interface{}
		op       string
		exitCode int
	)

	if strings.EqualFold(cmd, apitypes.LSXCmdSupported) {
		op = "supported"
		if dws, ok := d.(apitypes.StorageExecutorWithSupported); ok {
			opResult, opErr := dws.Supported(ctx, store)
			if opErr != nil {
				err = opErr
			} else {
				result = opResult
			}
		} else {
			err = apitypes.ErrNotImplemented
		}
	} else if strings.EqualFold(cmd, apitypes.LSXCmdInstanceID) {
		op = "instance ID"
		opResult, opErr := d.InstanceID(ctx, store)
		if opErr != nil {
			err = opErr
		} else {
			opResult.Driver = driverName
			result = opResult
		}
	} else if strings.EqualFold(cmd, apitypes.LSXCmdNextDevice) {
		op = "next device"
		opResult, opErr := d.NextDevice(ctx, store)
		if opErr != nil && opErr != apitypes.ErrNotImplemented {
			err = opErr
		} else {
			result = opResult
		}
	} else if strings.EqualFold(cmd, apitypes.LSXCmdLocalDevices) {
		if len(args) < 4 {
			printUsageAndExit()
		}
		op = "local devices"
		opResult, opErr := d.LocalDevices(ctx, &apitypes.LocalDevicesOpts{
			ScanType: apitypes.ParseDeviceScanType(args[3]),
			Opts:     store,
		})
		opResult.Driver = driverName
		if opErr != nil {
			err = opErr
		} else {
			result = opResult
		}
	} else if strings.EqualFold(cmd, apitypes.LSXCmdWaitForDevice) {
		if len(args) < 5 {
			printUsageAndExit()
		}
		op = "wait"
		opts := &apitypes.WaitForDeviceOpts{
			LocalDevicesOpts: apitypes.LocalDevicesOpts{
				ScanType: apitypes.ParseDeviceScanType(args[3]),
				Opts:     store,
			},
			Token:   strings.ToLower(args[4]),
			Timeout: utils.DeviceAttachTimeout(args[5]),
		}

		ldl := func() (bool, *apitypes.LocalDevices, error) {
			ldm, err := d.LocalDevices(ctx, &opts.LocalDevicesOpts)
			if err != nil {
				return false, nil, err
			}
			for k := range ldm.DeviceMap {
				if strings.ToLower(k) == opts.Token {
					return true, ldm, nil
				}
			}
			return false, ldm, nil
		}

		var (
			found    bool
			opErr    error
			opResult *apitypes.LocalDevices
			timeoutC = time.After(opts.Timeout)
			tick     = time.Tick(500 * time.Millisecond)
		)

	TimeoutLoop:

		for {
			select {
			case <-timeoutC:
				exitCode = apitypes.LSXExitCodeTimedOut
				break TimeoutLoop
			case <-tick:
				if found, opResult, opErr = ldl(); found || opErr != nil {
					break TimeoutLoop
				}
			}
		}

		if opErr != nil {
			err = opErr
		} else {
			opResult.Driver = driverName
			result = opResult
		}
	}

	if err != nil {
		// if the function is not implemented then exit with
		// apitypes.LSXExitCodeNotImplemented to let callers
		// know that the function is unsupported on this system
		exitCode = 1
		if strings.EqualFold(err.Error(), apitypes.ErrNotImplemented.Error()) {
			exitCode = apitypes.LSXExitCodeNotImplemented
		}
		fmt.Fprintf(os.Stderr,
			"error: error getting %s: %v\n", op, err)
		os.Exit(exitCode)
	}

	switch tr := result.(type) {
	case bool:
		fmt.Fprintf(os.Stdout, "%v", result)
	case string:
		fmt.Fprintln(os.Stdout, result)
	case encoding.TextMarshaler:
		buf, err := tr.MarshalText()
		if err != nil {
			fmt.Fprintf(os.Stderr, "error: error encoding %s: %v\n", op, err)
			os.Exit(1)
		}
		os.Stdout.Write(buf)
	default:
		buf, err := json.Marshal(result)
		if err != nil {
			fmt.Fprintf(os.Stderr, "error: error encoding %s: %v\n", op, err)
			os.Exit(1)
		}
		if isNullBuf(buf) {
			os.Stdout.Write(emptyJSONBuff)
		} else {
			os.Stdout.Write(buf)
		}
	}

	os.Exit(exitCode)
}