Skip to content

Commit

Permalink
Support lxc in the ip.docker driver
Browse files Browse the repository at this point in the history
The ip.docker has quite a lot of interesting features. Its work
is quite loosely coupled to docker actually, so it's easy to
make it support lxc netns setting up too.

Now this driver is misnamed. A later patch will rename it to
ip.netns instead of ip.docker.
  • Loading branch information
cvaroqui authored and arnaudveron committed Nov 21, 2018
1 parent cf59b09 commit 767881f
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 30 deletions.
10 changes: 9 additions & 1 deletion lib/resContainerLxc.py
Original file line number Diff line number Diff line change
Expand Up @@ -461,10 +461,18 @@ def cni_containerid(self):

def cni_netns(self):
"""
Used by ip.cni
Used by ip.cni and ip.docker
"""
try:
return "/proc/%d/ns/net" % self.get_pid()
except (TypeError, ValueError):
return

def start(self):
resContainer.Container.start(self)
self.svc.sub_set_action("ip", "start", tags=set([self.rid]))

def stop(self):
resContainer.Container.stop(self)
self.svc.sub_set_action("ip", "stop", tags=set([self.rid]))

81 changes: 52 additions & 29 deletions lib/resIpDockerLinux.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def guest_dev(self):
Execute a ip link command in the container net namespace to parse
used eth netdevs.
"""
cmd = [rcEnv.syspaths.nsenter, "--net="+self.sandboxkey, "ip" , "link"]
cmd = [rcEnv.syspaths.nsenter, "--net="+self.netns, "ip" , "link"]
out, err, ret = justcall(cmd)
used = []
for line in out.splitlines():
Expand All @@ -76,7 +76,10 @@ def container(self):
return self.svc.resources_by_id[self.container_rid]

def container_id(self, refresh=False):
return self.svc.dockerlib.get_container_id_by_name(self.container, refresh=refresh)
if self.container.type == "container.lxc":
return self.container.name
else:
return self.svc.dockerlib.get_container_id_by_name(self.container, refresh=refresh)

def arp_announce(self):
""" disable the generic arping. We do that in the guest namespace.
Expand All @@ -91,7 +94,7 @@ def get_docker_ifconfig(self):
if nspid is None:
return

cmd = [rcEnv.syspaths.nsenter, "--net="+self.sandboxkey, "ip", "addr"]
cmd = [rcEnv.syspaths.nsenter, "--net="+self.netns, "ip", "addr"]
out, err, ret = justcall(cmd)
if ret != 0:
return
Expand All @@ -100,7 +103,8 @@ def get_docker_ifconfig(self):
return ifconfig

def abort_start(self):
if not self.container.docker_service:
if not hasattr(self.container, "docker_service") or \
not self.container.docker_service:
return Res.Ip.abort_start(self)
return False

Expand All @@ -127,6 +131,8 @@ def get_docker_interface(self):
return

def container_running_elsewhere(self):
if not hasattr(self.container, "docker_service"):
return False
if not self.container.docker_service:
return False
if len(self.container.service_hosted_instances()) == 0 and \
Expand All @@ -135,12 +141,12 @@ def container_running_elsewhere(self):
return False

def _status(self, verbose=False):
self.unset_lazy("sandboxkey")
self.unset_lazy("netns")
if self.container_running_elsewhere():
self.status_log("%s is hosted by another host" % self.container_rid, "info")
return rcStatus.NA
ret = Res.Ip._status(self)
if self.container.docker_service and ret == rcStatus.DOWN:
if (hasattr(self.container, "docker_service") and self.container.docker_service) and ret == rcStatus.DOWN:
if check_ping(self.addr, timeout=1, count=1):
return rcStatus.STDBY_UP
else:
Expand All @@ -149,8 +155,9 @@ def _status(self, verbose=False):
return ret

def startip_cmd(self):
self.unset_lazy("sandboxkey")
if self.container.docker_service and \
self.unset_lazy("netns")
if hasattr(self.container, "docker_service") and \
self.container.docker_service and \
self._status() != rcStatus.STDBY_DOWN:
return 0, "", ""
if self.container_running_elsewhere():
Expand Down Expand Up @@ -197,26 +204,26 @@ def startip_cmd_dedicated(self):
return ret, out, err

# plumb the ip
cmd = [rcEnv.syspaths.nsenter, "--net="+self.sandboxkey, "ip", "addr", "add", "%s/%s" % (self.addr, to_cidr(self.mask)), "dev", self.guest_dev]
cmd = [rcEnv.syspaths.nsenter, "--net="+self.netns, "ip", "addr", "add", "%s/%s" % (self.addr, to_cidr(self.mask)), "dev", self.guest_dev]
ret, out, err = self.vcall(cmd)
if ret != 0:
return ret, out, err

# activate
cmd = [rcEnv.syspaths.nsenter, "--net="+self.sandboxkey, "ip", "link", "set", self.guest_dev, "up"]
cmd = [rcEnv.syspaths.nsenter, "--net="+self.netns, "ip", "link", "set", self.guest_dev, "up"]
ret, out, err = self.vcall(cmd)
if ret != 0:
return ret, out, err

# add default route
if self.gateway:
cmd = [rcEnv.syspaths.nsenter, "--net="+self.sandboxkey, "ip", "route", "add", "default", "via", self.gateway, "dev", self.guest_dev]
cmd = [rcEnv.syspaths.nsenter, "--net="+self.netns, "ip", "route", "add", "default", "via", self.gateway, "dev", self.guest_dev]
ret, out, err = self.vcall(cmd)
if ret != 0:
return ret, out, err

# announce
cmd = [rcEnv.syspaths.nsenter, "--net="+self.sandboxkey, os.path.join(rcEnv.paths.pathlib, "arp.py"), self.guest_dev, self.addr]
cmd = [rcEnv.syspaths.nsenter, "--net="+self.netns, os.path.join(rcEnv.paths.pathlib, "arp.py"), self.guest_dev, self.addr]
self.log.info(" ".join(cmd))
out, err, ret = justcall(cmd)

Expand Down Expand Up @@ -266,13 +273,13 @@ def startip_cmd_shared_ovs(self):
return ret, out, err

# rename the tmp guest dev
cmd = [rcEnv.syspaths.nsenter, "--net="+self.sandboxkey, "ip", "link", "set", tmp_guest_dev, "name", self.guest_dev]
cmd = [rcEnv.syspaths.nsenter, "--net="+self.netns, "ip", "link", "set", tmp_guest_dev, "name", self.guest_dev]
ret, out, err = self.vcall(cmd)
if ret != 0:
return ret, out, err

# plumb ip
cmd = [rcEnv.syspaths.nsenter, "--net="+self.sandboxkey, "ip", "addr", "add", self.addr+"/"+to_cidr(self.mask), "dev", self.guest_dev]
cmd = [rcEnv.syspaths.nsenter, "--net="+self.netns, "ip", "addr", "add", self.addr+"/"+to_cidr(self.mask), "dev", self.guest_dev]
ret, out, err = self.vcall(cmd)
if ret != 0:
return ret, out, err
Expand Down Expand Up @@ -312,13 +319,13 @@ def startip_cmd_shared_bridge(self):
return ret, out, err

# rename the tmp guest dev
cmd = [rcEnv.syspaths.nsenter, "--net="+self.sandboxkey, "ip", "link", "set", tmp_guest_dev, "name", self.guest_dev]
cmd = [rcEnv.syspaths.nsenter, "--net="+self.netns, "ip", "link", "set", tmp_guest_dev, "name", self.guest_dev]
ret, out, err = self.vcall(cmd)
if ret != 0:
return ret, out, err

# plumb ip
cmd = [rcEnv.syspaths.nsenter, "--net="+self.sandboxkey, "ip", "addr", "add", self.addr+"/"+to_cidr(self.mask), "dev", self.guest_dev]
cmd = [rcEnv.syspaths.nsenter, "--net="+self.netns, "ip", "addr", "add", self.addr+"/"+to_cidr(self.mask), "dev", self.guest_dev]
ret, out, err = self.vcall(cmd)
if ret != 0:
return ret, out, err
Expand Down Expand Up @@ -354,13 +361,13 @@ def startip_cmd_shared_ipvlan(self, mode):
return ret, out, err

# rename the tmp guest dev
cmd = [rcEnv.syspaths.nsenter, "--net="+self.sandboxkey, "ip", "link", "set", tmp_guest_dev, "name", self.guest_dev]
cmd = [rcEnv.syspaths.nsenter, "--net="+self.netns, "ip", "link", "set", tmp_guest_dev, "name", self.guest_dev]
ret, out, err = self.vcall(cmd)
if ret != 0:
return ret, out, err

# plumb the ip
cmd = [rcEnv.syspaths.nsenter, "--net="+self.sandboxkey, "ip", "addr", "add", "%s/%s" % (self.addr, to_cidr(self.mask)), "dev", self.guest_dev]
cmd = [rcEnv.syspaths.nsenter, "--net="+self.netns, "ip", "addr", "add", "%s/%s" % (self.addr, to_cidr(self.mask)), "dev", self.guest_dev]
ret, out, err = self.vcall(cmd)
if ret != 0:
return ret, out, err
Expand Down Expand Up @@ -396,13 +403,13 @@ def startip_cmd_shared_macvlan(self):
return ret, out, err

# rename the tmp guest dev
cmd = [rcEnv.syspaths.nsenter, "--net="+self.sandboxkey, "ip", "link", "set", tmp_guest_dev, "name", self.guest_dev]
cmd = [rcEnv.syspaths.nsenter, "--net="+self.netns, "ip", "link", "set", tmp_guest_dev, "name", self.guest_dev]
ret, out, err = self.vcall(cmd)
if ret != 0:
return ret, out, err

# plumb the ip
cmd = [rcEnv.syspaths.nsenter, "--net="+self.sandboxkey, "ip", "addr", "add", "%s/%s" % (self.addr, to_cidr(self.mask)), "dev", self.guest_dev]
cmd = [rcEnv.syspaths.nsenter, "--net="+self.netns, "ip", "addr", "add", "%s/%s" % (self.addr, to_cidr(self.mask)), "dev", self.guest_dev]
ret, out, err = self.vcall(cmd)
if ret != 0:
return ret, out, err
Expand All @@ -423,33 +430,33 @@ def ip_get_mtu(self):
return mtu

def ip_setup_route(self):
cmd = [rcEnv.syspaths.nsenter, "--net="+self.sandboxkey, "ip", "route", "del", "default"]
cmd = [rcEnv.syspaths.nsenter, "--net="+self.netns, "ip", "route", "del", "default"]
ret, out, err = self.call(cmd, errlog=False)

cmd = [rcEnv.syspaths.nsenter, "--net="+self.sandboxkey, "ip", "link", "set", self.guest_dev, "up"]
cmd = [rcEnv.syspaths.nsenter, "--net="+self.netns, "ip", "link", "set", self.guest_dev, "up"]
ret, out, err = self.vcall(cmd)
if ret != 0:
return ret, out, err

if self.gateway:
cmd = [rcEnv.syspaths.nsenter, "--net="+self.sandboxkey, "ip", "route", "replace", "default", "via", self.gateway]
cmd = [rcEnv.syspaths.nsenter, "--net="+self.netns, "ip", "route", "replace", "default", "via", self.gateway]
ret, out, err = self.vcall(cmd)
if ret != 0:
return ret, out, err
else:
cmd = [rcEnv.syspaths.nsenter, "--net="+self.sandboxkey, "ip", "route", "replace", "default", "dev", self.guest_dev]
cmd = [rcEnv.syspaths.nsenter, "--net="+self.netns, "ip", "route", "replace", "default", "dev", self.guest_dev]
ret, out, err = self.vcall(cmd)
if ret != 0:
return ret, out, err

if self.del_net_route and self.network:
cmd = [rcEnv.syspaths.nsenter, "--net="+self.sandboxkey, "ip", "route", "del", self.network+"/"+to_cidr(self.mask), "dev", self.guest_dev]
cmd = [rcEnv.syspaths.nsenter, "--net="+self.netns, "ip", "route", "del", self.network+"/"+to_cidr(self.mask), "dev", self.guest_dev]
ret, out, err = self.vcall(cmd)
if ret != 0:
return ret, out, err

# announce
cmd = [rcEnv.syspaths.nsenter, "--net="+self.sandboxkey, os.path.join(rcEnv.paths.pathlib, "arp.py"), self.guest_dev, self.addr]
cmd = [rcEnv.syspaths.nsenter, "--net="+self.netns, os.path.join(rcEnv.paths.pathlib, "arp.py"), self.guest_dev, self.addr]
self.log.info(" ".join(cmd))
out, err, ret = justcall(cmd)

Expand All @@ -462,6 +469,15 @@ def ip_wait(self):
raise ex.excError("timed out waiting for ip activation")

def get_nspid(self):
if self.container.type == "container.docker":
return self.get_nspid_docker()
elif self.container.type == "container.lxc":
return self.get_nspid_lxc()

def get_nspid_lxc(self):
return str(self.container.get_pid())

def get_nspid_docker(self):
container_id = self.container_id(refresh=True)
if container_id is None:
return
Expand All @@ -477,6 +493,13 @@ def get_nspid(self):
return nspid

@lazy
def netns(self):
if self.container.type == "container.docker":
return self.sandboxkey()
elif self.container.type == "container.lxc":
return self.container.cni_netns()
raise ex.excError("unsupported container type: %s" % self.container.type)

def sandboxkey(self):
container_id = self.container_id(refresh=True)
if container_id is None:
Expand All @@ -498,15 +521,15 @@ def stopip_cmd(self):
raise ex.excContinueAction("can't find on which interface %s is plumbed in container %s" % (self.addr, self.container_id()))
if self.mask is None:
raise ex.excContinueAction("netmask is not set")
cmd = [rcEnv.syspaths.nsenter, "--net="+self.sandboxkey, "ip", "addr", "del", self.addr+"/"+to_cidr(self.mask), "dev", intf]
cmd = [rcEnv.syspaths.nsenter, "--net="+self.netns, "ip", "addr", "del", self.addr+"/"+to_cidr(self.mask), "dev", intf]
ret, out, err = self.vcall(cmd)
cmd = [rcEnv.syspaths.nsenter, "--net="+self.sandboxkey, "ip", "link", "del", "dev", intf]
cmd = [rcEnv.syspaths.nsenter, "--net="+self.netns, "ip", "link", "del", "dev", intf]
ret, out, err = self.vcall(cmd)

if self.mode == "ovs":
self.log.info("ovs mode")
ret, out, err = self.stopip_cmd_shared_ovs()

self.unset_lazy("sandboxkey")
self.unset_lazy("netns")
return ret, out, err

0 comments on commit 767881f

Please sign in to comment.