summaryrefslogtreecommitdiff
path: root/libpod/network/create.go
diff options
context:
space:
mode:
Diffstat (limited to 'libpod/network/create.go')
-rw-r--r--libpod/network/create.go195
1 files changed, 195 insertions, 0 deletions
diff --git a/libpod/network/create.go b/libpod/network/create.go
new file mode 100644
index 000000000..a9ed4c4ef
--- /dev/null
+++ b/libpod/network/create.go
@@ -0,0 +1,195 @@
+package network
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+
+ "github.com/containernetworking/cni/pkg/version"
+ "github.com/containers/podman/v2/libpod"
+ "github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/util"
+ "github.com/pkg/errors"
+)
+
+func Create(name string, options entities.NetworkCreateOptions, r *libpod.Runtime) (*entities.NetworkCreateReport, error) {
+ var fileName string
+ if err := isSupportedDriver(options.Driver); err != nil {
+ return nil, err
+ }
+ config, err := r.GetConfig()
+ if err != nil {
+ return nil, err
+ }
+ // Acquire a lock for CNI
+ l, err := acquireCNILock(filepath.Join(config.Engine.TmpDir, LockFileName))
+ if err != nil {
+ return nil, err
+ }
+ defer l.releaseCNILock()
+ if len(options.MacVLAN) > 0 {
+ fileName, err = createMacVLAN(r, name, options)
+ } else {
+ fileName, err = createBridge(r, name, options)
+ }
+ if err != nil {
+ return nil, err
+ }
+ return &entities.NetworkCreateReport{Filename: fileName}, nil
+}
+
+// createBridge creates a CNI network
+func createBridge(r *libpod.Runtime, name string, options entities.NetworkCreateOptions) (string, error) {
+ isGateway := true
+ ipMasq := true
+ subnet := &options.Subnet
+ ipRange := options.Range
+ runtimeConfig, err := r.GetConfig()
+ if err != nil {
+ return "", err
+ }
+ // if range is provided, make sure it is "in" network
+ if subnet.IP != nil {
+ // if network is provided, does it conflict with existing CNI or live networks
+ err = ValidateUserNetworkIsAvailable(runtimeConfig, subnet)
+ } else {
+ // if no network is provided, figure out network
+ subnet, err = GetFreeNetwork(runtimeConfig)
+ }
+ if err != nil {
+ return "", err
+ }
+ gateway := options.Gateway
+ if gateway == nil {
+ // if no gateway is provided, provide it as first ip of network
+ gateway = CalcGatewayIP(subnet)
+ }
+ // if network is provided and if gateway is provided, make sure it is "in" network
+ if options.Subnet.IP != nil && options.Gateway != nil {
+ if !subnet.Contains(gateway) {
+ return "", errors.Errorf("gateway %s is not in valid for subnet %s", gateway.String(), subnet.String())
+ }
+ }
+ if options.Internal {
+ isGateway = false
+ ipMasq = false
+ }
+
+ // if a range is given, we need to ensure it is "in" the network range.
+ if options.Range.IP != nil {
+ if options.Subnet.IP == nil {
+ return "", errors.New("you must define a subnet range to define an ip-range")
+ }
+ firstIP, err := FirstIPInSubnet(&options.Range)
+ if err != nil {
+ return "", err
+ }
+ lastIP, err := LastIPInSubnet(&options.Range)
+ if err != nil {
+ return "", err
+ }
+ if !subnet.Contains(firstIP) || !subnet.Contains(lastIP) {
+ return "", errors.Errorf("the ip range %s does not fall within the subnet range %s", options.Range.String(), subnet.String())
+ }
+ }
+ bridgeDeviceName, err := GetFreeDeviceName(runtimeConfig)
+ if err != nil {
+ return "", err
+ }
+
+ if len(name) > 0 {
+ netNames, err := GetNetworkNamesFromFileSystem(runtimeConfig)
+ if err != nil {
+ return "", err
+ }
+ if util.StringInSlice(name, netNames) {
+ return "", errors.Errorf("the network name %s is already used", name)
+ }
+ } else {
+ // If no name is given, we give the name of the bridge device
+ name = bridgeDeviceName
+ }
+
+ ncList := NewNcList(name, version.Current())
+ var plugins []CNIPlugins
+ var routes []IPAMRoute
+
+ defaultRoute, err := NewIPAMDefaultRoute(IsIPv6(subnet.IP))
+ if err != nil {
+ return "", err
+ }
+ routes = append(routes, defaultRoute)
+ ipamConfig, err := NewIPAMHostLocalConf(subnet, routes, ipRange, gateway)
+ if err != nil {
+ return "", err
+ }
+
+ // TODO need to iron out the role of isDefaultGW and IPMasq
+ bridge := NewHostLocalBridge(bridgeDeviceName, isGateway, false, ipMasq, ipamConfig)
+ plugins = append(plugins, bridge)
+ plugins = append(plugins, NewPortMapPlugin())
+ plugins = append(plugins, NewFirewallPlugin())
+ // if we find the dnsname plugin, we add configuration for it
+ if HasDNSNamePlugin(runtimeConfig.Network.CNIPluginDirs) && !options.DisableDNS {
+ // Note: in the future we might like to allow for dynamic domain names
+ plugins = append(plugins, NewDNSNamePlugin(DefaultPodmanDomainName))
+ }
+ ncList["plugins"] = plugins
+ b, err := json.MarshalIndent(ncList, "", " ")
+ if err != nil {
+ return "", err
+ }
+ if err := os.MkdirAll(GetCNIConfDir(runtimeConfig), 0755); err != nil {
+ return "", err
+ }
+ cniPathName := filepath.Join(GetCNIConfDir(runtimeConfig), fmt.Sprintf("%s.conflist", name))
+ err = ioutil.WriteFile(cniPathName, b, 0644)
+ return cniPathName, err
+}
+
+func createMacVLAN(r *libpod.Runtime, name string, options entities.NetworkCreateOptions) (string, error) {
+ var (
+ plugins []CNIPlugins
+ )
+ liveNetNames, err := GetLiveNetworkNames()
+ if err != nil {
+ return "", err
+ }
+
+ config, err := r.GetConfig()
+ if err != nil {
+ return "", err
+ }
+
+ // Make sure the host-device exists
+ if !util.StringInSlice(options.MacVLAN, liveNetNames) {
+ return "", errors.Errorf("failed to find network interface %q", options.MacVLAN)
+ }
+ if len(name) > 0 {
+ netNames, err := GetNetworkNamesFromFileSystem(config)
+ if err != nil {
+ return "", err
+ }
+ if util.StringInSlice(name, netNames) {
+ return "", errors.Errorf("the network name %s is already used", name)
+ }
+ } else {
+ name, err = GetFreeDeviceName(config)
+ if err != nil {
+ return "", err
+ }
+ }
+ ncList := NewNcList(name, version.Current())
+ macvlan := NewMacVLANPlugin(options.MacVLAN)
+ plugins = append(plugins, macvlan)
+ ncList["plugins"] = plugins
+ b, err := json.MarshalIndent(ncList, "", " ")
+ if err != nil {
+ return "", err
+ }
+ cniPathName := filepath.Join(GetCNIConfDir(config), fmt.Sprintf("%s.conflist", name))
+ err = ioutil.WriteFile(cniPathName, b, 0644)
+ return cniPathName, err
+}