X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/ca2d946973b6ae25dd594ddecec54e02b83bc44e..HEAD:/lib/cloud/interfaces.go diff --git a/lib/cloud/interfaces.go b/lib/cloud/interfaces.go index 792e737a91..a2aa9e1432 100644 --- a/lib/cloud/interfaces.go +++ b/lib/cloud/interfaces.go @@ -10,7 +10,8 @@ import ( "io" "time" - "git.curoverse.com/arvados.git/sdk/go/arvados" + "git.arvados.org/arvados.git/sdk/go/arvados" + "github.com/prometheus/client_golang/prometheus" "github.com/sirupsen/logrus" "golang.org/x/crypto/ssh" ) @@ -36,6 +37,21 @@ type QuotaError interface { error } +// A CapacityError should be returned by an InstanceSet's Create +// method when the cloud service indicates it has insufficient +// capacity to create new instances -- i.e., we shouldn't retry right +// away. +type CapacityError interface { + // If true, wait before trying to create more instances. + IsCapacityError() bool + // If true, the condition is specific to the requested + // instance types. Wait before trying to create more + // instances of that same type. + IsInstanceTypeSpecific() bool + error +} + +type SharedResourceTags map[string]string type InstanceSetID string type InstanceTags map[string]string type InstanceID string @@ -101,6 +117,12 @@ type Instance interface { // Replace tags with the given tags SetTags(InstanceTags) error + // Get recent price history, if available. The InstanceType is + // supplied as an argument so the driver implementation can + // account for AddedScratch cost without requesting the volume + // attachment information from the provider's API. + PriceHistory(arvados.InstanceType) []InstancePrice + // Shut down the node Destroy() error } @@ -140,11 +162,20 @@ type InstanceSet interface { Stop() } +type InstancePrice struct { + StartTime time.Time + Price float64 +} + type InitCommand string // A Driver returns an InstanceSet that uses the given InstanceSetID // and driver-dependent configuration parameters. // +// If the driver creates cloud resources that aren't attached to a +// single VM instance (like SSH key pairs on AWS) and support tagging, +// they should be tagged with the provided SharedResourceTags. +// // The supplied id will be of the form "zzzzz-zzzzz-zzzzzzzzzzzzzzz" // where each z can be any alphanum. The returned InstanceSet must use // this id to tag long-lived cloud resources that it creates, and must @@ -154,13 +185,17 @@ type InitCommand string // other mechanism. The tags must be visible to another instance of // the same driver running on a different host. // -// The returned InstanceSet must ignore existing resources that are -// visible but not tagged with the given id, except that it should log -// a summary of such resources -- only once -- when it starts -// up. Thus, two identically configured InstanceSets running on -// different hosts with different ids should log about the existence -// of each other's resources at startup, but will not interfere with -// each other. +// The returned InstanceSet must not modify or delete cloud resources +// unless they are tagged with the given InstanceSetID or the caller +// (dispatcher) calls Destroy() on them. It may log a summary of +// untagged resources once at startup, though. Thus, two identically +// configured InstanceSets running on different hosts with different +// ids should log about the existence of each other's resources at +// startup, but will not interfere with each other. +// +// The dispatcher always passes the InstanceSetID as a tag when +// calling Create() and Instances(), so the driver does not need to +// tag/filter VMs by InstanceSetID itself. // // Example: // @@ -171,7 +206,7 @@ type InitCommand string // // type exampleDriver struct {} // -// func (*exampleDriver) InstanceSet(config json.RawMessage, id InstanceSetID) (InstanceSet, error) { +// func (*exampleDriver) InstanceSet(config json.RawMessage, id cloud.InstanceSetID, tags cloud.SharedResourceTags, logger logrus.FieldLogger, reg *prometheus.Registry) (cloud.InstanceSet, error) { // var is exampleInstanceSet // if err := json.Unmarshal(config, &is); err != nil { // return nil, err @@ -179,20 +214,18 @@ type InitCommand string // is.ownID = id // return &is, nil // } -// -// var _ = registerCloudDriver("example", &exampleDriver{}) type Driver interface { - InstanceSet(config json.RawMessage, id InstanceSetID, logger logrus.FieldLogger) (InstanceSet, error) + InstanceSet(config json.RawMessage, id InstanceSetID, tags SharedResourceTags, logger logrus.FieldLogger, reg *prometheus.Registry) (InstanceSet, error) } // DriverFunc makes a Driver using the provided function as its // InstanceSet method. This is similar to http.HandlerFunc. -func DriverFunc(fn func(config json.RawMessage, id InstanceSetID, logger logrus.FieldLogger) (InstanceSet, error)) Driver { +func DriverFunc(fn func(config json.RawMessage, id InstanceSetID, tags SharedResourceTags, logger logrus.FieldLogger, reg *prometheus.Registry) (InstanceSet, error)) Driver { return driverFunc(fn) } -type driverFunc func(config json.RawMessage, id InstanceSetID, logger logrus.FieldLogger) (InstanceSet, error) +type driverFunc func(config json.RawMessage, id InstanceSetID, tags SharedResourceTags, logger logrus.FieldLogger, reg *prometheus.Registry) (InstanceSet, error) -func (df driverFunc) InstanceSet(config json.RawMessage, id InstanceSetID, logger logrus.FieldLogger) (InstanceSet, error) { - return df(config, id, logger) +func (df driverFunc) InstanceSet(config json.RawMessage, id InstanceSetID, tags SharedResourceTags, logger logrus.FieldLogger, reg *prometheus.Registry) (InstanceSet, error) { + return df(config, id, tags, logger, reg) }