mirror of
https://github.com/psviderski/uncloud.git
synced 2026-08-26 11:03:34 +00:00
refactor: 'service run' create missing volumes satisfying all placement constraints
This commit is contained in:
@@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
// VolumeScheduler determines what missing volumes should be created and where for a multi-service deployment.
|
||||
// It must satisfy the following constraints:
|
||||
// It satisfies the following constraints:
|
||||
// - Services that share a volume must be placed on the same machine where the volume is located.
|
||||
// If the volume is located on multiple machines, services can be placed on any of them.
|
||||
// - Services must respect their individual placement constraints.
|
||||
@@ -25,6 +25,7 @@ type VolumeScheduler struct {
|
||||
// volumeSpecs is a map of volume names to their specifications from the service specs in a canonical form.
|
||||
volumeSpecs map[string]api.VolumeSpec
|
||||
// volumeServices is a map of volume names to the list of service names that use the volume.
|
||||
// TODO: not all service spec may contain the service name, so use a slice of int indexes instead of names.
|
||||
volumeServices map[string][]string
|
||||
// existingVolumeMachines is a map of volume names to the set of machine IDs where those volumes are located.
|
||||
// Contains only volumes that are used by at least one service in serviceSpecs.
|
||||
|
||||
@@ -9,8 +9,10 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/volume"
|
||||
"github.com/psviderski/uncloud/internal/machine/api/pb"
|
||||
"github.com/psviderski/uncloud/pkg/api"
|
||||
"github.com/psviderski/uncloud/pkg/client/deploy/scheduler"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
@@ -39,6 +41,33 @@ func (cli *Client) RunService(ctx context.Context, spec api.ServiceSpec) (RunSer
|
||||
}
|
||||
}
|
||||
|
||||
// Create missing named Docker volumes for the service.
|
||||
if len(spec.MountedDockerVolumes()) > 0 {
|
||||
volumeScheduler, err := scheduler.NewVolumeSchedulerWithClient(ctx, cli, []api.ServiceSpec{spec})
|
||||
if err != nil {
|
||||
return resp, fmt.Errorf("init volume scheduler: %w", err)
|
||||
}
|
||||
|
||||
scheduledVolumes, err := volumeScheduler.Schedule()
|
||||
if err != nil {
|
||||
return resp, fmt.Errorf("schedule volumes: %w", err)
|
||||
}
|
||||
|
||||
// Create the missing volumes on the scheduled machines.
|
||||
for machineID, volumes := range scheduledVolumes {
|
||||
for _, v := range volumes {
|
||||
_, err = cli.CreateVolume(ctx, machineID, volume.CreateOptions{
|
||||
Name: v.Name,
|
||||
Driver: v.VolumeOptions.Driver.Name,
|
||||
DriverOpts: v.VolumeOptions.Driver.Options,
|
||||
})
|
||||
if err != nil {
|
||||
return resp, fmt.Errorf("create volume '%s': %w", v.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deployment := cli.NewDeployment(spec, nil)
|
||||
plan, err := deployment.Run(ctx)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user