func (c *client) NextDevice( ctx types.Context, opts types.Store) (string, error) { if c.isController() { return "", utils.NewUnsupportedForClientTypeError( c.clientType, "NextDevice") } if supported, _ := c.Supported(ctx, opts); !supported { return "", errExecutorNotSupported } ctx = context.RequireTX(ctx.Join(c.ctx)) serviceName, ok := context.ServiceName(ctx) if !ok { return "", goof.New("missing service name") } si, err := c.getServiceInfo(serviceName) if err != nil { return "", err } driverName := si.Driver.Name out, err := c.runExecutor(ctx, driverName, types.LSXCmdNextDevice) if err != nil { return "", err } ctx.Debug("xli nextdevice success") return gotil.Trim(string(out)), nil }
func (c *client) requireCtx(ctx types.Context) types.Context { if ctx == nil { ctx = c.ctx } else { ctx = ctx.Join(c.ctx) } return context.RequireTX(ctx) }
func (c *client) Supported( ctx types.Context, opts types.Store) (bool, error) { if c.isController() { return false, utils.NewUnsupportedForClientTypeError( c.clientType, "Supported") } ctx = context.RequireTX(ctx.Join(c.ctx)) serviceName, ok := context.ServiceName(ctx) if !ok { return false, goof.New("missing service name") } si, err := c.getServiceInfo(serviceName) if err != nil { return false, err } driverName := strings.ToLower(si.Driver.Name) // check to see if the driver's executor is supported on this host if ok := c.supportedCache.IsSet(driverName); ok { return c.supportedCache.GetBool(driverName), nil } out, err := c.runExecutor(ctx, driverName, types.LSXCmdSupported) if err != nil { if err == types.ErrNotImplemented { ctx.WithField("serviceDriver", driverName).Warn( "supported cmd not implemented") c.supportedCache.Set(driverName, true) ctx.WithField("supported", true).Debug("cached supported flag") return true, nil } return false, err } if len(out) == 0 { return false, nil } out = bytes.TrimSpace(out) b, err := strconv.ParseBool(string(out)) if err != nil { return false, err } c.supportedCache.Set(driverName, b) ctx.WithField("supported", b).Debug("cached supported flag") return b, nil }
func (c *client) WaitForDevice( ctx types.Context, opts *types.WaitForDeviceOpts) (bool, *types.LocalDevices, error) { if c.isController() { return false, nil, utils.NewUnsupportedForClientTypeError( c.clientType, "WaitForDevice") } if supported, _ := c.Supported(ctx, opts.Opts); !supported { return false, nil, errExecutorNotSupported } ctx = context.RequireTX(ctx.Join(c.ctx)) serviceName, ok := context.ServiceName(ctx) if !ok { return false, nil, goof.New("missing service name") } si, err := c.getServiceInfo(serviceName) if err != nil { return false, nil, err } driverName := si.Driver.Name out, err := c.runExecutor( ctx, driverName, types.LSXCmdWaitForDevice, opts.ScanType.String(), opts.Token, opts.Timeout.String()) if err != types.ErrTimedOut { return false, nil, err } matched := err == nil ld, err := unmarshalLocalDevices(ctx, out) if err != nil { return false, nil, err } ctx.Debug("xli waitfordevice success") return matched, ld, nil }
func (c *client) LocalDevices( ctx types.Context, opts *types.LocalDevicesOpts) (*types.LocalDevices, error) { if c.isController() { return nil, utils.NewUnsupportedForClientTypeError( c.clientType, "LocalDevices") } if supported, _ := c.Supported(ctx, opts.Opts); !supported { return nil, errExecutorNotSupported } ctx = context.RequireTX(ctx.Join(c.ctx)) serviceName, ok := context.ServiceName(ctx) if !ok { return nil, goof.New("missing service name") } si, err := c.getServiceInfo(serviceName) if err != nil { return nil, err } driverName := si.Driver.Name out, err := c.runExecutor( ctx, driverName, types.LSXCmdLocalDevices, opts.ScanType.String()) if err != nil { return nil, err } ld, err := unmarshalLocalDevices(ctx, out) if err != nil { return nil, err } ctx.Debug("xli localdevices success") return ld, nil }
func (c *client) httpDo( ctx types.Context, method, path string, payload, reply interface{}) (*http.Response, error) { reqBody, err := encPayload(payload) if err != nil { return nil, err } url := fmt.Sprintf("http://%s%s", c.host, path) req, err := http.NewRequest(method, url, reqBody) if err != nil { return nil, err } ctx = context.RequireTX(ctx) tx := context.MustTransaction(ctx) ctx = ctx.WithValue(transactionHeaderKey, tx) if iid, ok := context.InstanceID(ctx); ok { ctx = ctx.WithValue(instanceIDHeaderKey, iid) } else if iidMap, ok := ctx.Value( context.AllInstanceIDsKey).(types.InstanceIDMap); ok { if len(iidMap) > 0 { var iids []fmt.Stringer for _, iid := range iidMap { iids = append(iids, iid) } ctx = ctx.WithValue(instanceIDHeaderKey, iids) } } if lds, ok := context.LocalDevices(ctx); ok { ctx = ctx.WithValue(localDevicesHeaderKey, lds) } else if ldsMap, ok := ctx.Value( context.AllLocalDevicesKey).(types.LocalDevicesMap); ok { if len(ldsMap) > 0 { var ldsess []fmt.Stringer for _, lds := range ldsMap { ldsess = append(ldsess, lds) } ctx = ctx.WithValue(localDevicesHeaderKey, ldsess) } } for key := range context.CustomHeaderKeys() { var headerName string switch tk := key.(type) { case string: headerName = tk case fmt.Stringer: headerName = tk.String() default: headerName = fmt.Sprintf("%v", key) } if headerName == "" { continue } val := ctx.Value(key) switch tv := val.(type) { case string: req.Header.Add(headerName, tv) case fmt.Stringer: req.Header.Add(headerName, tv.String()) case []string: for _, sv := range tv { req.Header.Add(headerName, sv) } case []fmt.Stringer: for _, sv := range tv { req.Header.Add(headerName, sv.String()) } default: if val != nil { req.Header.Add(headerName, fmt.Sprintf("%v", val)) } } } c.logRequest(req) res, err := ctxhttp.Do(ctx, &c.Client, req) if err != nil { return nil, err } defer c.setServerName(res) c.logResponse(res) if res.StatusCode > 299 { httpErr, err := goof.DecodeHTTPError(res.Body) if err != nil { return res, goof.WithField("status", res.StatusCode, "http error") } return res, httpErr } if req.Method != http.MethodHead && reply != nil { if err := decRes(res.Body, reply); err != nil { return nil, err } } return res, nil }
func (c *client) InstanceID( ctx types.Context, opts types.Store) (*types.InstanceID, error) { if c.isController() { return nil, utils.NewUnsupportedForClientTypeError( c.clientType, "InstanceID") } if supported, _ := c.Supported(ctx, opts); !supported { return nil, errExecutorNotSupported } ctx = context.RequireTX(ctx.Join(c.ctx)) serviceName, ok := context.ServiceName(ctx) if !ok { return nil, goof.New("missing service name") } si, err := c.getServiceInfo(serviceName) if err != nil { return nil, err } driverName := strings.ToLower(si.Driver.Name) // check to see if the driver's instance ID is cached if iid := c.instanceIDCache.GetInstanceID(driverName); iid != nil { return iid, nil } out, err := c.runExecutor(ctx, driverName, types.LSXCmdInstanceID) if err != nil { return nil, err } iid := &types.InstanceID{} if err := iid.UnmarshalText(out); err != nil { return nil, err } ctx = ctx.WithValue(context.InstanceIDKey, iid) if iid.HasMetadata() { ctx.Debug("sending instanceID in API.InstanceInspect call") instance, err := c.InstanceInspect(ctx, serviceName) if err != nil { return nil, err } ctx.Debug("received instanceID from API.InstanceInspect call") iid.ID = instance.InstanceID.ID iid.Fields = instance.InstanceID.Fields iid.DeleteMetadata() } c.instanceIDCache.Set(driverName, iid) ctx.Debug("cached instanceID") ctx.Debug("xli instanceID success") return iid, nil }