mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
f2614f2107
Signed-off-by: Alexander Morozov <lk4d4@docker.com>
124 lines
3.6 KiB
Go
124 lines
3.6 KiB
Go
package resourceapi
|
|
|
|
import (
|
|
"errors"
|
|
"time"
|
|
|
|
"github.com/docker/swarmkit/api"
|
|
"github.com/docker/swarmkit/ca"
|
|
"github.com/docker/swarmkit/identity"
|
|
"github.com/docker/swarmkit/manager/state/store"
|
|
"github.com/docker/swarmkit/protobuf/ptypes"
|
|
"golang.org/x/net/context"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/codes"
|
|
)
|
|
|
|
var (
|
|
errInvalidArgument = errors.New("invalid argument")
|
|
)
|
|
|
|
// ResourceAllocator handles resource allocation of cluster entities.
|
|
type ResourceAllocator struct {
|
|
store *store.MemoryStore
|
|
}
|
|
|
|
// New returns an instance of the allocator
|
|
func New(store *store.MemoryStore) *ResourceAllocator {
|
|
return &ResourceAllocator{store: store}
|
|
}
|
|
|
|
// AttachNetwork allows the node to request the resources
|
|
// allocation needed for a network attachment on the specific node.
|
|
// - Returns `InvalidArgument` if the Spec is malformed.
|
|
// - Returns `NotFound` if the Network is not found.
|
|
// - Returns `PermissionDenied` if the Network is not manually attachable.
|
|
// - Returns an error if the creation fails.
|
|
func (ra *ResourceAllocator) AttachNetwork(ctx context.Context, request *api.AttachNetworkRequest) (*api.AttachNetworkResponse, error) {
|
|
nodeInfo, err := ca.RemoteNode(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var network *api.Network
|
|
ra.store.View(func(tx store.ReadTx) {
|
|
network = store.GetNetwork(tx, request.Config.Target)
|
|
if network == nil {
|
|
if networks, err := store.FindNetworks(tx, store.ByName(request.Config.Target)); err == nil && len(networks) == 1 {
|
|
network = networks[0]
|
|
}
|
|
}
|
|
})
|
|
if network == nil {
|
|
return nil, grpc.Errorf(codes.NotFound, "network %s not found", request.Config.Target)
|
|
}
|
|
|
|
if !network.Spec.Attachable {
|
|
return nil, grpc.Errorf(codes.PermissionDenied, "network %s not manually attachable", request.Config.Target)
|
|
}
|
|
|
|
t := &api.Task{
|
|
ID: identity.NewID(),
|
|
NodeID: nodeInfo.NodeID,
|
|
Spec: api.TaskSpec{
|
|
Runtime: &api.TaskSpec_Attachment{
|
|
Attachment: &api.NetworkAttachmentSpec{
|
|
ContainerID: request.ContainerID,
|
|
},
|
|
},
|
|
Networks: []*api.NetworkAttachmentConfig{
|
|
{
|
|
Target: network.ID,
|
|
Addresses: request.Config.Addresses,
|
|
},
|
|
},
|
|
},
|
|
Status: api.TaskStatus{
|
|
State: api.TaskStateNew,
|
|
Timestamp: ptypes.MustTimestampProto(time.Now()),
|
|
Message: "created",
|
|
},
|
|
DesiredState: api.TaskStateRunning,
|
|
// TODO: Add Network attachment.
|
|
}
|
|
|
|
if err := ra.store.Update(func(tx store.Tx) error {
|
|
return store.CreateTask(tx, t)
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &api.AttachNetworkResponse{AttachmentID: t.ID}, nil
|
|
}
|
|
|
|
// DetachNetwork allows the node to request the release of
|
|
// the resources associated to the network attachment.
|
|
// - Returns `InvalidArgument` if attachment ID is not provided.
|
|
// - Returns `NotFound` if the attachment is not found.
|
|
// - Returns an error if the deletion fails.
|
|
func (ra *ResourceAllocator) DetachNetwork(ctx context.Context, request *api.DetachNetworkRequest) (*api.DetachNetworkResponse, error) {
|
|
if request.AttachmentID == "" {
|
|
return nil, grpc.Errorf(codes.InvalidArgument, errInvalidArgument.Error())
|
|
}
|
|
|
|
nodeInfo, err := ca.RemoteNode(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := ra.store.Update(func(tx store.Tx) error {
|
|
t := store.GetTask(tx, request.AttachmentID)
|
|
if t == nil {
|
|
return grpc.Errorf(codes.NotFound, "attachment %s not found", request.AttachmentID)
|
|
}
|
|
if t.NodeID != nodeInfo.NodeID {
|
|
return grpc.Errorf(codes.PermissionDenied, "attachment %s doesn't belong to this node", request.AttachmentID)
|
|
}
|
|
|
|
return store.DeleteTask(tx, request.AttachmentID)
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &api.DetachNetworkResponse{}, nil
|
|
}
|