Hopefully it's good to go now. Sending full patch.

Signed-off-by: Flavio Silvestrow <[email protected]>
---
 lib/networktables.py |  154 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 154 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..d967000
--- /dev/null
+++ b/lib/networktables.py
@@ -0,0 +1,154 @@
+#
+#
+
+# 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 as ganeti_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 L{ganeti.errors.ParameterError}: invalid context
+
+  """
+  if context not in CONTEXTS:
+    raise ganeti_errors.ParameterError("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 L{ganeti.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 ganeti_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 L{ganeti.errors.CommandError}: if 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"
+    extra_args = []
+
+  cmd = ["ip", context, "replace", ip_address, dest_token, dest_address,
+         "dev", iface]
+
+  if extra_args:
+    cmd.extend(extra_args)
+  result = utils.RunCmd(cmd)
+  if result.failed:
+    raise ganeti_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 L{ganeti.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 ganeti_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

Reply via email to