On Thu, Sep 17, 2009 at 5:34 PM, Flavio Silvestrow
<[email protected]> wrote:
>
> 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

we could do perhaps
from ganeti import errors as ganeti_errors
and
from nbma import errors (see below)
so we can define our own 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)
> +

ConfigurationError is used to symbolize an error in the Ganeti configuration.
We should really use separate errors, in nbma!

> +
> +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)

LGTM for the rest!!

Thanks,

Guido

Reply via email to