Change in vdsm[master]: WIP: Multiple Gateways Feature http://www.ovirt.org/Features...
amuller at redhat.com
amuller at redhat.com
Thu May 30 14:28:52 UTC 2013
Assaf Muller has uploaded a new change for review.
Change subject: WIP: Multiple Gateways Feature http://www.ovirt.org/Features/Multiple_Gateways
......................................................................
WIP: Multiple Gateways Feature
http://www.ovirt.org/Features/Multiple_Gateways
* The module currently works from the command line.
* For DHCP interfaces, a manually placed file in /etc/dhcp calls
this script whenever the interface goes up or down.
* For static interfaces, this module will be imported in vdsm code
and used as such: Create an instance of the class and call up
or down.
TODO - Improve multipleGateways.py implementation:
* Build a lightweight library to parse ip route and ip rule output
* Change from using print to logging - With either stdout for cmd,
or vdsm log file when importing
* Use a library to deal with command line arguments
TODO - Usage of multipleGateways.py:
* Add the 'netaddr' Python library as a VDSM depedency
* Add the file to the list of files installed in /usr/share/vdsm
* Use it during addNetwork, delNetwork for static interfaces
* For DHCP interfaces - Create and delete the hook files in
/etc/dhcp
Change-Id: I0224d896724b9cdc44215e92f0da0be71fd19038
Signed-off-by: Assaf Muller <amuller at redhat.com>
---
A vdsm/multipleGateways.py
1 file changed, 161 insertions(+), 0 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/07/15207/1
diff --git a/vdsm/multipleGateways.py b/vdsm/multipleGateways.py
new file mode 100644
index 0000000..231e971
--- /dev/null
+++ b/vdsm/multipleGateways.py
@@ -0,0 +1,161 @@
+import os
+import sys
+import netaddr
+from vdsm import utils
+
+
+NETWORK_SCRIPTS = '/etc/sysconfig/network-scripts/'
+
+
+class MultipleGatewaysConfigurator(object):
+ def __init__(self, isStatic, device):
+ self.isStatic = isStatic
+ self.device = device
+
+ def _generateTableId(self):
+ #TODO: Future proof for IPv6
+ return self.ip.value
+
+ def _buildRoutes(self):
+ return ["default via %s dev %s table %s" %
+ (self.gateway, self.device, self.table),
+ "%s via %s dev %s table %s" %
+ (self.network, self.ip, self.device, self.table)]
+
+ def _buildRules(self):
+ return ["from %s table %s" % (self.network, self.table),
+ "to %s table %s" % (self.network, self.table)]
+
+ def _writeCommands(self, commands, type='route'):
+ filePath = NETWORK_SCRIPTS + '%s-%s' % (type, self.device)
+ with open(filePath, 'w') as file:
+ for command in commands:
+ file.write(command + '\n')
+
+ def _addRoutesStatic(self, routes):
+ self._writeCommands(routes, type='route')
+
+ def _addRulesStatic(self, rules):
+ self._writeCommands(rules, type='rule')
+
+ def _runCommands(self, commands):
+ for command in commands:
+ utils.execCmd(command.split())
+
+ def _addRoutesDHCP(self, routes):
+ routes = ['ip route add ' + route for route in routes]
+ self._runCommands(routes)
+
+ def _addRulesDHCP(self, rules):
+ rules = ['ip rule add ' + rule for rule in rules]
+ self._runCommands(rules)
+
+ def up(self, ip, mask, gateway):
+ try:
+ self.ip = netaddr.IPAddress(ip)
+ self.mask = netaddr.IPAddress(mask)
+ self.gateway = netaddr.IPAddress(gateway)
+ except netaddr.core.AddrFormatError:
+ print ("IP, subnet mask or gateway not properly formatted.")
+ return
+ self.table = self._generateTableId()
+ network = netaddr.IPNetwork(str(self.ip) + '/' + str(self.mask))
+ self.network = "%s/%s" % (network.network, network.prefixlen)
+
+ print (("Bringing up - ip: %s, network: %s, subnet: %s " +
+ "gateway: %s, table: %s, device: %s") %
+ (self.ip, self.network, self.mask, self.gateway, self.table,
+ self.device))
+
+ routes = self._buildRoutes()
+ rules = self._buildRules()
+
+ if self.isStatic:
+ self._addRoutesStatic(routes)
+ self._addRulesStatic(rules)
+ else:
+ self._addRoutesDHCP(routes)
+ self._addRulesDHCP(rules)
+
+ def _delTable(self, table):
+ command = "/sbin/ip route show table".split()
+ command.append(table)
+ _, output, _ = utils.execCmd(command)
+ commands = ["/sbin/ip route del %s table %s"
+ % (line.strip(), table) for line in output if line]
+ self._runCommands(commands)
+
+ def _delRulesDHCP(self, rules):
+ rules = ['ip rule del ' + rule for rule in rules]
+ self._runCommands(rules)
+
+ def _getTable(self, rule):
+ return rule.split()[-1] if rule else None
+
+ def _getRules(self, network):
+ _, output, _ = utils.execCmd("/sbin/ip rule".split())
+ relevantLines = [line for line in output if network in line]
+ rules = [line.split(":")[1].strip() for line in relevantLines]
+ return rules
+
+ def _getNetwork(self, device):
+ _, output, _ = utils.execCmd(["/sbin/ip", "route"])
+ relevantLines = [line for line in output if self.device in line]
+
+ entry = relevantLines[0] if relevantLines else None
+ if entry:
+ network = entry.split()[0]
+ return network
+ else:
+ print "Network for given device name not found."
+ return None
+
+ def _delRoutesStatic(self):
+ os.remove(NETWORK_SCRIPTS + 'route-%s' % self.device)
+
+ def _delRulesStatic(self):
+ os.remove(NETWORK_SCRIPTS + 'rule-%s' % self.device)
+
+ def down(self):
+ print ("Bringing down - device: %s" % self.device)
+
+ if self.isStatic:
+ self._delRoutesStatic()
+ self._delRulesStatic()
+ else:
+ network = self._getNetwork(self.device)
+ rules = self._getRules(network)
+ table = self._getTable(rules[0])
+ self._delRulesDHCP(rules)
+ self._delTable(table)
+
+
+def main():
+ if (len(sys.argv) < 3 or
+ (((sys.argv[1] not in ('up', 'down')) or
+ sys.argv[2] not in ('static', 'dhcp'))) or
+ (sys.argv[1] == 'up' and len(sys.argv) != 7) or
+ (sys.argv[1] == 'down' and len(sys.argv) != 4)):
+ print ("Usage: %s up static/dhcp <ip> <mask> <gateway> <device>" %
+ sys.argv[0])
+ print ("Usage: %s down static/dhcp <device>" %
+ sys.argv[0])
+ sys.exit(1)
+
+ isUp = True if sys.argv[1] == 'up' else False
+ isStatic = True if sys.argv[2] == 'static' else False
+ device = sys.argv[6] if isUp else sys.argv[3]
+
+ gateways = MultipleGatewaysConfigurator(isStatic, device)
+
+ if isUp:
+ ip = sys.argv[3]
+ mask = sys.argv[4]
+ gateway = sys.argv[5]
+ gateways.up(ip, mask, gateway)
+ else:
+ gateways.down()
+
+
+if __name__ == "__main__":
+ main()
--
To view, visit http://gerrit.ovirt.org/15207
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I0224d896724b9cdc44215e92f0da0be71fd19038
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Assaf Muller <amuller at redhat.com>
More information about the vdsm-patches
mailing list