예제 #1
0
파일: podenv.go 프로젝트: nhlfr/rkt
func (e *podEnv) setupNets(nets []activeNet, noDNS bool) error {
	err := os.MkdirAll(e.netDir(), 0755)
	if err != nil {
		return err
	}

	i := 0
	defer func() {
		if err != nil {
			e.teardownNets(nets[:i])
		}
	}()

	n := activeNet{}

	// did stage0 already make /etc/rkt-resolv.conf (i.e. --dns passed)
	resolvPath := filepath.Join(common.Stage1RootfsPath(e.podRoot), "etc/rkt-resolv.conf")
	_, err = os.Stat(resolvPath)
	if err != nil && !os.IsNotExist(err) {
		return errwrap.Wrap(fmt.Errorf("error statting /etc/rkt-resolv.conf"), err)
	}
	podHasResolvConf := err == nil

	for i, n = range nets {
		if debuglog {
			stderr.Printf("loading network %v with type %v", n.conf.Name, n.conf.Type)
		}

		n.runtime.IfName = fmt.Sprintf(IfNamePattern, i)
		if n.runtime.ConfPath, err = copyFileToDir(n.runtime.ConfPath, e.netDir()); err != nil {
			return errwrap.Wrap(fmt.Errorf("error copying %q to %q", n.runtime.ConfPath, e.netDir()), err)
		}

		// Actually shell out to the plugin
		err = e.netPluginAdd(&n, e.podNS.Path())
		if err != nil {
			return errwrap.Wrap(fmt.Errorf("error adding network %q", n.conf.Name), err)
		}

		// Generate rkt-resolv.conf if it's not already there.
		// The first network plugin that supplies a non-empty
		// DNS response will win, unless noDNS is true (--dns passed to rkt run)
		if !common.IsDNSZero(&n.runtime.DNS) && !noDNS {
			if !podHasResolvConf {
				err := ioutil.WriteFile(
					resolvPath,
					[]byte(common.MakeResolvConf(n.runtime.DNS, "Generated by rkt from network "+n.conf.Name)),
					0644)
				if err != nil {
					return errwrap.Wrap(fmt.Errorf("error creating resolv.conf"), err)
				}
				podHasResolvConf = true
			} else {
				stderr.Printf("Warning: network %v plugin specified DNS configuration, but DNS already supplied", n.conf.Name)
			}
		}
	}
	return nil
}
예제 #2
0
파일: run.go 프로젝트: intelsdi-x/rkt
/*
 * Parse out the --hosts-entries, --dns, --dns-search, and --dns-opt flags
 * This includes decoding the "magic" values for hosts-entries and dns.
 * Try to detect any obvious insanity, namely invalid IPs or more than one
 * magic option
 */
func parseDNSFlags(flagHostsEntries, flagDNS, flagDNSSearch, flagDNSOpt []string, flagDNSDomain string) (stage0.DNSConfMode, cnitypes.DNS, *stage0.HostsEntries, error) {
	DNSConfMode := stage0.DNSConfMode{
		Resolv: "default",
		Hosts:  "default",
	}
	DNSConfig := cnitypes.DNS{}
	HostsEntries := make(stage0.HostsEntries)

	// Loop through --dns and look for magic option
	// Check for obvious insanity - only one magic option allowed
	for _, d := range flagDNS {
		// parse magic values
		if d == "host" || d == "none" {
			if len(flagDNS) > 1 {
				return DNSConfMode, DNSConfig, &HostsEntries,
					fmt.Errorf("no other --dns options allowed when --dns=%s is passed", d)
			}
			DNSConfMode.Resolv = d
			break

		} else {
			// parse list of IPS
			for _, d := range strings.Split(d, ",") {
				if net.ParseIP(d) == nil {
					return DNSConfMode, DNSConfig, &HostsEntries,
						fmt.Errorf("Invalid IP passed to --dns: %s", d)
				}
				DNSConfig.Nameservers = append(DNSConfig.Nameservers, d)
			}
		}
	}

	DNSConfig.Search = flagDNSSearch
	DNSConfig.Options = flagDNSOpt
	DNSConfig.Domain = flagDNSDomain

	if !common.IsDNSZero(&DNSConfig) {
		if DNSConfMode.Resolv == "default" {
			DNSConfMode.Resolv = "stage0"
		}

		if DNSConfMode.Resolv != "stage0" {
			return DNSConfMode, DNSConfig, &HostsEntries,
				fmt.Errorf("Cannot call --dns-opt, --dns-search, or --dns-domain with --dns=%v", DNSConfMode.Resolv)
		}
	}

	// Parse out --hosts-entries, also looking for the magic value "host"
	for _, entry := range flagHostsEntries {
		if entry == "host" {
			if len(flagHostsEntries) == 1 {
				DNSConfMode.Hosts = "host"
			} else {
				return DNSConfMode, DNSConfig, &HostsEntries,
					fmt.Errorf("cannot pass --hosts-entry=host with multiple hosts-entries")
			}
			break
		}
		for _, entry := range strings.Split(entry, ",") {
			vals := strings.SplitN(entry, "=", 2)
			if len(vals) != 2 {
				return DNSConfMode, DNSConfig, &HostsEntries,
					fmt.Errorf("Did not understand --hosts-entry %s", entry)
			}
			ipStr := vals[0]
			hostname := vals[1]

			// validate IP address
			ip := net.ParseIP(ipStr)
			if ip == nil {
				return DNSConfMode, DNSConfig, &HostsEntries,
					fmt.Errorf("Invalid IP passed to --hosts-entry: %s", ipStr)
			}

			_, exists := HostsEntries[ipStr]
			if !exists {
				HostsEntries[ipStr] = []string{hostname}
			} else {
				HostsEntries[ipStr] = append(HostsEntries[ipStr], hostname)
			}
		}
	}

	if len(HostsEntries) > 0 {
		DNSConfMode.Hosts = "stage0"
	}

	return DNSConfMode, DNSConfig, &HostsEntries, nil
}
예제 #3
0
파일: kvm.go 프로젝트: nhlfr/rkt
// kvmSetup prepare new Networking to be used in kvm environment based on tuntap pair interfaces
// to allow communication with virtual machine created by lkvm tool
func kvmSetup(podRoot string, podID types.UUID, fps []ForwardedPort, netList common.NetList, localConfig string, noDNS bool) (*Networking, error) {
	network := Networking{
		podEnv: podEnv{
			podRoot:      podRoot,
			podID:        podID,
			netsLoadList: netList,
			localConfig:  localConfig,
		},
	}
	var e error

	// If there's a network set as default in CNI configuration
	defaultGatewaySet := false

	_, defaultNet, err := net.ParseCIDR("0.0.0.0/0")
	if err != nil {
		return nil, errwrap.Wrap(errors.New("error when parsing net address"), err)
	}

	network.nets, e = network.loadNets()
	if e != nil {
		return nil, errwrap.Wrap(errors.New("error loading network definitions"), e)
	}

	// did stage0 already make /etc/rkt-resolv.conf (i.e. --dns passed)
	resolvPath := filepath.Join(common.Stage1RootfsPath(podRoot), "etc/rkt-resolv.conf")
	_, err = os.Stat(resolvPath)
	if err != nil && !os.IsNotExist(err) {
		return nil, errwrap.Wrap(fmt.Errorf("error statting /etc/rkt-resolv.conf"), err)
	}
	podHasResolvConf := err == nil

	for i, n := range network.nets {
		if n.conf.Type == "flannel" {
			if err := kvmTransformFlannelNetwork(&n); err != nil {
				return nil, errwrap.Wrap(errors.New("cannot transform flannel network into basic network"), err)
			}
		}
		switch n.conf.Type {
		case "ptp":
			link, err := setupTapDevice(podID)
			if err != nil {
				return nil, err
			}
			ifName := link.Attrs().Name
			n.runtime.IfName = ifName

			err = kvmSetupNetAddressing(&network, n, ifName)
			if err != nil {
				return nil, err
			}

			// add address to host tap device
			err = ensureHasAddr(
				link,
				&net.IPNet{
					IP:   n.runtime.IP4.Gateway,
					Mask: net.IPMask(n.runtime.Mask),
				},
			)
			if err != nil {
				return nil, errwrap.Wrap(fmt.Errorf("cannot add address to host tap device %q", ifName), err)
			}

			if err := removeAllRoutesOnLink(link); err != nil {
				return nil, errwrap.Wrap(fmt.Errorf("cannot remove route on host tap device %q", ifName), err)
			}

			if err := addRoute(link, n.runtime.IP); err != nil {
				return nil, errwrap.Wrap(errors.New("cannot add on host direct route to pod"), err)
			}

		case "bridge":
			config := BridgeNetConf{
				NetConf: NetConf{
					MTU: defaultMTU,
				},
				BrName: defaultBrName,
			}
			if err := json.Unmarshal(n.confBytes, &config); err != nil {
				return nil, errwrap.Wrap(fmt.Errorf("error parsing %q result", n.conf.Name), err)
			}

			br, err := ensureBridgeIsUp(config.BrName, config.MTU)
			if err != nil {
				return nil, errwrap.Wrap(errors.New("error in time of bridge setup"), err)
			}
			link, err := setupTapDevice(podID)
			if err != nil {
				return nil, errwrap.Wrap(errors.New("can not setup tap device"), err)
			}
			err = netlink.LinkSetMaster(link, br)
			if err != nil {
				rErr := tuntap.RemovePersistentIface(n.runtime.IfName, tuntap.Tap)
				if rErr != nil {
					stderr.PrintE("warning: could not cleanup tap interface", rErr)
				}
				return nil, errwrap.Wrap(errors.New("can not add tap interface to bridge"), err)
			}

			ifName := link.Attrs().Name
			n.runtime.IfName = ifName

			err = kvmSetupNetAddressing(&network, n, ifName)
			if err != nil {
				return nil, err
			}

			if n.conf.IsDefaultGateway {
				n.runtime.IP4.Routes = append(
					n.runtime.IP4.Routes,
					cnitypes.Route{Dst: *defaultNet, GW: n.runtime.IP4.Gateway},
				)
				defaultGatewaySet = true
				config.IsGw = true
			}

			if config.IsGw {
				err = ensureHasAddr(
					br,
					&net.IPNet{
						IP:   n.runtime.IP4.Gateway,
						Mask: net.IPMask(n.runtime.Mask),
					},
				)

				if err != nil {
					return nil, errwrap.Wrap(fmt.Errorf("cannot add address to host bridge device %q", br.Name), err)
				}
			}

		case "macvlan":
			config := MacVTapNetConf{}
			if err := json.Unmarshal(n.confBytes, &config); err != nil {
				return nil, errwrap.Wrap(fmt.Errorf("error parsing %q result", n.conf.Name), err)
			}
			link, err := setupMacVTapDevice(podID, config, i)
			if err != nil {
				return nil, err
			}
			ifName := link.Attrs().Name
			n.runtime.IfName = ifName

			err = kvmSetupNetAddressing(&network, n, ifName)
			if err != nil {
				return nil, err
			}

		default:
			return nil, fmt.Errorf("network %q have unsupported type: %q", n.conf.Name, n.conf.Type)
		}

		// Check if there's any other network set as default gateway
		if defaultGatewaySet {
			for _, route := range n.runtime.IP4.Routes {
				if (defaultNet.String() == route.Dst.String()) && !n.conf.IsDefaultGateway {
					return nil, fmt.Errorf("flannel config enables default gateway and IPAM sets default gateway via %q", n.runtime.IP4.Gateway)
				}
			}
		}

		// Generate rkt-resolv.conf if it's not already there.
		// The first network plugin that supplies a non-empty
		// DNS response will win, unless noDNS is true (--dns passed to rkt run)
		if !common.IsDNSZero(&n.runtime.DNS) && !noDNS {
			if !podHasResolvConf {
				err := ioutil.WriteFile(
					resolvPath,
					[]byte(common.MakeResolvConf(n.runtime.DNS, "Generated by rkt from network "+n.conf.Name)),
					0644)
				if err != nil {
					return nil, errwrap.Wrap(fmt.Errorf("error creating resolv.conf"), err)
				}
				podHasResolvConf = true
			} else {
				stderr.Printf("Warning: network %v plugin specified DNS configuration, but DNS already supplied", n.conf.Name)
			}
		}

		if n.conf.IPMasq {
			chain := cniutils.FormatChainName(n.conf.Name, podID.String())
			comment := cniutils.FormatComment(n.conf.Name, podID.String())
			if err := ip.SetupIPMasq(&net.IPNet{
				IP:   n.runtime.IP,
				Mask: net.IPMask(n.runtime.Mask),
			}, chain, comment); err != nil {
				return nil, err
			}
		}
		network.nets[i] = n
	}
	podIP, err := network.GetForwardableNetPodIP()
	if err != nil {
		return nil, err
	}
	if err := network.forwardPorts(fps, podIP); err != nil {
		return nil, err
	}

	return &network, nil
}