Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var CreateBatchCmd = &cli.Command{ Name: "create-batch", Usage: "Create the cross-product of schedules for multiple preparations and providers", Description: `Create all schedules for preparations x providers x deal types. Examples: # Cold DDO copies to 2 providers singularity deal schedule create-batch \ --group dataset-a-cold \ --preparation prep-a --preparation prep-b \ --provider f01000 --provider f02000 \ --deal-type ddo # Warm + cold to 1 provider singularity deal schedule create-batch \ --group dataset-a-warm \ --preparation prep-a \ --provider f03000 \ --deal-type ddo --deal-type pdp `, Flags: append([]cli.Flag{ &cli.StringSliceFlag{ Name: "preparation", Usage: "Preparation IDs or names to include. Repeat this flag.", Required: true, }, &cli.StringSliceFlag{ Name: "provider", Usage: "Storage provider IDs to include. Repeat this flag.", Required: true, }, &cli.StringSliceFlag{ Name: "deal-type", Usage: "Deal types to create schedules for: market, pdp, or ddo. Repeat for multiple types.", Value: cli.NewStringSlice(string(model.DealTypeMarket)), }, }, scheduleCreateFlags(false)...), Action: func(c *cli.Context) error { if c.String("group") == "" { return errors.New("group label is required for create-batch") } preparations := c.StringSlice("preparation") if len(preparations) == 0 { return errors.New("at least one preparation is required") } providers := c.StringSlice("provider") if len(providers) == 0 { return errors.New("at least one provider is required") } dealTypes, err := parseDealTypes(c.StringSlice("deal-type")) if err != nil { return err } db, closer, err := database.OpenFromCLI(c) if err != nil { return errors.WithStack(err) } defer closer.Close() allowedPieceCIDs, err := allowedPieceCIDsFromContext(c) if err != nil { return errors.WithStack(err) } lotusClient := util.NewLotusClient(c.String("lotus-api"), c.String("lotus-token")) created := make([]model.Schedule, 0, len(preparations)*len(dealTypes)*len(providers)) for _, preparation := range preparations { for _, dealType := range dealTypes { for _, provider := range providers { request := createRequest(c, preparation, provider, string(dealType), allowedPieceCIDs) schedule, err := handlerschedule.Default.CreateHandler(c.Context, db, lotusClient, request) if err != nil { return errors.Wrapf(err, "failed to create schedule for preparation %q, provider %q, deal type %q", preparation, provider, dealType) } created = append(created, *schedule) } } } cliutil.Print(c, created) return nil }, }
View Source
var CreateCmd = &cli.Command{ Name: "create", Usage: "Create a schedule to send out deals to a storage provider", Description: `CRON pattern '--schedule-cron': The CRON pattern can either be a descriptor or a standard CRON pattern with optional second field Standard CRON: ┌───────────── minute (0 - 59) │ ┌───────────── hour (0 - 23) │ │ ┌───────────── day of the month (1 - 31) │ │ │ ┌───────────── month (1 - 12) │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday) │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ * * * * * Optional Second field: ┌───────────── second (0 - 59) │ ┌───────────── minute (0 - 59) │ │ ┌───────────── hour (0 - 23) │ │ │ ┌───────────── day of the month (1 - 31) │ │ │ │ ┌───────────── month (1 - 12) │ │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday) │ │ │ │ │ │ │ │ │ │ │ │ * * * * * * Descriptor: @yearly, @annually - Equivalent to 0 0 1 1 * @monthly - Equivalent to 0 0 1 * * @weekly - Equivalent to 0 0 * * 0 @daily, @midnight - Equivalent to 0 0 * * * @hourly - Equivalent to 0 * * * *`, Flags: append(scheduleTargetFlags(), scheduleCreateFlags(true)...), Action: func(c *cli.Context) error { db, closer, err := database.OpenFromCLI(c) if err != nil { return errors.WithStack(err) } defer closer.Close() allowedPieceCIDs, err := allowedPieceCIDsFromContext(c) if err != nil { return errors.WithStack(err) } request := createRequest(c, c.String("preparation"), c.String("provider"), c.String("deal-type"), allowedPieceCIDs) lotusClient := util.NewLotusClient(c.String("lotus-api"), c.String("lotus-token")) schedule, err := handlerschedule.Default.CreateHandler(c.Context, db, lotusClient, request) if err != nil { return errors.WithStack(err) } cliutil.Print(c, schedule) return nil }, }
View Source
var ListCmd = &cli.Command{ Name: "list", Usage: "List all deal making schedules", Flags: []cli.Flag{ &cli.StringFlag{ Name: "group", Category: "Filtering", Usage: "Filter schedules by group label", }, }, Action: func(c *cli.Context) error { db, closer, err := database.OpenFromCLI(c) if err != nil { return errors.WithStack(err) } defer closer.Close() schedules, err := schedule.Default.ListHandler(c.Context, db, schedule.ListRequest{ Group: c.String("group"), }) if err != nil { return errors.WithStack(err) } cliutil.Print(c, schedules) return nil }, }
View Source
var PauseCmd = &cli.Command{ Name: "pause", Usage: "Pause a specific schedule", Before: cliutil.CheckNArgs, ArgsUsage: "<schedule_id>", Action: func(c *cli.Context) error { db, closer, err := database.OpenFromCLI(c) if err != nil { return errors.WithStack(err) } defer closer.Close() scheduleID, err := strconv.ParseUint(c.Args().Get(0), 10, 32) if err != nil { return errors.Wrapf(err, "failed to parse schedule ID %s", c.Args().Get(0)) } schedule, err := schedule.Default.PauseHandler(c.Context, db, uint32(scheduleID)) if err != nil { return errors.WithStack(err) } cliutil.Print(c, schedule) return nil }, }
View Source
var RemoveCmd = &cli.Command{ Name: "remove", Usage: "Remove a paused or completed schedule", Before: cliutil.CheckNArgs, ArgsUsage: "<schedule_id>", Description: "Note: all deals made by this schedule will remain for tracking purpose.", Action: func(c *cli.Context) error { db, closer, err := database.OpenFromCLI(c) if err != nil { return errors.WithStack(err) } defer closer.Close() scheduleID, err := strconv.ParseUint(c.Args().Get(0), 10, 32) if err != nil { return errors.Wrapf(err, "failed to parse schedule ID %s", c.Args().Get(0)) } err = schedule.Default.RemoveHandler(c.Context, db, uint32(scheduleID)) return errors.WithStack(err) }, }
View Source
var ResumeCmd = &cli.Command{ Name: "resume", Usage: "Resume a specific schedule", Before: cliutil.CheckNArgs, ArgsUsage: "<schedule_id>", Action: func(c *cli.Context) error { db, closer, err := database.OpenFromCLI(c) if err != nil { return errors.WithStack(err) } defer closer.Close() scheduleID, err := strconv.ParseUint(c.Args().Get(0), 10, 32) if err != nil { return errors.Wrapf(err, "failed to parse schedule ID %s", c.Args().Get(0)) } schedule, err := schedule.Default.ResumeHandler(c.Context, db, uint32(scheduleID)) if err != nil { return errors.WithStack(err) } cliutil.Print(c, schedule) return nil }, }
View Source
var UpdateCmd = &cli.Command{ Name: "update", ArgsUsage: "<schedule_id>", Before: cliutil.CheckNArgs, Usage: "Update an existing schedule", Description: `CRON pattern '--schedule-cron': The CRON pattern can either be a descriptor or a standard CRON pattern with optional second field Standard CRON: ┌───────────── minute (0 - 59) │ ┌───────────── hour (0 - 23) │ │ ┌───────────── day of the month (1 - 31) │ │ │ ┌───────────── month (1 - 12) │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday) │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ * * * * * Optional Second field: ┌───────────── second (0 - 59) │ ┌───────────── minute (0 - 59) │ │ ┌───────────── hour (0 - 23) │ │ │ ┌───────────── day of the month (1 - 31) │ │ │ │ ┌───────────── month (1 - 12) │ │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday) │ │ │ │ │ │ │ │ │ │ │ │ * * * * * * Descriptor: @yearly, @annually - Equivalent to 0 0 1 1 * @monthly - Equivalent to 0 0 1 * * @weekly - Equivalent to 0 0 * * 0 @daily, @midnight - Equivalent to 0 0 * * * @hourly - Equivalent to 0 * * * *`, Flags: []cli.Flag{ &cli.StringSliceFlag{ Name: "http-header", Category: "Boost Only", Aliases: []string{"H"}, Usage: "HTTP headers to be passed with the request (i.e. key=value). This will replace the existing header values. To remove a header, use --http-header \"key=\"\". To remove all headers, use --http-header \"\"", }, &cli.StringFlag{ Name: "url-template", Category: "Boost Only", Aliases: []string{"u"}, Usage: "URL template with PIECE_CID placeholder for boost to fetch the CAR file, i.e. http://127.0.0.1/piece/{PIECE_CID}.car", Value: "", }, &cli.Float64Flag{ Name: "price-per-gb-epoch", Category: "Deal Proposal", Usage: "Price in FIL per GiB per epoch", Value: 0, }, &cli.Float64Flag{ Name: "price-per-gb", Category: "Deal Proposal", Usage: "Price in FIL per GiB", Value: 0, }, &cli.Float64Flag{ Name: "price-per-deal", Category: "Deal Proposal", Usage: "Price in FIL per deal", Value: 0, }, &cli.BoolFlag{ Name: "verified", Category: "Deal Proposal", Usage: "Whether to propose deals as verified", Value: true, }, &cli.StringFlag{ Name: "deal-type", Category: "Deal Proposal", Usage: "Deal type: market (legacy f05), pdp (f41), or ddo (DDO allocations)", }, &cli.StringFlag{ Name: "group", Category: "Tracking", Usage: "Group label for related schedules", }, &cli.BoolFlag{ Name: "ipni", Category: "Boost Only", Usage: "Whether to announce the deal to IPNI", Value: true, }, &cli.BoolFlag{ Name: "force", Category: "Restrictions", Usage: "Force to send out deals regardless of replication restriction", }, &cli.BoolFlag{ Name: "keep-unsealed", Category: "Deal Proposal", Usage: "Whether to keep unsealed copy", Value: true, }, &cli.StringFlag{ Name: "schedule-cron", Category: "Scheduling", Aliases: []string{"cron"}, Usage: "Cron schedule to send out batch deals", }, &cli.StringFlag{ Name: "start-delay", Category: "Deal Proposal", Aliases: []string{"s"}, Usage: "Deal start delay in epoch or in duration format, i.e. 1000, 72h", }, &cli.StringFlag{ Name: "duration", Category: "Deal Proposal", Aliases: []string{"d"}, Usage: "Duration in epoch or in duration format, i.e. 1500000, 2400h", }, &cli.IntFlag{ Name: "schedule-deal-number", Category: "Scheduling", Aliases: []string{"number"}, Usage: "Max deal number per triggered schedule, i.e. 30", }, &cli.IntFlag{ Name: "total-deal-number", Category: "Restrictions", Aliases: []string{"total-number"}, Usage: "Max total deal number for this request, i.e. 1000", }, &cli.StringFlag{ Name: "schedule-deal-size", Category: "Scheduling", Aliases: []string{"size"}, Usage: "Max deal sizes per triggered schedule, i.e. 500GiB", }, &cli.StringFlag{ Name: "total-deal-size", Category: "Restrictions", Aliases: []string{"total-size"}, Usage: "Max total deal sizes for this request, i.e. 100TiB", }, &cli.StringFlag{ Name: "notes", Category: "Tracking", Aliases: []string{"n"}, Usage: "Any notes or tag to store along with the request, for tracking purpose", Value: "", }, &cli.StringFlag{ Name: "max-pending-deal-size", Category: "Restrictions", Aliases: []string{"pending-size"}, Usage: "Max pending deal sizes overall for this request, i.e. 100TiB", }, &cli.IntFlag{ Name: "max-pending-deal-number", Category: "Restrictions", Aliases: []string{"pending-number"}, Usage: "Max pending deal number overall for this request, i.e. 1000", }, &cli.StringSliceFlag{ Name: "allowed-piece-cid", Category: "Restrictions", Aliases: []string{"piece-cid"}, Usage: "List of allowed piece CIDs in this schedule. Append only.", }, &cli.StringSliceFlag{ Name: "allowed-piece-cid-file", Category: "Restrictions", Aliases: []string{"piece-cid-file"}, Usage: "List of files that contains a list of piece CIDs to allow. Append only.", }, }, Action: func(c *cli.Context) error { db, closer, err := database.OpenFromCLI(c) if err != nil { return errors.WithStack(err) } defer closer.Close() allowedPieceCIDs := c.StringSlice("allowed-piece-cid") for _, f := range c.StringSlice("allowed-piece-cid-file") { cidsFromFile, err := readCIDsFromFile(f) if err != nil { return errors.WithStack(err) } allowedPieceCIDs = append(allowedPieceCIDs, cidsFromFile...) } request := schedule.UpdateRequest{ HTTPHeaders: c.StringSlice("http-header"), AllowedPieceCIDs: allowedPieceCIDs, } if c.IsSet("url-template") { request.URLTemplate = ptr.Of(c.String("url-template")) } if c.IsSet("price-per-gb-epoch") { request.PricePerGBEpoch = ptr.Of(c.Float64("price-per-gb-epoch")) } if c.IsSet("price-per-gb") { request.PricePerGB = ptr.Of(c.Float64("price-per-gb")) } if c.IsSet("price-per-deal") { request.PricePerDeal = ptr.Of(c.Float64("price-per-deal")) } if c.IsSet("verified") { request.Verified = ptr.Of(c.Bool("verified")) } if c.IsSet("deal-type") { request.DealType = ptr.Of(c.String("deal-type")) } if c.IsSet("group") { request.Group = ptr.Of(c.String("group")) } if c.IsSet("ipni") { request.IPNI = ptr.Of(c.Bool("ipni")) } if c.IsSet("keep-unsealed") { request.KeepUnsealed = ptr.Of(c.Bool("keep-unsealed")) } if c.IsSet("schedule-cron") { request.ScheduleCron = ptr.Of(c.String("schedule-cron")) } if c.IsSet("start-delay") { request.StartDelay = ptr.Of(c.String("start-delay")) } if c.IsSet("duration") { request.Duration = ptr.Of(c.String("duration")) } if c.IsSet("schedule-deal-number") { request.ScheduleDealNumber = ptr.Of(c.Int("schedule-deal-number")) } if c.IsSet("total-deal-number") { request.TotalDealNumber = ptr.Of(c.Int("total-deal-number")) } if c.IsSet("schedule-deal-size") { request.ScheduleDealSize = ptr.Of(c.String("schedule-deal-size")) } if c.IsSet("total-deal-size") { request.TotalDealSize = ptr.Of(c.String("total-deal-size")) } if c.IsSet("notes") { request.Notes = ptr.Of(c.String("notes")) } if c.IsSet("max-pending-deal-size") { request.MaxPendingDealSize = ptr.Of(c.String("max-pending-deal-size")) } if c.IsSet("max-pending-deal-number") { request.MaxPendingDealNumber = ptr.Of(c.Int("max-pending-deal-number")) } if c.IsSet("force") { request.Force = ptr.Of(c.Bool("force")) } id, err := strconv.ParseUint(c.Args().Get(0), 10, 32) if err != nil { return errors.Newf("invalid schedule id %s", c.Args().Get(0)) } schedule, err := schedule.Default.UpdateHandler(c.Context, db, uint32(id), request) if err != nil { return errors.WithStack(err) } cliutil.Print(c, schedule) return nil }, }
Functions ¶
This section is empty.
Types ¶
This section is empty.
Click to show internal directories.
Click to hide internal directories.