Skip to content

Commit

Permalink
Add support for fixed ip interface names on linux
Browse files Browse the repository at this point in the history
Use the macvtap link type for that.

For example, with this resource configuration:

[ip#0]
ipname = 10.24.0.20
netmask = 24
ipdev = foo@eth0
alias = false

A start executes:

  /sbin/ip link add link eth0 name foo type macvtap
  /sbin/ip link set dev foo up
  /sbin/ip addr add 10.24.0.20/24 dev foo
  send gratuitous arp to announce 10.24.0.20 is at foo
  • Loading branch information
cvaroqui committed Jan 29, 2021
1 parent 7f689d4 commit f6e55ab
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 4 deletions.
22 changes: 19 additions & 3 deletions opensvc/drivers/resource/ip/__init__.py
Expand Up @@ -32,7 +32,7 @@
"keyword": "ipdev",
"at": True,
"required": True,
"text": "The interface name over which OpenSVC will try to stack the service ip. Can be different from one node to the other, in which case the ``@nodename`` can be specified. If the value is expressed as '<intf>:<alias>, the stacked interface index is forced to <alias> instead of the lowest free integer."
"text": "The interface name over which OpenSVC will try to stack the service ip. Can be different from one node to the other, in which case the ``@nodename`` can be specified. If the value is expressed as '<intf>:<alias>, the stacked interface index is forced to <alias> instead of the lowest free integer. If the value is expressed as <name>@<intf>, a macvtap interface named <name> is created and attached to <intf>."
}
KW_NETMASK = {
"keyword": "netmask",
Expand Down Expand Up @@ -163,13 +163,20 @@ def __init__(self,
provisioner=None,
**kwargs):
super(Ip, self).__init__(type=type, **kwargs)
self.ipdev = ipdev.split(":", 1)[0]
self.forced_stacked_dev = None
self.base_ipdev = None
if ":" in ipdev:
self.ipdev = ipdev.split(":", 1)[0]
self.forced_stacked_dev = ipdev
elif "@" in ipdev:
self.ipdev, self.base_ipdev = ipdev.split("@", 1)
else:
self.ipdev = ipdev
self.ipname = ipname
self.netmask = netmask
self.gateway = gateway
self.lockfd = None
self.stacked_dev = None
self.forced_stacked_dev = ipdev if ":" in ipdev else None
self.addr = None
self.expose = expose
self.check_carrier = check_carrier
Expand Down Expand Up @@ -384,6 +391,12 @@ def abort_start(self):
return True
return False

def add_link(self):
pass

def del_link(self):
pass

def start_link(self):
"""
Start the ipdev link.
Expand Down Expand Up @@ -470,6 +483,7 @@ def allow_start(self):
if self.is_up() is True:
self.log.info("%s is already up on %s", self.addr, self.ipdev)
raise ex.IpAlreadyUp(self.addr)
self.add_link()
ifconfig = self.get_ifconfig()
intf = ifconfig.interface(self.ipdev)
if self.has_carrier(intf) is False and not self.svc.options.force:
Expand Down Expand Up @@ -726,6 +740,8 @@ def stop(self):
self.log.error("%s refuse to go down", self.addr)
raise ex.Error

self.del_link()

def allocate(self):
"""
Request an ip in the ipdev network from the collector.
Expand Down
37 changes: 36 additions & 1 deletion opensvc/drivers/resource/ip/host/linux.py
Expand Up @@ -4,7 +4,7 @@
from .. import Ip
from env import Env
from utilities.net.converters import to_cidr, to_dotted
from utilities.proc import which
from utilities.proc import which, justcall

DRIVER_GROUP = "ip"
DRIVER_BASENAME = "host"
Expand All @@ -14,6 +14,38 @@ def check_ping(self, count=1, timeout=5):
self.log.info("checking %s availability (%ss)", self.addr, timeout)
return utilities.ping.check_ping(self.addr, timeout=timeout, count=count)

def has_macvtap_link(self):
cmd = [Env.syspaths.ip, "link", "ls", "dev", self.ipdev]
out, err, ret = justcall(cmd)
mark = "%s@%s" % (self.ipdev, self.base_ipdev)
return ret == 0 and mark in out

def del_macvtap_link(self):
if not self.base_ipdev:
return
if not self.has_macvtap_link():
return
cmd = [Env.syspaths.ip, "link", "del", "link", self.base_ipdev, "name", self.ipdev, "type", "macvtap"]
ret, out, err = self.vcall(cmd)
if ret:
raise ex.Error

def add_macvtap_link(self):
if not self.base_ipdev:
return
if self.has_macvtap_link():
return
cmd = [Env.syspaths.ip, "link", "add", "link", self.base_ipdev, "name", self.ipdev, "type", "macvtap"]
ret, out, err = self.vcall(cmd)
if ret:
raise ex.Error

def add_link(self):
self.add_macvtap_link()

def del_link(self):
self.del_macvtap_link()

def start_link(self):
if which(Env.syspaths.ip):
cmd = [Env.syspaths.ip, 'link', 'set', 'dev', self.ipdev, 'up']
Expand All @@ -23,6 +55,9 @@ def start_link(self):
if ret != 0:
return ret, out, err

def stop_link(self):
self.del_macvtap_link()

def startip_cmd(self):
if which("ifconfig") and self.alias:
if ':' in self.addr:
Expand Down

0 comments on commit f6e55ab

Please sign in to comment.