Signed-off-by: Flavio Silvestrow <[email protected]>
---
lib/networktables.py | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 150 insertions(+), 0 deletions(-)
create mode 100644 lib/networktables.py
diff --git a/lib/networktables.py b/lib/networktables.py
new file mode 100644
index 0000000..cf3679b
--- /dev/null
+++ b/lib/networktables.py
@@ -0,0 +1,150 @@
+#
+#
+
+# Copyright (C) 2009 Google Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+
+"""Neighbour IPs interface
+
+Module used to update both the Neighbour and Routing table.
+
+Besides adding and removing individual entries, it can also be used to
+add (or replace, if necessary) the entries in a given dictionary with
+src_ip:dest_addr mapping.
+
+"""
+
+
+from ganeti import errors
+from ganeti import utils
+
+
+NEIGHBOUR_CONTEXT = "neigh"
+ROUTING_CONTEXT = "route"
+CONTEXTS = frozenset([NEIGHBOUR_CONTEXT, ROUTING_CONTEXT])
+
+
+def _CheckValidContext(context):
+ """Verify if the context is valid.
+
+ @type context: str
+ @param context: one of CONTEXTS
+
+ @raise errors.ConfigurationError: if a check fails
+
+ """
+ if context not in CONTEXTS:
+ raise errors.ConfigurationError("Invalid context '%s'" % context)
+
+
+def RemoveNetworkEntry(ip_address, context, iface):
+ """Remove an entry in the local Neighbour or Routing table.
+
+ @type ip_address: str
+ @param ip_address: IP address to be updated
+ @type context: str
+ @param context: one of CONTEXTS
+ @type iface: str
+ @param iface: network interface to use
+
+ @raise errors.Commanderror: if an error occurs during removal
+
+ """
+ _CheckValidContext(context)
+ result = utils.RunCmd(["ip", context, "del", ip_address, "dev", iface])
+
+ # Check the command return code.
+ # 0: success
+ # 2: non-existent entry, we're fine with that
+ # something else: unknown, raise error
+ if result.exit_code not in (0, 2):
+ raise errors.CommandError("Can't remove network entry")
+
+
+def UpdateNetworkEntry(ip_address, dest_address, context, iface):
+ """Update (add if inexistant) an entry in the Neigh or Routing table.
+
+ @type ip_address: str
+ @param ip_address: IP address to be updated
+ @type dest_address: str
+ @param dest_address: new destination address
+ @type context: str
+ @param context: one of CONTEXTS
+ @type iface: str
+ @param iface: network interface to use
+
+ @raise errors.CommandError: if an error occurs when updating an entry
+
+ """
+ _CheckValidContext(context)
+
+ # Context-specific args
+ if context == NEIGHBOUR_CONTEXT:
+ dest_token = "lladdr"
+ extra_args = ["nud", "permanent"]
+ else:
+ dest_token = "via"
+
+ result = utils.RunCmd(["ip", context, "replace", ip_address,
+ dest_token, dest_address, "dev", iface,
+ extra_args])
+ if result.failed:
+ raise errors.CommandError("Could not update table, error %s" %
+ result.output)
+
+
+def UpdateNetworkTable(instances, context, iface):
+ """Add or replace the entries in instances in the Neigh|Routing table.
+
+ If the instance's IP is not there, add it.
+
+ @type instances: dict
+ @param instances: dict with instance:dest_address mapping
+ @type context: str
+ @param context: one of CONTEXTS
+ @type iface: str
+ @param iface: network interface to use
+
+ @raise errors.CommandError: if an error occurs when listing a table
+
+ """
+ _CheckValidContext(context)
+ # Check the local table
+ result = utils.RunCmd(["ip", context, "show", "dev", iface])
+ if result.failed:
+ raise errors.CommandError("Could not list table, error %s" %
+ result.output)
+ table = result.output.splitlines()
+
+ # Check if the local entries are up to date.
+ for entry in table:
+ # Skip empty lines
+ if not entry.strip():
+ continue
+ parts = entry.split()
+ # Get the address (first field)
+ src_ip = parts[0]
+ if src_ip in instances:
+ dest_addr = instances[src_ip]
+ UpdateNetworkEntry(src_ip, dest_addr, context, iface)
+
+ # Check the instance list, to make sure we're not missing anything
+ for instance_ip in instances:
+ if instance_ip not in table:
+ UpdateNetworkEntry(instance_ip, instances[instance_ip],
+ context, iface)
--
1.5.4.3