github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/client/allocrunner/network_hook.go (about)

     1  package allocrunner
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	hclog "github.com/hashicorp/go-hclog"
     8  	"github.com/hashicorp/nomad/nomad/structs"
     9  	"github.com/hashicorp/nomad/plugins/drivers"
    10  )
    11  
    12  type networkIsolationSetter interface {
    13  	SetNetworkIsolation(*drivers.NetworkIsolationSpec)
    14  }
    15  
    16  // allocNetworkIsolationSetter is a shim to allow the alloc network hook to
    17  // set the alloc network isolation configuration without full access
    18  // to the alloc runner
    19  type allocNetworkIsolationSetter struct {
    20  	ar *allocRunner
    21  }
    22  
    23  func (a *allocNetworkIsolationSetter) SetNetworkIsolation(n *drivers.NetworkIsolationSpec) {
    24  	for _, tr := range a.ar.tasks {
    25  		tr.SetNetworkIsolation(n)
    26  	}
    27  }
    28  
    29  type networkStatusSetter interface {
    30  	SetNetworkStatus(*structs.AllocNetworkStatus)
    31  }
    32  
    33  // networkHook is an alloc lifecycle hook that manages the network namespace
    34  // for an alloc
    35  type networkHook struct {
    36  	// isolationSetter is a callback to set the network isolation spec when after the
    37  	// network is created
    38  	isolationSetter networkIsolationSetter
    39  
    40  	// statusSetter is a callback to the alloc runner to set the network status once
    41  	// network setup is complete
    42  	networkStatusSetter networkStatusSetter
    43  
    44  	// manager is used when creating the network namespace. This defaults to
    45  	// bind mounting a network namespace descritor under /var/run/netns but
    46  	// can be created by a driver if nessicary
    47  	manager drivers.DriverNetworkManager
    48  
    49  	// alloc should only be read from
    50  	alloc *structs.Allocation
    51  
    52  	// spec described the network namespace and is syncronized by specLock
    53  	spec *drivers.NetworkIsolationSpec
    54  
    55  	// networkConfigurator configures the network interfaces, routes, etc once
    56  	// the alloc network has been created
    57  	networkConfigurator NetworkConfigurator
    58  
    59  	logger hclog.Logger
    60  }
    61  
    62  func newNetworkHook(logger hclog.Logger,
    63  	ns networkIsolationSetter,
    64  	alloc *structs.Allocation,
    65  	netManager drivers.DriverNetworkManager,
    66  	netConfigurator NetworkConfigurator,
    67  	networkStatusSetter networkStatusSetter) *networkHook {
    68  	return &networkHook{
    69  		isolationSetter:     ns,
    70  		networkStatusSetter: networkStatusSetter,
    71  		alloc:               alloc,
    72  		manager:             netManager,
    73  		networkConfigurator: netConfigurator,
    74  		logger:              logger,
    75  	}
    76  }
    77  
    78  func (h *networkHook) Name() string {
    79  	return "network"
    80  }
    81  
    82  func (h *networkHook) Prerun() error {
    83  	tg := h.alloc.Job.LookupTaskGroup(h.alloc.TaskGroup)
    84  	if len(tg.Networks) == 0 || tg.Networks[0].Mode == "host" || tg.Networks[0].Mode == "" {
    85  		return nil
    86  	}
    87  
    88  	if h.manager == nil || h.networkConfigurator == nil {
    89  		h.logger.Trace("shared network namespaces are not supported on this platform, skipping network hook")
    90  		return nil
    91  	}
    92  
    93  	spec, created, err := h.manager.CreateNetwork(h.alloc.ID)
    94  
    95  	if err != nil {
    96  		return fmt.Errorf("failed to create network for alloc: %v", err)
    97  	}
    98  
    99  	if spec != nil {
   100  		h.spec = spec
   101  		h.isolationSetter.SetNetworkIsolation(spec)
   102  	}
   103  
   104  	if created {
   105  		status, err := h.networkConfigurator.Setup(context.TODO(), h.alloc, spec)
   106  		if err != nil {
   107  			return fmt.Errorf("failed to configure networking for alloc: %v", err)
   108  		}
   109  
   110  		h.networkStatusSetter.SetNetworkStatus(status)
   111  	}
   112  	return nil
   113  }
   114  
   115  func (h *networkHook) Postrun() error {
   116  	if h.spec == nil {
   117  		return nil
   118  	}
   119  
   120  	if err := h.networkConfigurator.Teardown(context.TODO(), h.alloc, h.spec); err != nil {
   121  		h.logger.Error("failed to cleanup network for allocation, resources may have leaked", "alloc", h.alloc.ID, "error", err)
   122  	}
   123  	return h.manager.DestroyNetwork(h.alloc.ID, h.spec)
   124  }