---
 lib/networktables.py |  108 +++++++++++++++++++++++++++++++++++--------------
 1 files changed, 77 insertions(+), 31 deletions(-)

diff --git a/lib/networktables.py b/lib/networktables.py
index f2006e0..585405f 100644
--- a/lib/networktables.py
+++ b/lib/networktables.py
@@ -1,6 +1,23 @@
 #
 #
+
 # Copyright 2009 Google Inc. All Rights Reserved.
+#
+# 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
 
@@ -10,7 +27,6 @@ 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.
 
-
 """
 
 
@@ -18,79 +34,109 @@ from ganeti import errors
 from ganeti import utils
 
 
-NEIGHBOUR = 'neigh'
-ROUTING = 'route'
+NEIGHBOUR_CONTEXT = 'neigh'
+ROUTING_CONTEXT = 'route'
+CONTEXTS = frozenset([NEIGHBOUR_CONTEXT, ROUTING_CONTEXT])
 
 
-def RemoveNetworkEntry(ip_address, context, iface):
+def _CheckValidContext(context):
+  """Verify if the context is valid.
+
+  @type context: str
+  @param context: one of CONTEXTS
+
+  @raise errors.ConfigurationError: if a check fails
   """
-  Remove an entry in the local Neighbour or Routing table.
+  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: NEIGHBOUR or ROUTING
+  @param context: one of CONTEXTS
   @type iface: str
   @param iface: network interface to use
-  """
 
-  # This command returns an error when asked to remove a non-existent
-  # address. We don't care about that, so no need to raise an error
-  # here.
-  cmd = 'ip %s del %s dev %s' % (context, ip_address, iface)
-  result = utils.RunCmd(cmd)
+  @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 == 0) or (result.exit_code == 2):
+    pass
+  else:
+    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.
+  """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: NEIGHBOUR or ROUTING
+  @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
+
   """
-  
-  args = (ip_address, dest_address, iface)
-  if context == ROUTING:
-    cmd = 'ip route replace %s via %s dev %s' % args
+  _CheckValidContext(context)
+
+  # Context-specific args
+  if context == NEIGHBOUR_CONTEXT:
+    dest_token = "lladdr"
+    extra_args = ["nud", "permanent"]
   else:
-    cmd = 'ip neigh replace %s lladdr %s dev %s nud permanent' % args
+    dest_token = "via"
 
-  result = utils.RunCmd(cmd)
+  result = utils.RunCmd(["ip", context, "replace", ip_address,
+                         dest_token, dest_address, "dev", iface,
+                         extra_args])
   if result.failed:
-    raise errors.OpExecError("Could not update table, error %s" %
-                             result.output)
+    raise errors.CommandError("Could not update table, error %s" %
+                               result.output)
 
 
 def UpdateNetworkTable(instances, context, iface):
-  """
-  Add (or replace) the entries in instance_list to the Neigh|Routing table.
+  """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: NEIGHBOUR or ROUTING
+  @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
-  cmd = 'ip %s show dev %s' % (context, iface)
-  result = utils.RunCmd(cmd)
-  table = result.output.split('\n')
+  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()
   # Remove newline entry at the end
   table.pop()
 
   # Check if the local entries are up to date.
   for entry in table:
-    parts = entry.split(' ')
+    parts = entry.split()
     # Get the address (first field)
     src_ip = parts[0]
     if src_ip in instances:
-- 
1.5.4.3

Reply via email to