diff options
author | baude <bbaude@redhat.com> | 2019-08-08 06:01:00 -0500 |
---|---|---|
committer | baude <bbaude@redhat.com> | 2019-09-09 09:32:43 -0500 |
commit | ee432cf2792c5dbe81953007f1fd5c87beb3ebd5 (patch) | |
tree | dc0646e4b2faeadf9cca58bf80f1e90d98c50165 /pkg/adapter | |
parent | 30cbb0091515a7f802f0f3f3ee486be6ff98f645 (diff) | |
download | podman-ee432cf2792c5dbe81953007f1fd5c87beb3ebd5.tar.gz podman-ee432cf2792c5dbe81953007f1fd5c87beb3ebd5.tar.bz2 podman-ee432cf2792c5dbe81953007f1fd5c87beb3ebd5.zip |
podman network create
initial implementation of network create. we only support bridging
networks with this first pass.
Signed-off-by: baude <bbaude@redhat.com>
Diffstat (limited to 'pkg/adapter')
-rw-r--r-- | pkg/adapter/network.go | 135 |
1 files changed, 97 insertions, 38 deletions
diff --git a/pkg/adapter/network.go b/pkg/adapter/network.go index cf3a1dfdd..e4a160767 100644 --- a/pkg/adapter/network.go +++ b/pkg/adapter/network.go @@ -5,12 +5,13 @@ package adapter import ( "encoding/json" "fmt" + "github.com/containers/libpod/pkg/util" "io/ioutil" "os" - "strings" + "path/filepath" "text/tabwriter" - "github.com/containernetworking/cni/libcni" + cniversion "github.com/containernetworking/cni/pkg/version" "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/pkg/network" "github.com/pkg/errors" @@ -51,7 +52,7 @@ func (r *LocalRuntime) NetworkList(cli *cliconfig.NetworkListValues) error { return err } for _, cniNetwork := range networks { - if _, err := fmt.Fprintf(w, "%s\t%s\t%s\n", cniNetwork.Name, cniNetwork.CNIVersion, getCNIPlugins(cniNetwork)); err != nil { + if _, err := fmt.Fprintf(w, "%s\t%s\t%s\n", cniNetwork.Name, cniNetwork.CNIVersion, network.GetCNIPlugins(cniNetwork)); err != nil { return err } } @@ -64,12 +65,8 @@ func (r *LocalRuntime) NetworkInspect(cli *cliconfig.NetworkInspectValues) error var ( rawCNINetworks []map[string]interface{} ) - cniConfigPath, err := getCNIConfDir(r) - if err != nil { - return err - } for _, name := range cli.InputArgs { - b, err := readRawCNIConfByName(name, cniConfigPath) + b, err := network.ReadRawCNIConfByName(name) if err != nil { return err } @@ -89,12 +86,8 @@ func (r *LocalRuntime) NetworkInspect(cli *cliconfig.NetworkInspectValues) error // NetworkRemove deletes one or more CNI networks func (r *LocalRuntime) NetworkRemove(cli *cliconfig.NetworkRmValues) error { - cniConfigPath, err := getCNIConfDir(r) - if err != nil { - return err - } for _, name := range cli.InputArgs { - cniPath, err := getCNIConfigPathByName(name, cniConfigPath) + cniPath, err := network.GetCNIConfigPathByName(name) if err != nil { return err } @@ -106,42 +99,108 @@ func (r *LocalRuntime) NetworkRemove(cli *cliconfig.NetworkRmValues) error { return nil } -// getCNIConfigPathByName finds a CNI network by name and -// returns its configuration file path -func getCNIConfigPathByName(name, cniConfigPath string) (string, error) { - files, err := libcni.ConfFiles(cniConfigPath, []string{".conflist"}) +// NetworkCreate creates a CNI network +func (r *LocalRuntime) NetworkCreate(cli *cliconfig.NetworkCreateValues) (string, error) { + var ( + err error + ) + + isGateway := true + ipMasq := true + subnet := &cli.Network + ipRange := cli.IPRange + + // if range is provided, make sure it is "in" network + if cli.IsSet("subnet") { + // if network is provided, does it conflict with existing CNI or live networks + err = network.ValidateUserNetworkIsAvailable(subnet) + } else { + // if no network is provided, figure out network + subnet, err = network.GetFreeNetwork() + } if err != nil { return "", err } - for _, confFile := range files { - conf, err := libcni.ConfListFromFile(confFile) + + gateway := cli.Gateway + if gateway == nil { + // if no gateway is provided, provide it as first ip of network + gateway = network.CalcGatewayIP(subnet) + } + // if network is provided and if gateway is provided, make sure it is "in" network + if cli.IsSet("subnet") && cli.IsSet("gateway") { + if !subnet.Contains(gateway) { + return "", errors.Errorf("gateway %s is not in valid for subnet %s", gateway.String(), subnet.String()) + } + } + if cli.Internal { + isGateway = false + ipMasq = false + } + + // if a range is given, we need to ensure it is "in" the network range. + if cli.IsSet("ip-range") { + if !cli.IsSet("subnet") { + return "", errors.New("you must define a subnet range to define an ip-range") + } + firstIP, err := network.FirstIPInSubnet(&cli.IPRange) + if err != nil { + return "", err + } + lastIP, err := network.LastIPInSubnet(&cli.IPRange) if err != nil { return "", err } - if conf.Name == name { - return confFile, nil + if !subnet.Contains(firstIP) || !subnet.Contains(lastIP) { + return "", errors.Errorf("the ip range %s does not fall within the subnet range %s", cli.IPRange.String(), subnet.String()) + } + } + bridgeDeviceName, err := network.GetFreeDeviceName() + if err != nil { + return "", err + } + // If no name is given, we give the name of the bridge device + name := bridgeDeviceName + 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) } } - return "", errors.Errorf("unable to find network configuration for %s", name) -} -// readRawCNIConfByName reads the raw CNI configuration for a CNI -// network by name -func readRawCNIConfByName(name, cniConfigPath string) ([]byte, error) { - confFile, err := getCNIConfigPathByName(name, cniConfigPath) + ncList := network.NewNcList(name, cniversion.Current()) + var plugins []network.CNIPlugins + var routes []network.IPAMRoute + + defaultRoute, err := network.NewIPAMDefaultRoute() if err != nil { - return nil, err + return "", err + } + routes = append(routes, defaultRoute) + ipamConfig, err := network.NewIPAMHostLocalConf(subnet, routes, ipRange, gateway) + if err != nil { + return "", err } - b, err := ioutil.ReadFile(confFile) - return b, err -} -// getCNIPlugins returns a list of plugins that a given network -// has in the form of a string -func getCNIPlugins(list *libcni.NetworkConfigList) string { - var plugins []string - for _, plug := range list.Plugins { - plugins = append(plugins, plug.Network.Type) + // TODO need to iron out the role of isDefaultGW and IPMasq + bridge := network.NewHostLocalBridge(bridgeDeviceName, isGateway, false, ipMasq, ipamConfig) + plugins = append(plugins, bridge) + plugins = append(plugins, network.NewPortMapPlugin()) + plugins = append(plugins, network.NewFirewallPlugin()) + ncList["plugins"] = plugins + b, err := json.MarshalIndent(ncList, "", " ") + if err != nil { + return "", err + } + cniConfigPath, err := getCNIConfDir(r) + if err != nil { + return "", err } - return strings.Join(plugins, ",") + cniPathName := filepath.Join(cniConfigPath, fmt.Sprintf("%s.conflist", name)) + err = ioutil.WriteFile(cniPathName, b, 0644) + return cniPathName, err } |