github.com/iqoqo/nomad@v0.11.3-0.20200911112621-d7021c74d101/client/allocrunner/network_manager_linux.go (about)

     1  package allocrunner
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	hclog "github.com/hashicorp/go-hclog"
     8  	clientconfig "github.com/hashicorp/nomad/client/config"
     9  	"github.com/hashicorp/nomad/client/lib/nsutil"
    10  	"github.com/hashicorp/nomad/client/pluginmanager/drivermanager"
    11  	"github.com/hashicorp/nomad/nomad/structs"
    12  	"github.com/hashicorp/nomad/plugins/drivers"
    13  )
    14  
    15  func newNetworkManager(alloc *structs.Allocation, driverManager drivermanager.Manager) (nm drivers.DriverNetworkManager, err error) {
    16  	// The defaultNetworkManager is used if a driver doesn't need to create the network
    17  	nm = &defaultNetworkManager{}
    18  	tg := alloc.Job.LookupTaskGroup(alloc.TaskGroup)
    19  
    20  	// default netmode to host, this can be overridden by the task or task group
    21  	tgNetMode := "host"
    22  	if len(tg.Networks) > 0 && tg.Networks[0].Mode != "" {
    23  		tgNetMode = tg.Networks[0].Mode
    24  	}
    25  
    26  	// networkInitiator tracks the task driver which needs to create the network
    27  	// to check for multiple drivers needing the create the network
    28  	var networkInitiator string
    29  
    30  	// driverCaps tracks which drivers we've checked capabilities for so as not
    31  	// to do extra work
    32  	driverCaps := make(map[string]struct{})
    33  	for _, task := range tg.Tasks {
    34  		// the task's netmode defaults to the the task group but can be overridden
    35  		taskNetMode := tgNetMode
    36  		if len(task.Resources.Networks) > 0 && task.Resources.Networks[0].Mode != "" {
    37  			taskNetMode = task.Resources.Networks[0].Mode
    38  		}
    39  
    40  		// netmode host should always work to support backwards compat
    41  		if taskNetMode == "host" {
    42  			continue
    43  		}
    44  
    45  		// check to see if capabilities of this task's driver have already been checked
    46  		if _, ok := driverCaps[task.Driver]; ok {
    47  			continue
    48  		}
    49  
    50  		driver, err := driverManager.Dispense(task.Driver)
    51  		if err != nil {
    52  			return nil, fmt.Errorf("failed to dispense driver %s: %v", task.Driver, err)
    53  		}
    54  
    55  		caps, err := driver.Capabilities()
    56  		if err != nil {
    57  			return nil, fmt.Errorf("failed to retrieve capabilities for driver %s: %v",
    58  				task.Driver, err)
    59  		}
    60  
    61  		// check that the driver supports the requested network isolation mode
    62  		netIsolationMode := netModeToIsolationMode(taskNetMode)
    63  		if !caps.HasNetIsolationMode(netIsolationMode) {
    64  			return nil, fmt.Errorf("task %s does not support %q networking mode", task.Name, taskNetMode)
    65  		}
    66  
    67  		// check if the driver needs to create the network and if a different
    68  		// driver has already claimed it needs to initiate the network
    69  		if caps.MustInitiateNetwork {
    70  			if networkInitiator != "" {
    71  				return nil, fmt.Errorf("tasks %s and %s want to initiate networking but only one driver can do so", networkInitiator, task.Name)
    72  			}
    73  			netManager, ok := driver.(drivers.DriverNetworkManager)
    74  			if !ok {
    75  				return nil, fmt.Errorf("driver %s does not implement network management RPCs", task.Driver)
    76  			}
    77  
    78  			nm = netManager
    79  			networkInitiator = task.Name
    80  		}
    81  
    82  		// mark this driver's capabilities as checked
    83  		driverCaps[task.Driver] = struct{}{}
    84  	}
    85  
    86  	return nm, nil
    87  }
    88  
    89  // defaultNetworkManager creates a network namespace for the alloc
    90  type defaultNetworkManager struct{}
    91  
    92  func (*defaultNetworkManager) CreateNetwork(allocID string) (*drivers.NetworkIsolationSpec, bool, error) {
    93  	netns, err := nsutil.NewNS(allocID)
    94  	if err != nil {
    95  		return nil, false, err
    96  	}
    97  
    98  	spec := &drivers.NetworkIsolationSpec{
    99  		Mode:   drivers.NetIsolationModeGroup,
   100  		Path:   netns.Path(),
   101  		Labels: make(map[string]string),
   102  	}
   103  
   104  	return spec, true, nil
   105  }
   106  
   107  func (*defaultNetworkManager) DestroyNetwork(allocID string, spec *drivers.NetworkIsolationSpec) error {
   108  	return nsutil.UnmountNS(spec.Path)
   109  }
   110  
   111  func netModeToIsolationMode(netMode string) drivers.NetIsolationMode {
   112  	switch strings.ToLower(netMode) {
   113  	case "host":
   114  		return drivers.NetIsolationModeHost
   115  	case "bridge", "none":
   116  		return drivers.NetIsolationModeGroup
   117  	case "driver":
   118  		return drivers.NetIsolationModeTask
   119  	default:
   120  		return drivers.NetIsolationModeHost
   121  	}
   122  }
   123  
   124  func newNetworkConfigurator(log hclog.Logger, alloc *structs.Allocation, config *clientconfig.Config) (NetworkConfigurator, error) {
   125  	tg := alloc.Job.LookupTaskGroup(alloc.TaskGroup)
   126  
   127  	// Check if network stanza is given
   128  	if len(tg.Networks) == 0 {
   129  		return &hostNetworkConfigurator{}, nil
   130  	}
   131  
   132  	switch strings.ToLower(tg.Networks[0].Mode) {
   133  	case "bridge":
   134  		return newBridgeNetworkConfigurator(log, config.BridgeNetworkName, config.BridgeNetworkAllocSubnet, config.CNIPath)
   135  	default:
   136  		return &hostNetworkConfigurator{}, nil
   137  	}
   138  }