//netlink is not avaible in MAC OS, build fail. func AddContainerNetworking() { if CliIF == "" { log.Fatal("the host-interface is missing,please give one") } if ok := utils.ValidateHostIface(CliIF); !ok { log.Fatalf("the host-interface [ %s ] was not found.", CliIF) } hostmacvlanname, _ := utils.GenerateRandomName(hostprefix, hostlen) hostEth, _ := netlink.LinkByName(CliIF) //create the macvlan device macvlandev := &netlink.Macvlan{ LinkAttrs: netlink.LinkAttrs{ Name: hostmacvlanname, ParentIndex: hostEth.Attrs().Index, }, Mode: netlink.MACVLAN_MODE_BRIDGE, } if err := netlink.LinkAdd(macvlandev); err != nil { log.Fatalf("failed to create Macvlan: [ %v ] with the error: %s", macvlandev.Attrs().Name, err) } // log.Infof("Created Macvlan port: [ %s ] using the mode: [ %s ]", macvlan.Name, macvlanMode) // ugly, actually ,can get the ns from netns.getfromDocker. the netns have many function, netns.getformpid // netns.getfromdocker the arg can not be the container name dockerPid := utils.DockerPid(CliCName) //the macvlandev can be use directly, don't get netlink.byname again. netlink.LinkSetNsPid(macvlandev, dockerPid) runtime.LockOSThread() defer runtime.UnlockOSThread() //get root network namespace origns, _ := netns.Get() defer origns.Close() //enter the docker container network dockerNS, _ := netns.GetFromPid(dockerPid) defer dockerNS.Close() netns.Set(dockerNS) // use macvlandev can cause error,need type assertion. netlink.Macvlan not must be netlink.Link,fmz(realy? the vlan action add) // it is wrong, macvlandev1, _ := netlink.LinkByName(macvlandev.Attrs().Name) // when the eth is up, set name fail,: Device or resource busy netlink.LinkSetDown(macvlandev1) netlink.LinkSetName(macvlandev1, "eth1") addr, err := netlink.ParseAddr(CliIP) if err != nil { log.Fatalf("failed to parse the ip address %v", CliIP) } netlink.AddrAdd(macvlandev1, addr) netlink.LinkSetUp(macvlandev1) /* set the default route, have some problem. Dst == 0.0.0.0/0? no defaultgw := &netlink.Route{ Dst: nil, } netlink.RouteDel(defaultgw) ip, _ := net.ParseIP("8.8.8.8") routes, _ := netlink.RouteGet(ip) for _, r := range routes { netlink.RouteDel(&r) } */ //if use ip instruction, it also can config the container, --privileged have no effect. // The sublime test code(test this function) is strange, it only can avaiable in first time. And then fail(even need to reboot) // got it, //following code successfully delete the default route in docker container,but error in my host ,no such process routes, _ := netlink.RouteList(nil, netlink.FAMILY_V4) for _, r := range routes { if r.Dst == nil { if err := netlink.RouteDel(&r); err != nil { log.Warnf("delete the default error: ", err) } } } if CligwIP == "" { log.Fatal("container gw is null") } defaultRoute := &netlink.Route{ Dst: nil, Gw: net.ParseIP(CligwIP), LinkIndex: macvlandev1.Attrs().Index, } if err := netlink.RouteAdd(defaultRoute); err != nil { log.Warnf("create default route error: ", err) } netns.Set(origns) }
func AddDHCPNetwork() { if ok := utils.ValidateHostIface(flat.CliIF); !ok { log.Fatalf("the host-interface [ %s ] was not found.", flat.CliIF) } hostmacvlanname, _ := utils.GenerateRandomName(hostprefix, hostlen) hostEth, _ := netlink.LinkByName(flat.CliIF) //create the macvlan device macvlandev := &netlink.Macvlan{ LinkAttrs: netlink.LinkAttrs{ Name: hostmacvlanname, ParentIndex: hostEth.Attrs().Index, }, Mode: netlink.MACVLAN_MODE_BRIDGE, } if err := netlink.LinkAdd(macvlandev); err != nil { log.Fatalf("failed to create Macvlan: [ %v ] with the error: %s", macvlandev.Attrs().Name, err) } dockerPid := utils.DockerPid(flat.CliCName) netlink.LinkSetNsPid(macvlandev, dockerPid) runtime.LockOSThread() defer runtime.UnlockOSThread() //get root network namespace origns, _ := netns.Get() defer origns.Close() //enter the docker container network dockerNS, _ := netns.GetFromPid(dockerPid) defer dockerNS.Close() //get the dochclient name dhcpClientPath := "/home/fmzhen/go/src/github.com/fmzhen/docker-macvlan/macvlan/dhcp/dhcpclient.sh" out, err := exec.Command(dhcpClientPath).Output() if err != nil { log.Fatal("exec the dhcpclient.sh error: ", err) } dhcpClient := string(out) // like ip netns exec xxx, just the netns ,so the command in host can exec netns.Set(dockerNS) // use macvlandev can cause error,need type assertion. netlink.Macvlan not must be netlink.Link,fmz macvlandev1, _ := netlink.LinkByName(macvlandev.Attrs().Name) netlink.LinkSetDown(macvlandev1) netlink.LinkSetName(macvlandev1, "eth1") netlink.LinkSetUp(macvlandev1) //delete the default route routes, _ := netlink.RouteList(nil, netlink.FAMILY_V4) for _, r := range routes { if r.Dst == nil { if err := netlink.RouteDel(&r); err != nil { log.Warnf("delete the default error: ", err) } } } //it doesn't work, the problem at the atgs don't pass to the shell script dhcpReqpath := "/home/fmzhen/go/src/github.com/fmzhen/docker-macvlan/macvlan/dhcp/dhcpReq.sh" exec.Command(dhcpReqpath, dhcpClient, string(dockerPid), flat.CliCName).Run() netns.Set(origns) }
func AddVlannetwork(etcdval string, vlanid string, containerName string) { ss := strings.Split(etcdval, ",") hostif := ss[0] if ok := utils.ValidateHostIface(hostif); !ok { log.Warnf("the host interface not exist") return } vlandevName := hostif + "." + vlanid hostEth, _ := netlink.LinkByName(hostif) intvlanid, err := strconv.Atoi(vlanid) if err != nil { log.Warnf("the vlan id convert error: \n") return } var vlandev *netlink.Vlan if ok := utils.ValidateHostIface(vlandevName); ok { } else { //not exist ,create the vlan device vlandev = &netlink.Vlan{ LinkAttrs: netlink.LinkAttrs{ Name: vlandevName, ParentIndex: hostEth.Attrs().Index, }, VlanId: intvlanid, } if err := netlink.LinkAdd(vlandev); err != nil { log.Warnf("failed to create vlandev: [ %v ] with the error: %s", vlandev, err) return } } netlink.LinkSetUp(vlandev) macvlanname, _ := utils.GenerateRandomName("vlan"+vlanid, 5) //create the macvlan device macvlandev := &netlink.Macvlan{ LinkAttrs: netlink.LinkAttrs{ Name: macvlanname, ParentIndex: vlandev.Attrs().Index, }, Mode: netlink.MACVLAN_MODE_BRIDGE, } if err := netlink.LinkAdd(macvlandev); err != nil { log.Warnf("failed to create Macvlan: [ %v ] with the error: %s", macvlandev, err) return } dockerPid := utils.DockerPid(containerName) //the macvlandev can be use directly, don't get netlink.byname again. netlink.LinkSetNsPid(macvlandev, dockerPid) runtime.LockOSThread() defer runtime.UnlockOSThread() //get root network naAddVlannetworkmespace origns, _ := netns.Get() defer origns.Close() //enter the docker container network dockerNS, _ := netns.GetFromPid(dockerPid) defer dockerNS.Close() netns.Set(dockerNS) netlink.LinkSetDown(macvlandev) netlink.LinkSetName(macvlandev, "eth1") _, network, _ := net.ParseCIDR(ss[1]) if _, ok := ipallocs[vlanid]; !ok { log.Fatalf("the ipallocator is null \n") } ip, _ := ipallocs[vlanid].RequestIP(network, nil) ind := strings.LastIndex(ss[1], "/") ipstring := ip.String() + ss[1][ind:] addr, err := netlink.ParseAddr(ipstring) netlink.AddrAdd(macvlandev, addr) netlink.LinkSetUp(macvlandev) /* routes, _ := netlink.RouteList(nil, netlink.FAMILY_V4) for _, r := range routes { if r.Dst == nil { if err := netlink.RouteDel(&r); err != nil { log.Warnf("delete the default error: ", err) } } } if CligwIP == "" { log.Fatal("container gw is null") } defaultRoute := &netlink.Route{ Dst: nil, Gw: net.ParseIP(CligwIP), LinkIndex: macvlandev1.Attrs().Index, } if err := netlink.RouteAdd(defaultRoute); err != nil { log.Warnf("create default route error: ", err) } */ netns.Set(origns) }