diff options
-rw-r--r-- | cmd/podman/cliconfig/config.go | 1 | ||||
-rw-r--r-- | cmd/podman/network_create.go | 11 | ||||
-rw-r--r-- | completions/bash/podman | 1 | ||||
-rw-r--r-- | docs/source/markdown/podman-network-create.1.md | 17 | ||||
-rw-r--r-- | pkg/adapter/network.go | 51 | ||||
-rw-r--r-- | pkg/network/config.go | 16 | ||||
-rw-r--r-- | pkg/network/netconflist.go | 12 |
7 files changed, 104 insertions, 5 deletions
diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go index 780b68333..857c49a48 100644 --- a/cmd/podman/cliconfig/config.go +++ b/cmd/podman/cliconfig/config.go @@ -274,6 +274,7 @@ type NetworkCreateValues struct { IPRange net.IPNet IPV6 bool Network net.IPNet + MacVLAN string } type NetworkListValues struct { diff --git a/cmd/podman/network_create.go b/cmd/podman/network_create.go index 6710883ae..886607885 100644 --- a/cmd/podman/network_create.go +++ b/cmd/podman/network_create.go @@ -41,6 +41,7 @@ func init() { flags.IPVar(&networkCreateCommand.Gateway, "gateway", nil, "IPv4 or IPv6 gateway for the subnet") flags.BoolVar(&networkCreateCommand.Internal, "internal", false, "restrict external access from this network") flags.IPNetVar(&networkCreateCommand.IPRange, "ip-range", net.IPNet{}, "allocate container IP from range") + flags.StringVar(&networkCreateCommand.MacVLAN, "macvlan", "", "create a Macvlan connection based on this device") // TODO not supported yet //flags.StringVar(&networkCreateCommand.IPamDriver, "ipam-driver", "", "IP Address Management Driver") // TODO enable when IPv6 is working @@ -50,6 +51,10 @@ func init() { } func networkcreateCmd(c *cliconfig.NetworkCreateValues) error { + var ( + fileName string + err error + ) if err := network.IsSupportedDriver(c.Driver); err != nil { return err } @@ -66,7 +71,11 @@ func networkcreateCmd(c *cliconfig.NetworkCreateValues) error { if err != nil { return err } - fileName, err := runtime.NetworkCreate(c) + if len(c.MacVLAN) > 0 { + fileName, err = runtime.NetworkCreateMacVLAN(c) + } else { + fileName, err = runtime.NetworkCreateBridge(c) + } if err == nil { fmt.Println(fileName) } diff --git a/completions/bash/podman b/completions/bash/podman index d8034ad11..379c33711 100644 --- a/completions/bash/podman +++ b/completions/bash/podman @@ -980,6 +980,7 @@ _podman_network_create() { --driver --gateway --ip-range + --macvlan --subnet " local boolean_options=" diff --git a/docs/source/markdown/podman-network-create.1.md b/docs/source/markdown/podman-network-create.1.md index c281d50d9..2eca93adb 100644 --- a/docs/source/markdown/podman-network-create.1.md +++ b/docs/source/markdown/podman-network-create.1.md @@ -7,8 +7,10 @@ podman\-network-create - Create a Podman CNI network **podman network create** [*options*] name ## DESCRIPTION -Create a CNI-network configuration for use with Podman. At the time of this writing, the only network -type that can be created is a *bridge* network. +Create a CNI-network configuration for use with Podman. By default, Podman creates a bridge connection. A +*Macvlan* connection can be created with the *macvlan* option. In the case of *Macvlan* connections, the +CNI *dhcp* plugin needs to be activated or the container image must have a DHCP client to interact +with the host network's DHCP server. If no options are provided, Podman will assign a free subnet and name for your network. @@ -38,6 +40,11 @@ Restrict external access of this network Allocate container IP from a range. The range must be a complete subnet and in CIDR notation. The *ip-range* option must be used with a *subnet* option. +**--macvlan** + +Create a *Macvlan* based connection rather than a classic bridge. You must pass an interface name from the host for the +Macvlan connection. + **--subnet** The subnet in CIDR notation. @@ -68,6 +75,12 @@ Create a network that uses a *192.168.55.0/24** subnet and has an IP address ran /etc/cni/net.d/cni-podman-5.conflist ``` +Create a Macvlan based network using the host interface eth0 +``` +# podman network create --macvlan eth0 newnet +/etc/cni/net.d/newnet.conflist +``` + ## SEE ALSO podman(1), podman-network(1), podman-network-inspect(1) diff --git a/pkg/adapter/network.go b/pkg/adapter/network.go index 9659ae339..160e334e9 100644 --- a/pkg/adapter/network.go +++ b/pkg/adapter/network.go @@ -153,8 +153,8 @@ func (r *LocalRuntime) removeNetwork(ctx context.Context, name string, container return nil } -// NetworkCreate creates a CNI network -func (r *LocalRuntime) NetworkCreate(cli *cliconfig.NetworkCreateValues) (string, error) { +// NetworkCreateBridge creates a CNI network +func (r *LocalRuntime) NetworkCreateBridge(cli *cliconfig.NetworkCreateValues) (string, error) { isGateway := true ipMasq := true subnet := &cli.Network @@ -262,3 +262,50 @@ func (r *LocalRuntime) NetworkCreate(cli *cliconfig.NetworkCreateValues) (string err = ioutil.WriteFile(cniPathName, b, 0644) return cniPathName, err } + +// NetworkCreateMacVLAN creates a CNI network +func (r *LocalRuntime) NetworkCreateMacVLAN(cli *cliconfig.NetworkCreateValues) (string, error) { + var ( + name string + plugins []network.CNIPlugins + ) + liveNetNames, err := network.GetLiveNetworkNames() + if err != nil { + return "", err + } + // Make sure the host-device exists + if !util.StringInSlice(cli.MacVLAN, liveNetNames) { + return "", errors.Errorf("failed to find network interface %q", cli.MacVLAN) + } + if len(cli.InputArgs) > 0 { + name = cli.InputArgs[0] + netNames, err := network.GetNetworkNamesFromFileSystem() + if err != nil { + return "", err + } + if util.StringInSlice(name, netNames) { + return "", errors.Errorf("the network name %s is already used", name) + } + } + if len(name) < 1 { + name, err = network.GetFreeDeviceName() + if err != nil { + return "", err + } + } + ncList := network.NewNcList(name, cniversion.Current()) + macvlan := network.NewMacVLANPlugin(cli.MacVLAN) + plugins = append(plugins, macvlan) + ncList["plugins"] = plugins + b, err := json.MarshalIndent(ncList, "", " ") + if err != nil { + return "", err + } + cniConfigPath, err := getCNIConfDir(r) + if err != nil { + return "", err + } + cniPathName := filepath.Join(cniConfigPath, fmt.Sprintf("%s.conflist", name)) + err = ioutil.WriteFile(cniPathName, b, 0644) + return cniPathName, err +} diff --git a/pkg/network/config.go b/pkg/network/config.go index 37eb0dd64..e47b16143 100644 --- a/pkg/network/config.go +++ b/pkg/network/config.go @@ -90,6 +90,22 @@ func (p PortMapConfig) Bytes() ([]byte, error) { return json.MarshalIndent(p, "", "\t") } +type IPAMDHCP struct { + DHCP string `json:"type"` +} + +// MacVLANConfig describes the macvlan config +type MacVLANConfig struct { + PluginType string `json:"type"` + Master string `json:"master"` + IPAM IPAMDHCP `json:"ipam"` +} + +// Bytes outputs the configuration as []byte +func (p MacVLANConfig) Bytes() ([]byte, error) { + return json.MarshalIndent(p, "", "\t") +} + // FirewallConfig describes the firewall plugin type FirewallConfig struct { PluginType string `json:"type"` diff --git a/pkg/network/netconflist.go b/pkg/network/netconflist.go index e19051b88..a8217097a 100644 --- a/pkg/network/netconflist.go +++ b/pkg/network/netconflist.go @@ -132,3 +132,15 @@ func HasDNSNamePlugin(paths []string) bool { } return false } + +// NewMacVLANPlugin creates a macvlanconfig with a given device name +func NewMacVLANPlugin(device string) MacVLANConfig { + i := IPAMDHCP{DHCP: "dhcp"} + + m := MacVLANConfig{ + PluginType: "macvlan", + Master: device, + IPAM: i, + } + return m +} |