mirror of
				https://github.com/CumulusNetworks/ifupdown2.git
				synced 2024-05-06 15:54:50 +00:00 
			
		
		
		
	python-ifupdown initial checkin
Ticket: CM-1438 Reviewed By: TBD Testing Done: - Will checkin build files after some more testing and performance numbers. It will go into the testing repo for 2.0 - All TODO items are part of the checked in TODO file
This commit is contained in:
		
							
								
								
									
										39
									
								
								README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								README
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
python-ifupdown2
 | 
			
		||||
================
 | 
			
		||||
 | 
			
		||||
This package is a replacement for the debian ifupdown package.
 | 
			
		||||
It is completely re-written in python. It maintains the original ifupdown
 | 
			
		||||
pluggable architecture and extends it further.
 | 
			
		||||
 | 
			
		||||
The python-ifupdown2 package provides the infrastructure for
 | 
			
		||||
parsing /etc/network/interfaces file, loading, scheduling and state
 | 
			
		||||
management of interfaces.
 | 
			
		||||
 | 
			
		||||
It dynamically loads python modules from /usr/share/ifupdownmodules (provided
 | 
			
		||||
 by the python-ifupdown2-addons package). To remain compatible with other
 | 
			
		||||
packages that depend on ifupdown, it also executes scripts under /etc/network/.
 | 
			
		||||
To make the transition smoother, a python module under
 | 
			
		||||
/usr/share/ifupdownmodules will override a script by the same name under
 | 
			
		||||
/etc/network/.
 | 
			
		||||
 | 
			
		||||
It publishes an interface object which is passed to all loadble python
 | 
			
		||||
modules (more details about the interface object is available in the
 | 
			
		||||
python docs).
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
pluggable python modules:
 | 
			
		||||
=========================
 | 
			
		||||
Unlike original ifupdown, all interface configuration is moved to external
 | 
			
		||||
python modules. That includes inet, inet6 and dhcp configurations.
 | 
			
		||||
 | 
			
		||||
It expects a few things from the pluggable modules:
 | 
			
		||||
- the module should implement a class by the same name
 | 
			
		||||
- the interface object (class iface) and the operation to be performed is
 | 
			
		||||
  passed to the modules
 | 
			
		||||
- the python class should provide a few methods:
 | 
			
		||||
	- run() : method to configure the interface.
 | 
			
		||||
	- get_ops() : must return a list of operations it supports.
 | 
			
		||||
		eg: 'pre-up', 'post-down'
 | 
			
		||||
	- get_dependent_ifacenames() : must return a list of interfaces the
 | 
			
		||||
	  interface is dependent on. This is used to build the dependency list
 | 
			
		||||
	  for sorting and executing interfaces in parallel.
 | 
			
		||||
							
								
								
									
										19
									
								
								TODO
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								TODO
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
TODO:
 | 
			
		||||
====
 | 
			
		||||
- support for /etc/networking.defaults
 | 
			
		||||
- Implement the ifupdown interface mapping feature
 | 
			
		||||
- Fix parallel implementation
 | 
			
		||||
- Test all original ifupdown options for compatibility
 | 
			
		||||
- Test scale
 | 
			
		||||
- Test with ifupdown-extra, ifmetric, ifupdown-scripts-zg2
 | 
			
		||||
- export other environment variables to scripts:
 | 
			
		||||
	IFACE  physical name of the interface being processed
 | 
			
		||||
        LOGICAL logical name of the interface being processed
 | 
			
		||||
        ADDRFAM address family of the interface
 | 
			
		||||
        METHOD method of the interface (e.g., static)
 | 
			
		||||
        MODE   start if run from ifup, stop if run from ifdown
 | 
			
		||||
        PHASE  as per MODE, but with finer granularity, distinguishing the pre-
 | 
			
		||||
               up, post-up, pre-down and post-down phases.
 | 
			
		||||
        VERBOSITY indicates  whether --verbose was used; set to 1 if so, 0 if not.
 | 
			
		||||
        PATH   the  command   search   path:   /usr/local/sbin:/usr/local/bin:‐
 | 
			
		||||
               /usr/sbin:/usr/bin:/sbin:/bin
 | 
			
		||||
							
								
								
									
										67
									
								
								debian/python-ifupdown2.postinst
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								debian/python-ifupdown2.postinst
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,67 @@
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
MYNAME="${0##*/}"
 | 
			
		||||
 | 
			
		||||
report() { echo "${MYNAME}: $*" ; }
 | 
			
		||||
report_warn() { report "Warning: $*" >&2 ; }
 | 
			
		||||
report_err() { report "Error: $*" >&2 ; }
 | 
			
		||||
 | 
			
		||||
case "$1" in
 | 
			
		||||
    configure)
 | 
			
		||||
        # Create /etc/network/run 
 | 
			
		||||
        [ -d /run/network ] || mkdir -p /run/network
 | 
			
		||||
 | 
			
		||||
        # for backward compatibility
 | 
			
		||||
        ln -sf /run/network /etc/network/run
 | 
			
		||||
 | 
			
		||||
        [ -d /etc/network/if-pre-up.d ] || mkdir -p /etc/network/if-pre-up.d
 | 
			
		||||
        [ -d /etc/network/if-up.d ] || mkdir -p /etc/network/if-up.d
 | 
			
		||||
        [ -d /etc/network/if-post-up.d ] || mkdir -p /etc/network/if-post-up.d
 | 
			
		||||
 | 
			
		||||
        [ -d /etc/network/if-pre-down.d ] || mkdir -p /etc/network/if-pre-down.d
 | 
			
		||||
        [ -d /etc/network/if-down.d ] || mkdir -p /etc/network/if-down.d
 | 
			
		||||
        [ -d /etc/network/if-post-down.d ] || mkdir -p /etc/network/if-post-down.d
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        # Generic stuff done on all configurations
 | 
			
		||||
        if [ -f /etc/network/interfaces ] ; then
 | 
			
		||||
            # TODO: This should be handled with debconf and the script
 | 
			
		||||
            # could introduce the line there directly
 | 
			
		||||
            if ! grep -q "^[[:space:]]*iface[[:space:]]\+lo0\?[[:space:]]\+inet[[:space:]]\+loopback\>" /etc/network/interfaces ; then
 | 
			
		||||
                report_warn "No 'iface lo' definition found in /etc/network/interfaces"
 | 
			
		||||
            fi
 | 
			
		||||
 | 
			
		||||
            if ! grep -q "^[[:space:]]*\(allow-\|\)auto[[:space:]]\+\(.*[[:space:]]\+\|\)lo0\?\([[:space:]]\+\|$\)" /etc/network/interfaces ; then
 | 
			
		||||
                report_warn "No 'auto lo' statement found in /etc/network/interfaces"
 | 
			
		||||
            fi
 | 
			
		||||
        else  # ! -f /etc/network/interfaces
 | 
			
		||||
            if [ -z "$2" ]; then
 | 
			
		||||
                echo "Creating /etc/network/interfaces."
 | 
			
		||||
                echo "# interfaces(5) file used by ifup(8) and ifdown(8)" > /etc/network/interfaces
 | 
			
		||||
                echo "auto lo" >> /etc/network/interfaces
 | 
			
		||||
                    echo "iface lo inet loopback" >> /etc/network/interfaces
 | 
			
		||||
            else
 | 
			
		||||
                    report_warn "/etc/network/interfaces does not exist"
 | 
			
		||||
            fi
 | 
			
		||||
        fi
 | 
			
		||||
 | 
			
		||||
        [ -e /sbin/ifup ] || ln -s /sbin/ifupdown /sbin/ifup
 | 
			
		||||
        [ -e /sbin/ifdown ] || ln -s /sbin/ifupdown /sbin/ifdown
 | 
			
		||||
        [ -e /sbin/ifquery ] || ln -s /sbin/ifupdown /sbin/ifquery
 | 
			
		||||
        ;;
 | 
			
		||||
 | 
			
		||||
  purge)
 | 
			
		||||
    # Note: We don't remove /etc/network/interfaces
 | 
			
		||||
    rm -f /run/network/ifstate
 | 
			
		||||
    rm -f /sbin/ifquery
 | 
			
		||||
    rm -f /sbin/ifup
 | 
			
		||||
    rm -f /sbin/ifdown
 | 
			
		||||
    ;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
if [ -x "/etc/init.d/networking" ]; then
 | 
			
		||||
    update-rc.d networking start 40 S . start 35 0 6 . >/dev/null || exit $?
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
#DEBHELPER#
 | 
			
		||||
							
								
								
									
										20
									
								
								debian/python-ifupdown2.postrm
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								debian/python-ifupdown2.postrm
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
case "$1" in
 | 
			
		||||
  purge)
 | 
			
		||||
    # Note: We don't remove /etc/network/interfaces
 | 
			
		||||
    rm -f /etc/network/run/ifstate
 | 
			
		||||
 | 
			
		||||
    if [ -L /etc/network/run ] ; then
 | 
			
		||||
      rm -f /etc/network/run
 | 
			
		||||
    elif [ -d /etc/network/run ] ; then
 | 
			
		||||
      rmdir --ignore-fail-on-non-empty /etc/network/run
 | 
			
		||||
    fi
 | 
			
		||||
    ;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
if [ "$1" = "purge" ] ; then
 | 
			
		||||
    update-rc.d networking remove >/dev/null
 | 
			
		||||
fi
 | 
			
		||||
							
								
								
									
										194
									
								
								init.d/networking
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								init.d/networking
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,194 @@
 | 
			
		||||
#!/bin/sh -e
 | 
			
		||||
### BEGIN INIT INFO
 | 
			
		||||
# Provides:          networking ifupdown
 | 
			
		||||
# Required-Start:    mountkernfs $local_fs urandom
 | 
			
		||||
# Required-Stop:     $local_fs
 | 
			
		||||
# Default-Start:     S
 | 
			
		||||
# Default-Stop:      0 6
 | 
			
		||||
# Short-Description: Raise network interfaces.
 | 
			
		||||
# Description:       Prepare /run/network directory, ifstate file and raise network interfaces, or take them down.
 | 
			
		||||
### END INIT INFO
 | 
			
		||||
 | 
			
		||||
PATH="/sbin:/bin"
 | 
			
		||||
RUN_DIR="/run/network"
 | 
			
		||||
IFSTATE="$RUN_DIR/ifstate"
 | 
			
		||||
 | 
			
		||||
[ -x /sbin/ifup ] || exit 0
 | 
			
		||||
[ -x /sbin/ifdown ] || exit 0
 | 
			
		||||
 | 
			
		||||
. /lib/lsb/init-functions
 | 
			
		||||
 | 
			
		||||
CONFIGURE_INTERFACES=yes
 | 
			
		||||
EXCLUDE_INTERFACES=
 | 
			
		||||
VERBOSE=no
 | 
			
		||||
 | 
			
		||||
[ -f /etc/default/networking ] && . /etc/default/networking
 | 
			
		||||
 | 
			
		||||
[ "$VERBOSE" = yes ] && verbose=-v
 | 
			
		||||
 | 
			
		||||
process_exclusions() {
 | 
			
		||||
    set -- $EXCLUDE_INTERFACES
 | 
			
		||||
    exclusions=""
 | 
			
		||||
    for d
 | 
			
		||||
    do
 | 
			
		||||
	exclusions="-X $d $exclusions"
 | 
			
		||||
    done
 | 
			
		||||
    echo $exclusions
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
process_options() {
 | 
			
		||||
    [ -e /etc/network/options ] || return 0
 | 
			
		||||
    log_warning_msg "/etc/network/options still exists and it will be IGNORED! Please use /etc/sysctl.conf instead."
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
check_ifstate() {
 | 
			
		||||
    if [ ! -d "$RUN_DIR" ] ; then
 | 
			
		||||
	if ! mkdir -p "$RUN_DIR" ; then
 | 
			
		||||
	    log_failure_msg "can't create $RUN_DIR"
 | 
			
		||||
	    exit 1
 | 
			
		||||
	fi
 | 
			
		||||
    fi
 | 
			
		||||
    if [ ! -r "$IFSTATE" ] ; then
 | 
			
		||||
	if ! :> "$IFSTATE" ; then
 | 
			
		||||
	    log_failure_msg "can't initialise $IFSTATE"
 | 
			
		||||
	    exit 1
 | 
			
		||||
	fi
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
check_network_file_systems() {
 | 
			
		||||
    [ -e /proc/mounts ] || return 0
 | 
			
		||||
 | 
			
		||||
    if [ -e /etc/iscsi/iscsi.initramfs ]; then
 | 
			
		||||
	log_warning_msg "not deconfiguring network interfaces: iSCSI root is mounted."
 | 
			
		||||
	exit 0
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    while read DEV MTPT FSTYPE REST; do
 | 
			
		||||
	case $DEV in
 | 
			
		||||
	/dev/nbd*|/dev/nd[a-z]*|/dev/etherd/e*)
 | 
			
		||||
	    log_warning_msg "not deconfiguring network interfaces: network devices still mounted."
 | 
			
		||||
	    exit 0
 | 
			
		||||
	    ;;
 | 
			
		||||
	esac
 | 
			
		||||
	case $FSTYPE in
 | 
			
		||||
	nfs|nfs4|smbfs|ncp|ncpfs|cifs|coda|ocfs2|gfs|pvfs|pvfs2|fuse.httpfs|fuse.curlftpfs)
 | 
			
		||||
	    log_warning_msg "not deconfiguring network interfaces: network file systems still mounted."
 | 
			
		||||
	    exit 0
 | 
			
		||||
	    ;;
 | 
			
		||||
	esac
 | 
			
		||||
    done < /proc/mounts
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
check_network_swap() {
 | 
			
		||||
    [ -e /proc/swaps ] || return 0
 | 
			
		||||
 | 
			
		||||
    while read DEV MTPT FSTYPE REST; do
 | 
			
		||||
	case $DEV in
 | 
			
		||||
	/dev/nbd*|/dev/nd[a-z]*|/dev/etherd/e*)
 | 
			
		||||
	    log_warning_msg "not deconfiguring network interfaces: network swap still mounted."
 | 
			
		||||
	    exit 0
 | 
			
		||||
	    ;;
 | 
			
		||||
	esac
 | 
			
		||||
    done < /proc/swaps
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ifup_hotplug () {
 | 
			
		||||
    if [ -d /sys/class/net ]
 | 
			
		||||
    then
 | 
			
		||||
	    ifaces=$(for iface in $(ifquery --list --allow=hotplug)
 | 
			
		||||
			    do
 | 
			
		||||
				    link=${iface##:*}
 | 
			
		||||
				    link=${link##.*}
 | 
			
		||||
				    if [ -e "/sys/class/net/$link" ] && [ "$(cat /sys/class/net/$link/operstate)" = up ]
 | 
			
		||||
				    then
 | 
			
		||||
					    echo "$iface"
 | 
			
		||||
				    fi
 | 
			
		||||
			    done)
 | 
			
		||||
	    if [ -n "$ifaces" ]
 | 
			
		||||
	    then
 | 
			
		||||
		ifup $ifaces "$@" || true
 | 
			
		||||
	    fi
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
case "$1" in
 | 
			
		||||
start)
 | 
			
		||||
	if init_is_upstart; then
 | 
			
		||||
		exit 1
 | 
			
		||||
	fi
 | 
			
		||||
	process_options
 | 
			
		||||
	check_ifstate
 | 
			
		||||
 | 
			
		||||
	if [ "$CONFIGURE_INTERFACES" = no ]
 | 
			
		||||
	then
 | 
			
		||||
	    log_action_msg "Not configuring network interfaces, see /etc/default/networking"
 | 
			
		||||
	    exit 0
 | 
			
		||||
	fi
 | 
			
		||||
	set -f
 | 
			
		||||
	exclusions=$(process_exclusions)
 | 
			
		||||
	log_action_begin_msg "Configuring network interfaces"
 | 
			
		||||
	if ifup -a $exclusions $verbose && ifup_hotplug $exclusions $verbose
 | 
			
		||||
	then
 | 
			
		||||
	    log_action_end_msg $?
 | 
			
		||||
	else
 | 
			
		||||
	    log_action_end_msg $?
 | 
			
		||||
	fi
 | 
			
		||||
	;;
 | 
			
		||||
 | 
			
		||||
stop)
 | 
			
		||||
	if init_is_upstart; then
 | 
			
		||||
		exit 0
 | 
			
		||||
	fi
 | 
			
		||||
	check_network_file_systems
 | 
			
		||||
	check_network_swap
 | 
			
		||||
 | 
			
		||||
	log_action_begin_msg "Deconfiguring network interfaces"
 | 
			
		||||
	if ifdown -a --exclude=lo $verbose; then
 | 
			
		||||
	    log_action_end_msg $?
 | 
			
		||||
	else
 | 
			
		||||
	    log_action_end_msg $?
 | 
			
		||||
	fi
 | 
			
		||||
	;;
 | 
			
		||||
 | 
			
		||||
reload)
 | 
			
		||||
	process_options
 | 
			
		||||
 | 
			
		||||
	log_action_begin_msg "Reloading network interfaces configuration"
 | 
			
		||||
	state=$(cat /run/network/ifstate)
 | 
			
		||||
	ifdown -a --exclude=lo $verbose || true
 | 
			
		||||
	if ifup --exclude=lo $state $verbose ; then
 | 
			
		||||
	    log_action_end_msg $?
 | 
			
		||||
	else
 | 
			
		||||
	    log_action_end_msg $?
 | 
			
		||||
	fi
 | 
			
		||||
	;;
 | 
			
		||||
 | 
			
		||||
force-reload|restart)
 | 
			
		||||
	if init_is_upstart; then
 | 
			
		||||
		exit 1
 | 
			
		||||
	fi
 | 
			
		||||
	process_options
 | 
			
		||||
 | 
			
		||||
	log_warning_msg "Running $0 $1 is deprecated because it may not re-enable some interfaces"
 | 
			
		||||
	log_action_begin_msg "Reconfiguring network interfaces"
 | 
			
		||||
	ifdown -a --exclude=lo $verbose || true
 | 
			
		||||
	set -f
 | 
			
		||||
	exclusions=$(process_exclusions)
 | 
			
		||||
	if ifup -a --exclude=lo $exclusions $verbose && ifup_hotplug $exclusions $verbose
 | 
			
		||||
	then
 | 
			
		||||
	    log_action_end_msg $?
 | 
			
		||||
	else
 | 
			
		||||
	    log_action_end_msg $?
 | 
			
		||||
	fi
 | 
			
		||||
	;;
 | 
			
		||||
 | 
			
		||||
*)
 | 
			
		||||
	echo "Usage: /etc/init.d/networking {start|stop|reload|restart|force-reload}"
 | 
			
		||||
	exit 1
 | 
			
		||||
	;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
exit 0
 | 
			
		||||
 | 
			
		||||
# vim: noet ts=8
 | 
			
		||||
							
								
								
									
										1
									
								
								man/ifdown.8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								man/ifdown.8
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
.so ifup.8
 | 
			
		||||
							
								
								
									
										1
									
								
								man/ifquery.8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								man/ifquery.8
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
.so ifup.8
 | 
			
		||||
							
								
								
									
										232
									
								
								man/ifup.8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										232
									
								
								man/ifup.8
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,232 @@
 | 
			
		||||
.TH ifup 8 "22 May 2004" IFUPDOWN ""
 | 
			
		||||
.SH NAME
 | 
			
		||||
ifup \- bring a network interface up
 | 
			
		||||
.PP
 | 
			
		||||
ifdown \- take a network interface down
 | 
			
		||||
.PP
 | 
			
		||||
ifquery \- parse interface configuration
 | 
			
		||||
.SH SYNOPSIS
 | 
			
		||||
.B ifup 
 | 
			
		||||
[\fB\-nv\fR]
 | 
			
		||||
[\fB\-\-no\-act\fR]
 | 
			
		||||
[\fB\-\-verbose\fR]
 | 
			
		||||
[\fB\-i\fR \fIFILE\fR|\fB\-\-interfaces=\fR\fIFILE\fR]
 | 
			
		||||
[\fB\-\-allow\fR \fICLASS\fR]
 | 
			
		||||
\fB\-a\fR|\fIIFACE\fR...
 | 
			
		||||
.br
 | 
			
		||||
.B ifup 
 | 
			
		||||
\fB\-h\fR|\fB\-\-help\fR
 | 
			
		||||
.br
 | 
			
		||||
.B ifup 
 | 
			
		||||
\fB\-V\fR|\fB\-\-version\fR
 | 
			
		||||
.PP
 | 
			
		||||
.B ifdown
 | 
			
		||||
[\fB\-nv\fR]
 | 
			
		||||
[\fB\-\-no\-act\fR]
 | 
			
		||||
[\fB\-\-verbose\fR]
 | 
			
		||||
[\fB\-i\fR \fIFILE\fR|\fB\-\-interfaces=\fR\fIFILE\fR]
 | 
			
		||||
[\fB\-\-allow\fR \fICLASS\fR]
 | 
			
		||||
\fB\-a\fR|\fIIFACE\fR...
 | 
			
		||||
.PP
 | 
			
		||||
.B ifquery
 | 
			
		||||
[\fB\-nv\fR]
 | 
			
		||||
[\fB\-\-no\-act\fR]
 | 
			
		||||
[\fB\-\-verbose\fR]
 | 
			
		||||
[\fB\-i\fR \fIFILE\fR|\fB\-\-interfaces=\fR\fIFILE\fR]
 | 
			
		||||
[\fB\-\-allow\fR \fICLASS\fR]
 | 
			
		||||
\fB\-a\fR|\fIIFACE\fR...
 | 
			
		||||
.PP
 | 
			
		||||
.B ifquery
 | 
			
		||||
\fB\-l\fR|\fB\-\-list\fR
 | 
			
		||||
[\fB\-nv\fR]
 | 
			
		||||
[\fB\-\-no\-act\fR]
 | 
			
		||||
[\fB\-\-verbose\fR]
 | 
			
		||||
[\fB\-i\fR \fIFILE\fR|\fB\-\-interfaces=\fR\fIFILE\fR]
 | 
			
		||||
[\fB\-\-allow\fR \fICLASS\fR]
 | 
			
		||||
\fB\-a\fR|\fIIFACE\fR...
 | 
			
		||||
.SH DESCRIPTION
 | 
			
		||||
The
 | 
			
		||||
.BR ifup " and " ifdown
 | 
			
		||||
commands may be used to configure (or, respectively, deconfigure) network
 | 
			
		||||
interfaces based on interface definitions in the file
 | 
			
		||||
.IR /etc/network/interfaces ". "
 | 
			
		||||
.BR ifquery " command may be used to parse interfaces configuration."
 | 
			
		||||
.SH OPTIONS
 | 
			
		||||
A summary of options is included below.
 | 
			
		||||
.TP
 | 
			
		||||
.BR \-a ", " \-\-all
 | 
			
		||||
If given to \fBifup\fP, affect all interfaces marked \fBauto\fP.
 | 
			
		||||
Interfaces are brought up in the order in which they are defined
 | 
			
		||||
in
 | 
			
		||||
.IR /etc/network/interfaces .
 | 
			
		||||
Combined with \fB-\-allow\fP, acts on all interfaces of a specified class
 | 
			
		||||
instead.
 | 
			
		||||
If given to \fBifdown\fP, affect all defined interfaces.
 | 
			
		||||
Interfaces are brought down in the order in which they are
 | 
			
		||||
currently listed in the state file. Only interfaces defined
 | 
			
		||||
in
 | 
			
		||||
.I /etc/network/interfaces
 | 
			
		||||
will be brought down.
 | 
			
		||||
.TP
 | 
			
		||||
.B \-\-force
 | 
			
		||||
Force configuration or deconfiguration of the interface.
 | 
			
		||||
.TP
 | 
			
		||||
.BR \-h ", " \-\-help
 | 
			
		||||
Show summary of options.
 | 
			
		||||
.TP
 | 
			
		||||
\fB\-\-allow=\fR\fICLASS\fR
 | 
			
		||||
Only allow interfaces listed in an
 | 
			
		||||
.I allow\-CLASS
 | 
			
		||||
line in 
 | 
			
		||||
.IR /etc/network/interfaces " to be acted upon."
 | 
			
		||||
.TP
 | 
			
		||||
\fB\-i\fR \fIFILE\fR, \fB\-\-interfaces=\fR\fIFILE\fR
 | 
			
		||||
Read interface definitions from 
 | 
			
		||||
.I FILE
 | 
			
		||||
instead of from
 | 
			
		||||
.IR /etc/network/interfaces "."
 | 
			
		||||
.TP
 | 
			
		||||
.BI \-X " PATTERN\fR, " "\-\-exclude=" PATTERN
 | 
			
		||||
Exclude interfaces from the list of interfaces to operate on by the \fIPATTERN\fR.
 | 
			
		||||
\fIPATTERN\fR uses a usual shell glob syntax. If shell wildcards are not used, it
 | 
			
		||||
must match the exact interface name. This option may be specified multiple times
 | 
			
		||||
resulting in more than one pattern being excluded.
 | 
			
		||||
.TP
 | 
			
		||||
.BI \-o " OPTION" "\fB=" VALUE
 | 
			
		||||
Set \fIOPTION\fR to \fIVALUE\fR as though it were in
 | 
			
		||||
.IR /etc/network/interfaces .
 | 
			
		||||
.TP
 | 
			
		||||
.BR \-n ", " \-\-no\-act
 | 
			
		||||
Don't configure any interfaces or run any "up" or "down" commands.
 | 
			
		||||
.TP
 | 
			
		||||
.B \-\-no\-mappings
 | 
			
		||||
Don't run any mappings.  See
 | 
			
		||||
.BR interfaces (5)
 | 
			
		||||
for more information about the mapping feature.
 | 
			
		||||
.TP
 | 
			
		||||
.B \-\-no\-scripts
 | 
			
		||||
Don't run any scripts under /etc/network/if-*.d/
 | 
			
		||||
.TP
 | 
			
		||||
.BR \-V ", " \-\-version
 | 
			
		||||
Show copyright and version information.
 | 
			
		||||
.TP
 | 
			
		||||
.BR \-v ", " \-\-verbose
 | 
			
		||||
Show commands as they are executed.
 | 
			
		||||
.TP
 | 
			
		||||
.BR \-l ", " \-\-list
 | 
			
		||||
For \fBifquery\fR, list all the interfaces which match the specified class.
 | 
			
		||||
If no class specified, prints all the interfaces listed as \fBauto\fR.
 | 
			
		||||
.SH EXAMPLES
 | 
			
		||||
.TP
 | 
			
		||||
.B ifup -a
 | 
			
		||||
Bring up all the interfaces defined with
 | 
			
		||||
.I auto
 | 
			
		||||
in 
 | 
			
		||||
.I /etc/network/interfaces
 | 
			
		||||
.TP
 | 
			
		||||
.B ifup eth0
 | 
			
		||||
Bring up interface
 | 
			
		||||
.B eth0
 | 
			
		||||
.TP
 | 
			
		||||
.B ifup eth0=home
 | 
			
		||||
Bring up interface
 | 
			
		||||
.B eth0
 | 
			
		||||
as logical interface
 | 
			
		||||
.B home
 | 
			
		||||
.TP
 | 
			
		||||
.B ifdown -a
 | 
			
		||||
Bring down all interfaces that are currently up.
 | 
			
		||||
.TP
 | 
			
		||||
.B ifquery -l
 | 
			
		||||
Print names of all interfaces specified with the \fBauto\fR keyword.
 | 
			
		||||
.TP
 | 
			
		||||
.B ifquery -l --allow=hotplug
 | 
			
		||||
Print names of all interfaces specified with the \fBallow-hotplug\fR keyword.
 | 
			
		||||
.TP
 | 
			
		||||
.B ifquery eth0
 | 
			
		||||
Display the interface options as specified in the \fBifupdown\fR
 | 
			
		||||
configuration. Each key-value pair is printed out on individual
 | 
			
		||||
line using "\fB: \fR" as separator.
 | 
			
		||||
.SH NOTES
 | 
			
		||||
.BR ifup ,
 | 
			
		||||
.BR ifdown ,
 | 
			
		||||
and
 | 
			
		||||
.BR ifquery
 | 
			
		||||
are actually the same program called by different names.
 | 
			
		||||
.P
 | 
			
		||||
The program does not configure network interfaces directly;
 | 
			
		||||
it runs low level utilities such as
 | 
			
		||||
.BR ip
 | 
			
		||||
to do its dirty work.
 | 
			
		||||
.P
 | 
			
		||||
When invoked,
 | 
			
		||||
.B ifdown
 | 
			
		||||
checks if
 | 
			
		||||
.B ifup
 | 
			
		||||
is still running. In that case,
 | 
			
		||||
.B SIGTERM
 | 
			
		||||
is sent to ifup.
 | 
			
		||||
.SH FILES
 | 
			
		||||
.TP
 | 
			
		||||
.I /etc/network/interfaces
 | 
			
		||||
definitions of network interfaces
 | 
			
		||||
See
 | 
			
		||||
.BR interfaces (5)
 | 
			
		||||
for more information.
 | 
			
		||||
.TP
 | 
			
		||||
.I /run/network/ifstate
 | 
			
		||||
current state of network interfaces
 | 
			
		||||
.SH KNOWN BUGS/LIMITATIONS
 | 
			
		||||
The program keeps records of whether network interfaces are up or down.
 | 
			
		||||
Under exceptional circumstances these records can become
 | 
			
		||||
inconsistent with the real states of the interfaces.
 | 
			
		||||
For example, an interface that was brought up using
 | 
			
		||||
.B ifup
 | 
			
		||||
and later deconfigured using
 | 
			
		||||
.B ifconfig
 | 
			
		||||
will still be recorded as up.
 | 
			
		||||
To fix this you can use the
 | 
			
		||||
.B \-\-force
 | 
			
		||||
option to force
 | 
			
		||||
.B ifup
 | 
			
		||||
or
 | 
			
		||||
.B ifdown
 | 
			
		||||
to run configuration or deconfiguration commands despite what
 | 
			
		||||
it considers the current state of the interface to be.
 | 
			
		||||
.P
 | 
			
		||||
The file
 | 
			
		||||
.I /run/network/ifstate
 | 
			
		||||
must be writable for
 | 
			
		||||
.B ifup
 | 
			
		||||
or
 | 
			
		||||
.B ifdown
 | 
			
		||||
to work properly.
 | 
			
		||||
If that location is not writable
 | 
			
		||||
(for example, because the root filesystem is mounted read-only
 | 
			
		||||
for system recovery)
 | 
			
		||||
then
 | 
			
		||||
.I /run/network/ifstate
 | 
			
		||||
should be made a symbolic link to a writable location.
 | 
			
		||||
If that is not possible then you can use the
 | 
			
		||||
.B \-\-force
 | 
			
		||||
option to run configuration or deconfiguration commands
 | 
			
		||||
without updating the file.
 | 
			
		||||
.P
 | 
			
		||||
Note that the program does not run automatically:
 | 
			
		||||
.B ifup
 | 
			
		||||
alone does not bring up interfaces
 | 
			
		||||
that appear as a result of hardware being installed and 
 | 
			
		||||
.B ifdown
 | 
			
		||||
alone does not bring down interfaces
 | 
			
		||||
that disappear as a result of hardware being removed.
 | 
			
		||||
To automate the configuration of network interfaces you need to
 | 
			
		||||
install other packages such as
 | 
			
		||||
.BR udev (7)
 | 
			
		||||
or
 | 
			
		||||
.BR ifplugd (8).
 | 
			
		||||
.SH AUTHOR
 | 
			
		||||
The ifupdown suite was written by Anthony Towns <aj@azure.humbug.org.au>.
 | 
			
		||||
.SH SEE ALSO
 | 
			
		||||
.BR interfaces (5),
 | 
			
		||||
.BR ip (8),
 | 
			
		||||
.BR ifconfig (8).
 | 
			
		||||
							
								
								
									
										310
									
								
								man/interfaces.5
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										310
									
								
								man/interfaces.5
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,310 @@
 | 
			
		||||
.\" -*- nroff -*-
 | 
			
		||||
.\" macros
 | 
			
		||||
.de EX \" Begin Example
 | 
			
		||||
.  IP
 | 
			
		||||
.  ft CW
 | 
			
		||||
.  nf
 | 
			
		||||
.  ne \\$1
 | 
			
		||||
..
 | 
			
		||||
.de EE \" End Example
 | 
			
		||||
.  ft P
 | 
			
		||||
.  fi
 | 
			
		||||
.  PP
 | 
			
		||||
..
 | 
			
		||||
.TH INTERFACES 5 "5 April 2004" "ifupdown" "File formats"
 | 
			
		||||
.SH NAME
 | 
			
		||||
/etc/network/interfaces \- network interface configuration for ifup and ifdown 
 | 
			
		||||
.SH DESCRIPTION
 | 
			
		||||
/etc/network/interfaces contains network interface configuration
 | 
			
		||||
information for the
 | 
			
		||||
.BR ifup (8)
 | 
			
		||||
and
 | 
			
		||||
.BR ifdown (8)
 | 
			
		||||
commands.
 | 
			
		||||
This is where you configure how your system is connected to the network.
 | 
			
		||||
.P
 | 
			
		||||
Lines starting with `#' are ignored. Note that end-of-line comments are
 | 
			
		||||
NOT supported, comments must be on a line of their own.
 | 
			
		||||
.P
 | 
			
		||||
A line may be extended across multiple lines by making the last character
 | 
			
		||||
a backslash.
 | 
			
		||||
.P
 | 
			
		||||
The file consists of zero or more "iface", "mapping", "auto", "allow-" and
 | 
			
		||||
"source" stanzas. Here is an example.
 | 
			
		||||
.EX
 | 
			
		||||
auto lo eth0
 | 
			
		||||
allow-hotplug eth1
 | 
			
		||||
 | 
			
		||||
iface lo inet loopback
 | 
			
		||||
 | 
			
		||||
source interfaces.d/machine\-dependent
 | 
			
		||||
 | 
			
		||||
mapping eth0 
 | 
			
		||||
 	script /usr/local/sbin/map\-scheme
 | 
			
		||||
 	map HOME eth0\-home
 | 
			
		||||
 	map WORK eth0\-work
 | 
			
		||||
 | 
			
		||||
iface eth0\-home inet static
 | 
			
		||||
 	address 192.168.1.1
 | 
			
		||||
 	netmask 255.255.255.0
 | 
			
		||||
 	up flush\-mail
 | 
			
		||||
 | 
			
		||||
iface eth0\-work inet dhcp
 | 
			
		||||
 | 
			
		||||
iface eth1 inet dhcp
 | 
			
		||||
.EE
 | 
			
		||||
Lines beginning with the word "auto" are used to identify the physical
 | 
			
		||||
interfaces to be brought up when
 | 
			
		||||
.B ifup
 | 
			
		||||
is run with the
 | 
			
		||||
.B \-a
 | 
			
		||||
option.  (This option is used by the system boot scripts.)
 | 
			
		||||
Physical interface names should follow the word "auto" on the same line.
 | 
			
		||||
There can be multiple "auto" stanzas.
 | 
			
		||||
.B ifup
 | 
			
		||||
brings the named interfaces up in the order listed.
 | 
			
		||||
.P
 | 
			
		||||
Lines beginning with "allow-" are used to identify interfaces that should
 | 
			
		||||
be brought up automatically by various subsytems. This may be done using
 | 
			
		||||
a command such as "ifup \-\-allow=hotplug eth0 eth1", which will only bring
 | 
			
		||||
up eth0 or eth1 if it is listed in an "allow-hotplug" line. Note that
 | 
			
		||||
"allow-auto" and "auto" are synonyms.
 | 
			
		||||
.P
 | 
			
		||||
Lines beginning with "source" are used to include stanzas from other files,
 | 
			
		||||
so configuration can be split into many files. The word "source" is 
 | 
			
		||||
followed by the path of file to be sourced. Shell wildcards can be 
 | 
			
		||||
used.
 | 
			
		||||
(See
 | 
			
		||||
.BR wordexp (3)
 | 
			
		||||
for details.)
 | 
			
		||||
.P
 | 
			
		||||
Stanzas beginning with the word "mapping" are used to determine how a
 | 
			
		||||
logical interface name is chosen for a physical interface that is to be
 | 
			
		||||
brought up.  The first line of a mapping stanza consists of the word
 | 
			
		||||
"mapping" followed by a pattern in shell glob syntax.  Each mapping stanza
 | 
			
		||||
must contain a
 | 
			
		||||
.BR script
 | 
			
		||||
definition.  The named script is run with the physical interface name as
 | 
			
		||||
its argument and with the contents of all following "map" lines 
 | 
			
		||||
(\fBwithout\fR the leading "map") in the
 | 
			
		||||
stanza provided to it on its standard input. The script must print a
 | 
			
		||||
string on its standard output before exiting. See 
 | 
			
		||||
.IR /usr/share/doc/ifupdown/examples
 | 
			
		||||
for examples of what the script must print.
 | 
			
		||||
.P
 | 
			
		||||
Mapping a name consists of searching the remaining mapping
 | 
			
		||||
patterns and running the script corresponding to the first match;
 | 
			
		||||
the script outputs the name to which the original is mapped.
 | 
			
		||||
.P
 | 
			
		||||
.B ifup
 | 
			
		||||
is normally given a physical interface name as its first non\-option argument.
 | 
			
		||||
.B ifup
 | 
			
		||||
also uses this name as the initial logical name for the interface unless
 | 
			
		||||
it is accompanied by a  suffix of the form \fI=LOGICAL\fR, in which case
 | 
			
		||||
ifup chooses \fILOGICAL\fR as the initial logical name for the interface.
 | 
			
		||||
It then maps this name, possibly more than once according to successive
 | 
			
		||||
mapping specifications,  until no further mappings are possible.  If the
 | 
			
		||||
resulting name is the name of some defined logical interface then
 | 
			
		||||
.B ifup 
 | 
			
		||||
attempts to bring up the physical interface
 | 
			
		||||
as that logical interface.  Otherwise
 | 
			
		||||
.B ifup
 | 
			
		||||
exits with an error.
 | 
			
		||||
.P
 | 
			
		||||
Stanzas defining logical interfaces start with a line consisting of the
 | 
			
		||||
word "iface" followed by the name of the logical interface.
 | 
			
		||||
In simple configurations without mapping stanzas this name should simply
 | 
			
		||||
be the name of the physical interface to which it is to be applied.
 | 
			
		||||
(The default mapping script is, in effect, the
 | 
			
		||||
.B echo
 | 
			
		||||
command.)
 | 
			
		||||
The interface name is followed by the name of the address family that the
 | 
			
		||||
interface uses.  This will be "inet" for TCP/IP networking, but there is
 | 
			
		||||
also some support for IPX networking ("ipx"), and IPv6 networking ("inet6").
 | 
			
		||||
Following that is the name of the method used to configure the interface.
 | 
			
		||||
.P
 | 
			
		||||
Additional options can be given on subsequent lines in the stanza.
 | 
			
		||||
Which options are available depends on the family and method,
 | 
			
		||||
as described below.
 | 
			
		||||
Additional options can be made available by other Debian packages.
 | 
			
		||||
For example, the wireless\-tools package makes available a number of
 | 
			
		||||
options prefixed with "wireless\-" which can be used to configure the
 | 
			
		||||
interface using
 | 
			
		||||
.BR iwconfig (8) .
 | 
			
		||||
(See
 | 
			
		||||
.BR wireless (7)
 | 
			
		||||
for details.)
 | 
			
		||||
.P
 | 
			
		||||
Options are usually indented for clarity (as in the example above)
 | 
			
		||||
but are not required to be.
 | 
			
		||||
.P
 | 
			
		||||
.SH VLAN AND BRIDGE INTERFACES
 | 
			
		||||
To ease the configuration of VLAN interfaces, interfaces having
 | 
			
		||||
.B .
 | 
			
		||||
(full stop character) in the name are configured as 802.1q tagged
 | 
			
		||||
virtual LAN interface. For example, interface
 | 
			
		||||
.B eth0.1
 | 
			
		||||
is a virtual interface having
 | 
			
		||||
.B eth0
 | 
			
		||||
as physical link, with VLAN ID 1.
 | 
			
		||||
.P
 | 
			
		||||
For compatibility with
 | 
			
		||||
.B bridge-utils
 | 
			
		||||
package, if
 | 
			
		||||
.B bridge_ports
 | 
			
		||||
option is specified, VLAN interface configuration is
 | 
			
		||||
.B not
 | 
			
		||||
performed.
 | 
			
		||||
.SH IFACE OPTIONS
 | 
			
		||||
The following "command" options are available for every family and method.
 | 
			
		||||
Each of these options can be given multiple times in a single stanza,
 | 
			
		||||
in which case the commands are executed in the order in which they appear
 | 
			
		||||
in the stanza.
 | 
			
		||||
(You can ensure a command never fails by suffixing "|| true".)
 | 
			
		||||
.TP
 | 
			
		||||
.BI pre\-up " command"
 | 
			
		||||
Run
 | 
			
		||||
.I command
 | 
			
		||||
before bringing the interface up.
 | 
			
		||||
If this command fails then
 | 
			
		||||
.B ifup
 | 
			
		||||
aborts,
 | 
			
		||||
refraining from marking the interface as configured,
 | 
			
		||||
prints an error message,
 | 
			
		||||
and exits with status 0.
 | 
			
		||||
This behavior may change in the future.
 | 
			
		||||
.TP
 | 
			
		||||
.BI up " command" 
 | 
			
		||||
.TP
 | 
			
		||||
.BI post\-up " command"
 | 
			
		||||
Run
 | 
			
		||||
.I command
 | 
			
		||||
after bringing the interface up.
 | 
			
		||||
If this command fails then
 | 
			
		||||
.B ifup
 | 
			
		||||
aborts,
 | 
			
		||||
refraining from marking the interface as configured
 | 
			
		||||
(even though it has really been configured),
 | 
			
		||||
prints an error message,
 | 
			
		||||
and exits with status 0.
 | 
			
		||||
This behavior may change in the future.
 | 
			
		||||
.TP
 | 
			
		||||
.BI down " command"
 | 
			
		||||
.TP
 | 
			
		||||
.BI pre\-down " command"
 | 
			
		||||
Run
 | 
			
		||||
.I command
 | 
			
		||||
before taking the interface down.
 | 
			
		||||
If this command fails then
 | 
			
		||||
.B ifdown
 | 
			
		||||
aborts,
 | 
			
		||||
marks the interface as deconfigured
 | 
			
		||||
(even though it has not really been deconfigured),
 | 
			
		||||
and exits with status 0.
 | 
			
		||||
This behavior may change in the future.
 | 
			
		||||
.TP
 | 
			
		||||
.BI post\-down " command"
 | 
			
		||||
Run
 | 
			
		||||
.I command
 | 
			
		||||
after taking the interface down.
 | 
			
		||||
If this command fails then
 | 
			
		||||
.B ifdown
 | 
			
		||||
aborts,
 | 
			
		||||
marks the interface as deconfigured,
 | 
			
		||||
and exits with status 0.
 | 
			
		||||
This behavior may change in the future.
 | 
			
		||||
.P
 | 
			
		||||
There exists for each of the above mentioned options a directory
 | 
			
		||||
.IR /etc/network/if\-\fB<option>\fI.d/ 
 | 
			
		||||
the scripts in which are run (with no arguments) using
 | 
			
		||||
.BR run\-parts (8)
 | 
			
		||||
after the option itself has been processed. Please note that as
 | 
			
		||||
.BI post\-up
 | 
			
		||||
and
 | 
			
		||||
.BI pre\-down
 | 
			
		||||
are aliases, no files in the corresponding directories are processed.
 | 
			
		||||
Please use
 | 
			
		||||
.IR if-up.d
 | 
			
		||||
and
 | 
			
		||||
.IR if-down.d
 | 
			
		||||
directories instead.
 | 
			
		||||
.P
 | 
			
		||||
All of these commands have access to the following environment variables.
 | 
			
		||||
.TP
 | 
			
		||||
.B IFACE
 | 
			
		||||
physical name of the interface being processed
 | 
			
		||||
.TP
 | 
			
		||||
.B LOGICAL
 | 
			
		||||
logical name of the interface being processed
 | 
			
		||||
.TP
 | 
			
		||||
.B ADDRFAM
 | 
			
		||||
address family of the interface
 | 
			
		||||
.TP
 | 
			
		||||
.B METHOD
 | 
			
		||||
method of the interface (e.g.,
 | 
			
		||||
.IR static )
 | 
			
		||||
.TP
 | 
			
		||||
.B MODE
 | 
			
		||||
.IR start " if run from ifup, " stop " if run from ifdown"
 | 
			
		||||
.TP
 | 
			
		||||
.B PHASE 
 | 
			
		||||
as per MODE, but with finer granularity, distinguishing the
 | 
			
		||||
\fIpre-up\fR, \fIpost-up\fR, \fIpre-down\fR and \fIpost-down\fR phases.
 | 
			
		||||
.TP
 | 
			
		||||
.B VERBOSITY
 | 
			
		||||
indicates whether \fB\-\-verbose\fR was used; set to 1 if so, 0 if not.
 | 
			
		||||
.TP
 | 
			
		||||
.B PATH
 | 
			
		||||
the command search path:
 | 
			
		||||
.I /usr/local/sbin:\%/usr/local/bin:\%/usr/sbin:\%/usr/bin:\%/sbin:\%/bin
 | 
			
		||||
.P
 | 
			
		||||
Additionally, all options given in an interface definition stanza are
 | 
			
		||||
exported to the environment in upper case with "IF_" prepended and with
 | 
			
		||||
hyphens converted to underscores and non\-alphanumeric characters discarded.
 | 
			
		||||
.P
 | 
			
		||||
When ifupdown is being called with the \fB\-\-all\fR option, before doing anything
 | 
			
		||||
to interfaces, if calls all the hook scripts (\fIpre-up\fR or \fIdown\fR) with
 | 
			
		||||
\fBIFACE\fR set to "\-\-all", \fBLOGICAL\fR set to the current value of \-\-allow
 | 
			
		||||
parameter (or "auto" if it's not set), \fBADDRFAM\fR="meta" and \fBMETHOD\fR="none".
 | 
			
		||||
After all the interfaces have been brought up or taken down, the appropriate scripts
 | 
			
		||||
(\fIup\fR or \fIpost-down\fR) are executed.
 | 
			
		||||
##ADDRESSFAM##
 | 
			
		||||
.SH KNOWN BUGS/LIMITATIONS
 | 
			
		||||
The
 | 
			
		||||
.B ifup
 | 
			
		||||
and
 | 
			
		||||
.B ifdown
 | 
			
		||||
programs work with so-called "physical" interface names.
 | 
			
		||||
These names are assigned to hardware by the kernel.
 | 
			
		||||
Unfortunately it can happen that the kernel assigns different
 | 
			
		||||
physical interface names to the same hardware at different
 | 
			
		||||
times; for example, what was called "eth0" last time you booted
 | 
			
		||||
is now called "eth1" and vice versa.
 | 
			
		||||
This creates a problem if you want to configure the interfaces
 | 
			
		||||
appropriately.
 | 
			
		||||
A way to deal with this problem is to use mapping scripts that
 | 
			
		||||
choose logical interface names according to the properties of
 | 
			
		||||
the interface hardware.
 | 
			
		||||
See the
 | 
			
		||||
.B get-mac-address.sh
 | 
			
		||||
script in the examples directory for an example of such a mapping
 | 
			
		||||
script.  See also Debian bug #101728.
 | 
			
		||||
.SH AUTHOR
 | 
			
		||||
The ifupdown suite was written by Anthony Towns <aj@azure.humbug.org.au>.
 | 
			
		||||
This manpage was contributed by Joey Hess <joey@kitenet.net>.
 | 
			
		||||
.SH "SEE ALSO"
 | 
			
		||||
.BR ifup (8),
 | 
			
		||||
.BR ip (8),
 | 
			
		||||
.BR ifconfig (8),
 | 
			
		||||
.BR run\-parts (8),
 | 
			
		||||
.BR resolvconf (8).
 | 
			
		||||
.P
 | 
			
		||||
For advice on configuring this package read the
 | 
			
		||||
.B Network Configuration
 | 
			
		||||
chapter of the \fIDebian Reference\fR manual,
 | 
			
		||||
available at
 | 
			
		||||
\fIhttp://www.debian.org/doc/manuals/debian-reference/ch05.en.html\fR
 | 
			
		||||
or in the \fBdebian-reference-en\fR package.
 | 
			
		||||
.P
 | 
			
		||||
Examples of how to set up interfaces can be found in
 | 
			
		||||
.BR /usr/share/doc/ifupdown/examples/network-interfaces.gz .
 | 
			
		||||
							
								
								
									
										0
									
								
								pkg/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								pkg/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										17
									
								
								pkg/exceptions.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								pkg/exceptions.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
#!/usr/bin/python
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Error(Exception):
 | 
			
		||||
    """Base class for exceptions in ifupdown"""
 | 
			
		||||
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
class ifaceNotFoundError(Error):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class invalidValueError(Error):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
class errorReadingStateError(Error):
 | 
			
		||||
    pass
 | 
			
		||||
							
								
								
									
										43
									
								
								pkg/graph.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								pkg/graph.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
#!/usr/bin/python
 | 
			
		||||
 | 
			
		||||
import logging
 | 
			
		||||
from collections import deque
 | 
			
		||||
 | 
			
		||||
class graph():
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.logger = logging.getLogger('ifupdown.' +
 | 
			
		||||
                    self.__class__.__name__)
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def topological_sort(cls, dependency_graph, indegrees=None):
 | 
			
		||||
        S = []
 | 
			
		||||
        Q = deque()
 | 
			
		||||
 | 
			
		||||
        for ifname,indegree in indegrees.items():
 | 
			
		||||
            if indegree == 0:
 | 
			
		||||
                Q.append(ifname)
 | 
			
		||||
 | 
			
		||||
        while len(Q) != 0:
 | 
			
		||||
            # initialize queue
 | 
			
		||||
            x = Q.popleft()
 | 
			
		||||
 | 
			
		||||
            # Get dependents of x
 | 
			
		||||
            dlist = dependency_graph.get(x)
 | 
			
		||||
            if dlist == None or len(dlist) == 0:
 | 
			
		||||
                S.append(x)
 | 
			
		||||
                continue
 | 
			
		||||
 | 
			
		||||
            for y in dlist:
 | 
			
		||||
                indegrees[y] = indegrees.get(y) - 1
 | 
			
		||||
                if indegrees.get(y) == 0:
 | 
			
		||||
                    Q.append(y)
 | 
			
		||||
 | 
			
		||||
            S.append(x)
 | 
			
		||||
 | 
			
		||||
        # If some indegrees are non zero, we have a cycle
 | 
			
		||||
        for ifname,indegree in indegrees.items():
 | 
			
		||||
            if indegree != 0:
 | 
			
		||||
                raise Exception('cycle found involving iface %s' %ifname)
 | 
			
		||||
 | 
			
		||||
        return S
 | 
			
		||||
							
								
								
									
										366
									
								
								pkg/iface.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										366
									
								
								pkg/iface.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,366 @@
 | 
			
		||||
#!/usr/bin/python
 | 
			
		||||
 | 
			
		||||
import logging
 | 
			
		||||
 | 
			
		||||
class ifaceFlags():
 | 
			
		||||
 | 
			
		||||
    NONE = 0x1
 | 
			
		||||
    FOLLOW_DEPENDENTS = 0x2
 | 
			
		||||
 | 
			
		||||
class ifaceStatus():
 | 
			
		||||
 | 
			
		||||
    """iface status """
 | 
			
		||||
    UNKNOWN = 0x1
 | 
			
		||||
    SUCCESS = 0x2
 | 
			
		||||
    ERROR = 0x3
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def to_str(cls, state):
 | 
			
		||||
        if state == cls.UNKNOWN:
 | 
			
		||||
            return 'unknown'
 | 
			
		||||
        elif state == cls.SUCCESS:
 | 
			
		||||
            return 'success'
 | 
			
		||||
        elif state == cls.ERROR:
 | 
			
		||||
            return 'error'
 | 
			
		||||
    
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def from_str(cls, state_str):
 | 
			
		||||
        if state_str == 'unknown':
 | 
			
		||||
            return cls.UNKNOWN
 | 
			
		||||
        elif state_str == 'success':
 | 
			
		||||
            return cls.SUCCESS
 | 
			
		||||
        elif state_str == 'error':
 | 
			
		||||
            return cls.ERROR
 | 
			
		||||
 | 
			
		||||
class ifaceState():
 | 
			
		||||
 | 
			
		||||
    """ iface states """
 | 
			
		||||
    UNKNOWN = 0x1
 | 
			
		||||
    NEW = 0x2
 | 
			
		||||
    PRE_UP = 0x3
 | 
			
		||||
    UP = 0x4
 | 
			
		||||
    POST_UP = 0x5
 | 
			
		||||
    PRE_DOWN = 0x6
 | 
			
		||||
    DOWN = 0x7
 | 
			
		||||
    POST_DOWN = 0x8
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def to_str(cls, state):
 | 
			
		||||
        if state == cls.UNKNOWN:
 | 
			
		||||
            return 'unknown'
 | 
			
		||||
        elif state == cls.NEW:
 | 
			
		||||
            return 'new'
 | 
			
		||||
        elif state == cls.PRE_UP:
 | 
			
		||||
            return 'pre-up'
 | 
			
		||||
        elif state == cls.UP:
 | 
			
		||||
            return 'up'
 | 
			
		||||
        elif state == cls.POST_UP:
 | 
			
		||||
            return 'post-up'
 | 
			
		||||
        elif state == cls.PRE_DOWN:
 | 
			
		||||
            return 'pre-down'
 | 
			
		||||
        elif state == cls.POST_DOWN:
 | 
			
		||||
            return 'post-down'
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def from_str(cls, state_str):
 | 
			
		||||
        if state_str == 'unknown':
 | 
			
		||||
            return cls.UNKNOWN
 | 
			
		||||
        elif state_str == 'new':
 | 
			
		||||
            return cls.NEW
 | 
			
		||||
        elif state_str == 'pre-up':
 | 
			
		||||
            return cls.PRE_UP
 | 
			
		||||
        elif state_str == 'up':
 | 
			
		||||
            return cls.UP
 | 
			
		||||
        elif state_str == 'post-up':
 | 
			
		||||
            return cls.POST_UP
 | 
			
		||||
        elif state_str == 'pre-down':
 | 
			
		||||
            return cls.PRE_DOWN
 | 
			
		||||
        elif state_str == 'post-down':
 | 
			
		||||
            return cls.POST_DOWN
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class iface():
 | 
			
		||||
    """ config flags """
 | 
			
		||||
    AUTO = 0x1
 | 
			
		||||
    HOT_PLUG = 0x2
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.name = None
 | 
			
		||||
        self.addr_family = None
 | 
			
		||||
        self.addr_method = None
 | 
			
		||||
        self.config = {}
 | 
			
		||||
        self.children = []
 | 
			
		||||
        self.state = ifaceState.NEW
 | 
			
		||||
        self.status = ifaceStatus.UNKNOWN
 | 
			
		||||
        self.flags = 0x0
 | 
			
		||||
        self.refcnt = 0
 | 
			
		||||
        self.dependents = None
 | 
			
		||||
        self.auto = False
 | 
			
		||||
        self.classes = []
 | 
			
		||||
        self.env = None
 | 
			
		||||
        self.config_current = {}
 | 
			
		||||
        self.raw_lines = []
 | 
			
		||||
        self.linkstate = None
 | 
			
		||||
 | 
			
		||||
    def inc_refcnt(self):
 | 
			
		||||
        #print 'inside inc_refcnt = %d' %self.refcnt
 | 
			
		||||
        self.refcnt += 1
 | 
			
		||||
 | 
			
		||||
    def dec_refcnt(self):
 | 
			
		||||
        self.refcnt -= 1
 | 
			
		||||
 | 
			
		||||
    def get_refcnt(self):
 | 
			
		||||
        return self.refcnt
 | 
			
		||||
 | 
			
		||||
    def set_refcnt(self, cnt):
 | 
			
		||||
        self.refcnt = 0
 | 
			
		||||
 | 
			
		||||
    def set_name(self, name):
 | 
			
		||||
        self.name = name
 | 
			
		||||
 | 
			
		||||
    def get_name(self):
 | 
			
		||||
        return self.name
 | 
			
		||||
 | 
			
		||||
    def set_addr_family(self, family):
 | 
			
		||||
        self.addr_family = family
 | 
			
		||||
 | 
			
		||||
    def get_addr_family(self):
 | 
			
		||||
        return self.addr_family
 | 
			
		||||
 | 
			
		||||
    def set_addr_method(self, method):
 | 
			
		||||
        self.addr_method = method
 | 
			
		||||
 | 
			
		||||
    def get_addr_method(self):
 | 
			
		||||
        return self.addr_method
 | 
			
		||||
 | 
			
		||||
    def set_config(self, config_dict):
 | 
			
		||||
        self.config = config_dict
 | 
			
		||||
 | 
			
		||||
    def get_config(self):
 | 
			
		||||
        return self.config
 | 
			
		||||
 | 
			
		||||
    def set_config_current(self, config_current):
 | 
			
		||||
        self.config_current = config_current
 | 
			
		||||
 | 
			
		||||
    def get_config_current(self):
 | 
			
		||||
        return self.config_current
 | 
			
		||||
 | 
			
		||||
    def get_auto(self):
 | 
			
		||||
        return self.auto
 | 
			
		||||
 | 
			
		||||
    def set_auto(self):
 | 
			
		||||
        self.auto = True
 | 
			
		||||
 | 
			
		||||
    def reset_auto(self):
 | 
			
		||||
        self.auto = False
 | 
			
		||||
 | 
			
		||||
    def get_classes(self):
 | 
			
		||||
        return self.classes
 | 
			
		||||
 | 
			
		||||
    def set_classes(self, classname):
 | 
			
		||||
        self.classes.append(classname)
 | 
			
		||||
 | 
			
		||||
    def belongs_to_class(self, intfclass):
 | 
			
		||||
        if intfclass in self.classes:
 | 
			
		||||
            return True
 | 
			
		||||
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    def add_child(self, child_iface_obj):
 | 
			
		||||
        self.children.append(child_iface_obj)
 | 
			
		||||
 | 
			
		||||
    def get_state(self):
 | 
			
		||||
        return self.state
 | 
			
		||||
 | 
			
		||||
    def get_state_str(self):
 | 
			
		||||
        return ifaceState.to_str(self.state)
 | 
			
		||||
 | 
			
		||||
    def set_state(self, state):
 | 
			
		||||
        self.state = state
 | 
			
		||||
 | 
			
		||||
    def get_status(self):
 | 
			
		||||
        return self.status
 | 
			
		||||
 | 
			
		||||
    def get_status_str(self):
 | 
			
		||||
        return ifaceStatus.to_str(self.status)
 | 
			
		||||
 | 
			
		||||
    def set_status(self, status):
 | 
			
		||||
        self.status = status
 | 
			
		||||
 | 
			
		||||
    def state_str_to_hex(self, state_str):
 | 
			
		||||
        return self.state_str_map.get(state_str)
 | 
			
		||||
 | 
			
		||||
    def set_flag(self, flag):
 | 
			
		||||
        self.flags |= flag
 | 
			
		||||
 | 
			
		||||
    def clear_flag(self, flag):
 | 
			
		||||
        self.flags &= ~flag
 | 
			
		||||
 | 
			
		||||
    def set_dependents(self, dlist):
 | 
			
		||||
        self.dependents = dlist
 | 
			
		||||
 | 
			
		||||
    def get_dependents(self):
 | 
			
		||||
        return self.dependents
 | 
			
		||||
 | 
			
		||||
    def set_linkstate(self, l):
 | 
			
		||||
        self.linkstate = l
 | 
			
		||||
 | 
			
		||||
    def get_linkstate(self):
 | 
			
		||||
        return self.linkstate
 | 
			
		||||
 | 
			
		||||
    def run_children(self, stage, module_list, force=0):
 | 
			
		||||
 | 
			
		||||
        if (self.is_flag_on(ifaceFlags.FOLLOW_DEPENDENTS)
 | 
			
		||||
                == False):
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        for c in self.children:
 | 
			
		||||
            self.set_flag(
 | 
			
		||||
                ifaceFlags.FOLLOW_DEPENDENTS)
 | 
			
		||||
            ret = c.run(stage, module_list, force)
 | 
			
		||||
            self.clear_flag(
 | 
			
		||||
                ifaceFlags.FOLLOW_DEPENDENTS)
 | 
			
		||||
 | 
			
		||||
            if ret != 0:
 | 
			
		||||
                self.set_state(stage, ret)
 | 
			
		||||
                if force == 0:
 | 
			
		||||
                    break
 | 
			
		||||
 | 
			
		||||
        return ret
 | 
			
		||||
 | 
			
		||||
    def run(self, stage, module_list, force=0):
 | 
			
		||||
        ret = 0
 | 
			
		||||
        err = 0
 | 
			
		||||
 | 
			
		||||
        ret = self.run_children()
 | 
			
		||||
 | 
			
		||||
        if ret != 0 and force == 0:
 | 
			
		||||
            return ret
 | 
			
		||||
            
 | 
			
		||||
        for m in module_list:
 | 
			
		||||
            ret = m.run(self, stage, force)
 | 
			
		||||
            if ret != 0:
 | 
			
		||||
                self.set_state(stage, ret)
 | 
			
		||||
 | 
			
		||||
                # If no force, return!
 | 
			
		||||
                if force == 0:
 | 
			
		||||
                    return -1
 | 
			
		||||
                err += 1
 | 
			
		||||
            else:
 | 
			
		||||
                self.set_state(stage, ret)
 | 
			
		||||
 | 
			
		||||
        return ret
 | 
			
		||||
 | 
			
		||||
    def get_attr_value(self, attr_name):
 | 
			
		||||
        config = self.get_config()
 | 
			
		||||
 | 
			
		||||
        return config.get(attr_name)
 | 
			
		||||
    
 | 
			
		||||
    def get_attr_value_first(self, attr_name):
 | 
			
		||||
        config = self.get_config()
 | 
			
		||||
 | 
			
		||||
        attr_value_list = config.get(attr_name)
 | 
			
		||||
        if attr_value_list is not None:
 | 
			
		||||
            return attr_value_list[0]
 | 
			
		||||
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
    def get_attr_value_n(self, attr_name, attr_index):
 | 
			
		||||
        config = self.get_config()
 | 
			
		||||
 | 
			
		||||
        attr_value_list = config.get(attr_name)
 | 
			
		||||
        if attr_value_list is not None:
 | 
			
		||||
            try:
 | 
			
		||||
                return attr_value_list[attr_index]
 | 
			
		||||
            except:
 | 
			
		||||
                return None
 | 
			
		||||
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
    def get_env(self):
 | 
			
		||||
        if self.env is None or len(self.env) == 0:
 | 
			
		||||
            self.generate_env()
 | 
			
		||||
        return self.env
 | 
			
		||||
 | 
			
		||||
    def set_env(self, env):
 | 
			
		||||
        self.env = env
 | 
			
		||||
 | 
			
		||||
    def generate_env(self):
 | 
			
		||||
        env = {}
 | 
			
		||||
        config = self.get_config()
 | 
			
		||||
        env['IFACE'] = self.get_name()
 | 
			
		||||
        for attr, attr_value in config.items():
 | 
			
		||||
            attr_env_name = 'IF_%s' %attr.upper()
 | 
			
		||||
            env[attr_env_name] = attr_value[0]
 | 
			
		||||
 | 
			
		||||
        if len(env) > 0:
 | 
			
		||||
            self.set_env(env)
 | 
			
		||||
 | 
			
		||||
    def update_config(self, attr_name, attr_value, attr_status=None):
 | 
			
		||||
        if attr_value is None:
 | 
			
		||||
            attr_value = ''
 | 
			
		||||
 | 
			
		||||
        if attr_status == None:
 | 
			
		||||
            attr_status_str = ''
 | 
			
		||||
        elif attr_status == 0:
 | 
			
		||||
            attr_status_str = ' (success)'
 | 
			
		||||
        elif attr_status != 0:
 | 
			
		||||
            attr_status_str = ' (error)'
 | 
			
		||||
 | 
			
		||||
        self.config[attr_name] = attr_value + attr_status_str
 | 
			
		||||
 | 
			
		||||
    def dump_raw(self, logger):
 | 
			
		||||
        indent = '  '
 | 
			
		||||
        print (self.raw_lines[0])
 | 
			
		||||
        for i in range(1, len(self.raw_lines)):
 | 
			
		||||
            print (indent + self.raw_lines[i])
 | 
			
		||||
        
 | 
			
		||||
    def dump_state_pretty(self, logger):
 | 
			
		||||
        indent = '  '
 | 
			
		||||
        logger.info('iface %s' %self.get_name())
 | 
			
		||||
        for attr_name, attr_value in self.get_config_current().items():
 | 
			
		||||
            print (indent + '%s' %attr_name + ' %s' %attr_value)
 | 
			
		||||
 | 
			
		||||
    def dump(self, logger):
 | 
			
		||||
        indent = '\t'
 | 
			
		||||
        logger.info(self.get_name() + ' : {')
 | 
			
		||||
        logger.info(indent + 'family: %s' %self.get_addr_family())
 | 
			
		||||
        logger.info(indent + 'method: %s' %self.get_addr_method())
 | 
			
		||||
        logger.info(indent + 'state: %s'
 | 
			
		||||
                %ifaceState.to_str(self.get_state()))
 | 
			
		||||
        logger.info(indent + 'status: %s'
 | 
			
		||||
                %ifaceStatus.to_str(self.get_status()))
 | 
			
		||||
        logger.info(indent + 'refcnt: %d' %self.get_refcnt())
 | 
			
		||||
        d = self.get_dependents()
 | 
			
		||||
        if d is not None:
 | 
			
		||||
            logger.info(indent + 'dependents: %s' %str(d))
 | 
			
		||||
        else:
 | 
			
		||||
            logger.info(indent + 'dependents: None')
 | 
			
		||||
 | 
			
		||||
        logger.info(indent + 'config: ')
 | 
			
		||||
        config = self.get_config()
 | 
			
		||||
        if config is not None:
 | 
			
		||||
            logger.info(indent + indent + str(config))
 | 
			
		||||
        logger.info('}')
 | 
			
		||||
 | 
			
		||||
    def dump_pretty(self, logger):
 | 
			
		||||
        indent = '\t'
 | 
			
		||||
        outbuf = 'iface %s' %self.get_name()
 | 
			
		||||
        if self.get_addr_family() is not None:
 | 
			
		||||
            outbuf += ' %s' %self.get_addr_family()
 | 
			
		||||
 | 
			
		||||
        if self.get_addr_method() is not None:
 | 
			
		||||
            outbuf += ' %s' %self.get_addr_method()
 | 
			
		||||
 | 
			
		||||
        outbuf += '\n'
 | 
			
		||||
 | 
			
		||||
        config = self.get_config()
 | 
			
		||||
        if config is not None:
 | 
			
		||||
            for cname, cvalue in config.items():
 | 
			
		||||
                outbuf += indent + '%s' %cname + ' %s\n' %cvalue
 | 
			
		||||
 | 
			
		||||
        #outbuf += ('%s' %indent + '%s' %self.get_state_str() +
 | 
			
		||||
        #                ' %s' %self.get_status_str())
 | 
			
		||||
 | 
			
		||||
        print outbuf
 | 
			
		||||
							
								
								
									
										665
									
								
								pkg/ifupdown_main.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										665
									
								
								pkg/ifupdown_main.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,665 @@
 | 
			
		||||
#!/usr/bin/python
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
import re
 | 
			
		||||
from statemanager import *
 | 
			
		||||
from networkinterfaces import *
 | 
			
		||||
from iface import *
 | 
			
		||||
from scheduler import *
 | 
			
		||||
from collections import deque
 | 
			
		||||
from collections import OrderedDict
 | 
			
		||||
import imp
 | 
			
		||||
import pprint
 | 
			
		||||
import logging
 | 
			
		||||
from graph import *
 | 
			
		||||
import sys, traceback
 | 
			
		||||
 | 
			
		||||
class ifupdown_main():
 | 
			
		||||
 | 
			
		||||
    # Flags
 | 
			
		||||
    FORCE = False
 | 
			
		||||
    NOWAIT = False
 | 
			
		||||
    DRYRUN = False
 | 
			
		||||
    NODEPENDS = False
 | 
			
		||||
    ALL = False
 | 
			
		||||
    STATE_CHECK = True
 | 
			
		||||
 | 
			
		||||
    modules_dir='/etc/network'
 | 
			
		||||
    builtin_modules_dir='/usr/share/ifupdownaddons'
 | 
			
		||||
 | 
			
		||||
    # iface dictionary in the below format:
 | 
			
		||||
    # { '<ifacename>' : [<ifaceobject1>, <ifaceobject2> ..] }
 | 
			
		||||
    # eg:
 | 
			
		||||
    # { 'swp1' : [<ifaceobject1>, <ifaceobject2> ..] }
 | 
			
		||||
    #
 | 
			
		||||
    # Each ifaceobject corresponds to a configuration block for
 | 
			
		||||
    # that interface
 | 
			
		||||
    ifaceobjdict = OrderedDict()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    # iface dictionary representing the curr running state of an iface
 | 
			
		||||
    # in the below format:
 | 
			
		||||
    # {'<ifacename>' : <ifaceobject>}
 | 
			
		||||
    ifaceobjcurrdict = OrderedDict()
 | 
			
		||||
 | 
			
		||||
    # Dictionary representing operation, sub operation and modules
 | 
			
		||||
    # for every sub operation
 | 
			
		||||
    operations = { 'up' :
 | 
			
		||||
                    OrderedDict([('pre-up', OrderedDict({})),
 | 
			
		||||
                                 ('up' , OrderedDict({})),
 | 
			
		||||
                                 ('post-up' , OrderedDict({}))]),
 | 
			
		||||
                   'down' :
 | 
			
		||||
                    OrderedDict([('pre-down', OrderedDict({})),
 | 
			
		||||
                                 ('down' , OrderedDict({})),
 | 
			
		||||
                                 ('post-down' , OrderedDict({}))])}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.logger = logging.getLogger('ifupdown')
 | 
			
		||||
 | 
			
		||||
        self.ifaces = OrderedDict()
 | 
			
		||||
        self.njobs = 1
 | 
			
		||||
        self.pp = pprint.PrettyPrinter(indent=4)
 | 
			
		||||
        self.load_modules_builtin(self.builtin_modules_dir)
 | 
			
		||||
        self.load_modules(self.modules_dir)
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            self.statemanager = stateManager()
 | 
			
		||||
            self.statemanager.read_saved_state()
 | 
			
		||||
        except Exception, e:
 | 
			
		||||
            # XXX Maybe we should continue by ignoring old state
 | 
			
		||||
            self.logger.warning('error reading state (%s)' %str(e))
 | 
			
		||||
            raise
 | 
			
		||||
 | 
			
		||||
    def get_subops(self, op):
 | 
			
		||||
        """ Returns sub-operation list """
 | 
			
		||||
        return self.operations.get(op).keys()
 | 
			
		||||
 | 
			
		||||
    def compat_conv_op_to_mode(self, op):
 | 
			
		||||
        """ Returns old op name to work with existing scripts """
 | 
			
		||||
        if op == 'up':
 | 
			
		||||
            return 'start'
 | 
			
		||||
        elif op == 'down':
 | 
			
		||||
            return 'stop'
 | 
			
		||||
        else:
 | 
			
		||||
            return op
 | 
			
		||||
 | 
			
		||||
    def set_force(self, force):
 | 
			
		||||
        """ Set force flag. """
 | 
			
		||||
        if force == True:
 | 
			
		||||
            self.logger.debug('setting force to true')
 | 
			
		||||
        self.FORCE = force
 | 
			
		||||
 | 
			
		||||
    def get_force(self):
 | 
			
		||||
        """ return force flag. """
 | 
			
		||||
        return self.FORCE
 | 
			
		||||
 | 
			
		||||
    def set_dryrun(self, dryrun):
 | 
			
		||||
        if dryrun == True:
 | 
			
		||||
            self.logger.debug('setting dryrun to true')
 | 
			
		||||
        self.DRYRUN = dryrun
 | 
			
		||||
 | 
			
		||||
    def get_dryrun(self):
 | 
			
		||||
        return self.DRYRUN
 | 
			
		||||
 | 
			
		||||
    def set_nowait(self, nowait):
 | 
			
		||||
        if nowait == True:
 | 
			
		||||
            self.logger.debug('setting dryrun to true')
 | 
			
		||||
        self.NOWAIT = nowait
 | 
			
		||||
 | 
			
		||||
    def get_nowait(self):
 | 
			
		||||
        return self.NOWAIT
 | 
			
		||||
 | 
			
		||||
    def set_njobs(self, njobs):
 | 
			
		||||
        self.logger.debug('setting njobs to %d' %njobs)
 | 
			
		||||
        self.njobs = njobs
 | 
			
		||||
 | 
			
		||||
    def get_njobs(self):
 | 
			
		||||
        return self.njobs
 | 
			
		||||
 | 
			
		||||
    def ignore_error(self, errmsg):
 | 
			
		||||
        if (self.FORCE == True or re.search(r'exists', errmsg,
 | 
			
		||||
            re.IGNORECASE | re.MULTILINE) is not None):
 | 
			
		||||
            return True
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    def get_nodepends(self):
 | 
			
		||||
        return self.NODEPENDS
 | 
			
		||||
 | 
			
		||||
    def set_nodepends(self, nodepends):
 | 
			
		||||
        self.logger.debug('setting nodepends to true')
 | 
			
		||||
        self.NODEPENDS = nodepends
 | 
			
		||||
 | 
			
		||||
    def set_iface_state(self, ifaceobj, state, status):
 | 
			
		||||
        ifaceobj.set_state(state)
 | 
			
		||||
        ifaceobj.set_status(status)
 | 
			
		||||
        self.statemanager.update_iface_state(ifaceobj)
 | 
			
		||||
 | 
			
		||||
    def get_iface_objs(self, ifacename):
 | 
			
		||||
        return self.ifaceobjdict.get(ifacename)
 | 
			
		||||
 | 
			
		||||
    def get_iface_obj_first(self, ifacename):
 | 
			
		||||
        ifaceobjs = self.get_iface_objs(ifacename)
 | 
			
		||||
        if ifaceobjs is not None:
 | 
			
		||||
            return ifaceobjs[0]
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
    def get_iface_obj_last(self, ifacename):
 | 
			
		||||
        return self.ifaceobjdict.get(ifacename)[-1]
 | 
			
		||||
 | 
			
		||||
    def create_ifaceobjcurr(self, ifacename):
 | 
			
		||||
        ifaceobj = self.get_ifaceobjcurr(ifacename)
 | 
			
		||||
        if ifaceobj is not None:
 | 
			
		||||
            return ifaceobj
 | 
			
		||||
 | 
			
		||||
        ifaceobj = iface()
 | 
			
		||||
        ifaceobj.set_name(ifacename)
 | 
			
		||||
        self.ifaceobjcurrdict[ifacename] = ifaceobj
 | 
			
		||||
 | 
			
		||||
        return ifaceobj
 | 
			
		||||
 | 
			
		||||
    def get_ifaceobjcurr(self, ifacename):
 | 
			
		||||
        return self.ifaceobjcurrdict.get(ifacename)
 | 
			
		||||
 | 
			
		||||
    def get_iface_status(self, ifacename):
 | 
			
		||||
        ifaceobjs = self.get_iface_objs(ifacename)
 | 
			
		||||
        for i in ifaceobjs:
 | 
			
		||||
            if i.get_status() != ifaceStatus.SUCCESS:
 | 
			
		||||
                return i.get_status()
 | 
			
		||||
 | 
			
		||||
        return ifaceStatus.SUCCESS
 | 
			
		||||
 | 
			
		||||
    def get_iface_refcnt(self, ifacename):
 | 
			
		||||
        max = 0
 | 
			
		||||
        ifaceobjs = self.get_iface_objs(ifacename)
 | 
			
		||||
        for i in ifaceobjs:
 | 
			
		||||
            if i.get_refcnt() > max:
 | 
			
		||||
                max = i.get_refcnt()
 | 
			
		||||
        return max
 | 
			
		||||
 | 
			
		||||
    def create_fake_vlan_iface(self, vlan_ifname, op):
 | 
			
		||||
        """ creates and returns a fake vlan iface object.
 | 
			
		||||
 | 
			
		||||
        This was added to support creation of simple vlan devices without any
 | 
			
		||||
        user specified configuration.
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        # XXX: Ideally this should be a call-back into the vlan module.
 | 
			
		||||
        vlan_iface_obj = iface()
 | 
			
		||||
        vlan_iface_obj.set_name(vlan_ifname)
 | 
			
		||||
        vlan_iface_obj.set_dependents(self.get_dependents(vlan_iface_obj, op))
 | 
			
		||||
 | 
			
		||||
        return vlan_iface_obj
 | 
			
		||||
 | 
			
		||||
    def is_vlan_device(self, ifacename):
 | 
			
		||||
        """ Returns true if iface name is a vlan interface.
 | 
			
		||||
        
 | 
			
		||||
        only supports vlan interfaces of the format <ifacename>.<vlanid>
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
        if (re.search(r'\.', ifacename, 0) is not None):
 | 
			
		||||
            return True
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    def preprocess_dependency_list(self, dlist, op):
 | 
			
		||||
        del_list = []
 | 
			
		||||
 | 
			
		||||
        self.logger.debug('pre-processing dependency list: %s' %list(dlist))
 | 
			
		||||
        for d in dlist:
 | 
			
		||||
            dilist = self.get_iface_objs(d)
 | 
			
		||||
            if dilist == None:
 | 
			
		||||
                if self.is_vlan_device(d) == True:
 | 
			
		||||
                    vlan_iface_obj = self.create_fake_vlan_iface(d, op)
 | 
			
		||||
 | 
			
		||||
                    # Add face vlan device to ifaceobjdict dict
 | 
			
		||||
                    vlan_iface_obj.inc_refcnt()
 | 
			
		||||
                    self.save_iface(vlan_iface_obj)
 | 
			
		||||
                else:
 | 
			
		||||
                    # Remove the device from the list
 | 
			
		||||
                    del_list.append(d)
 | 
			
		||||
            else:
 | 
			
		||||
                for di in dilist:
 | 
			
		||||
                    di.inc_refcnt()
 | 
			
		||||
 | 
			
		||||
        for d in del_list:
 | 
			
		||||
            dlist.remove(d)
 | 
			
		||||
 | 
			
		||||
        self.logger.debug('After Processing dependency list: %s'
 | 
			
		||||
            %list(dlist))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def get_dependents(self, ifaceobj, op):
 | 
			
		||||
        """ Gets iface dependents by calling into respective modules """
 | 
			
		||||
        dlist = None
 | 
			
		||||
 | 
			
		||||
        self.logger.debug('%s: ' %ifaceobj.get_name() + 'getting dependency')
 | 
			
		||||
 | 
			
		||||
        # Get dependents for interface by querying respective modules
 | 
			
		||||
        subopdict = self.operations.get(op)
 | 
			
		||||
        for subop, mdict in subopdict.items():
 | 
			
		||||
            for mname, mdata  in mdict.items():
 | 
			
		||||
                if mdata.get('ftype') == 'pmodule':
 | 
			
		||||
                    module = mdata.get('module')
 | 
			
		||||
                    if (hasattr(module,
 | 
			
		||||
                        'get_dependent_ifacenames') == False):
 | 
			
		||||
                        continue
 | 
			
		||||
                    dlist = module.get_dependent_ifacenames(ifaceobj,
 | 
			
		||||
                                    self.ifaceobjdict.keys())
 | 
			
		||||
                    if dlist:
 | 
			
		||||
                        self.logger.debug('%s: ' %ifaceobj.get_name() +
 | 
			
		||||
                                'got dependency list: %s' %str(dlist))
 | 
			
		||||
                        break
 | 
			
		||||
 | 
			
		||||
        return dlist
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    def generate_dependency_info(self, ifacenames, dependency_graph, op):
 | 
			
		||||
        """ recursive function to generate iface dependency info """
 | 
			
		||||
 | 
			
		||||
        self.logger.debug('generating dependency info for %s' %str(ifacenames))
 | 
			
		||||
 | 
			
		||||
        for i in ifacenames:
 | 
			
		||||
            # Go through all modules and find dependent ifaces
 | 
			
		||||
            dlist = None
 | 
			
		||||
            ifaceobj = self.get_iface_obj_first(i)
 | 
			
		||||
            if ifaceobj is None: 
 | 
			
		||||
                continue
 | 
			
		||||
 | 
			
		||||
            dlist = ifaceobj.get_dependents()
 | 
			
		||||
            if dlist is None:
 | 
			
		||||
                dlist = self.get_dependents(ifaceobj, op)
 | 
			
		||||
 | 
			
		||||
            if dlist is not None:
 | 
			
		||||
                self.preprocess_dependency_list(dlist, op)
 | 
			
		||||
                ifaceobj.set_dependents(dlist)
 | 
			
		||||
 | 
			
		||||
            if dependency_graph.get(i) is None:
 | 
			
		||||
                dependency_graph[i] = dlist
 | 
			
		||||
 | 
			
		||||
            if dlist is not None:
 | 
			
		||||
                self.generate_dependency_info(dlist,
 | 
			
		||||
                         dependency_graph, op)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def is_valid_state_transition(self, ifname, to_be_state):
 | 
			
		||||
        return self.statemanager.is_valid_state_transition(ifname,
 | 
			
		||||
                to_be_state)
 | 
			
		||||
 | 
			
		||||
    def save_iface(self, ifaceobj):
 | 
			
		||||
        if self.ifaceobjdict.get(ifaceobj.get_name()) is None:
 | 
			
		||||
            self.ifaceobjdict[ifaceobj.get_name()] = [ifaceobj]
 | 
			
		||||
        else:
 | 
			
		||||
            self.ifaceobjdict[ifaceobj.get_name()].append(ifaceobj)
 | 
			
		||||
 | 
			
		||||
    def read_default_iface_config(self):
 | 
			
		||||
        """ Reads default network interface config /etc/network/interfaces. """
 | 
			
		||||
        nifaces = networkInterfaces()
 | 
			
		||||
        nifaces.subscribe('iface_found', self.save_iface)
 | 
			
		||||
        nifaces.load()
 | 
			
		||||
 | 
			
		||||
    def read_iface_config(self):
 | 
			
		||||
        return self.read_default_iface_config()
 | 
			
		||||
 | 
			
		||||
    def read_old_iface_config(self):
 | 
			
		||||
        """ Reads the saved iface config instead of default iface config. """
 | 
			
		||||
 | 
			
		||||
        # Read it from the statemanager
 | 
			
		||||
        self.ifaceobjdict = self.statemanager.get_ifaceobjdict()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def save_module(self, mkind, msubkind, mname, mftype, module):
 | 
			
		||||
        """ saves a module into internal module dict for later use.
 | 
			
		||||
        
 | 
			
		||||
        mtype - pre-up.d, post-up.d and so on
 | 
			
		||||
        mftype - pmodule (python module), bashscript (bash script)
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        mmetadata = self.operations[mkind][msubkind].get(mname)
 | 
			
		||||
        if mmetadata is None or mmetadata.get('ftype') != 'pmodule':
 | 
			
		||||
            mmetadata = {}
 | 
			
		||||
            mmetadata['ftype'] = mftype
 | 
			
		||||
            mmetadata['module'] = module
 | 
			
		||||
            self.operations[mkind][msubkind][mname] = mmetadata
 | 
			
		||||
 | 
			
		||||
            self.logger.debug('saved module %s' %mkind +
 | 
			
		||||
                             ' %s' %mname + ' %s' %mftype)
 | 
			
		||||
        else:
 | 
			
		||||
            self.logger.warn('ignoring module %s' %mkind + ' %s' %msubkind +
 | 
			
		||||
                        ' %s' %mname + ' of type %s' %mftype)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def load_modules_builtin(self, modules_dir):
 | 
			
		||||
        """ load python modules from modules_dir
 | 
			
		||||
 | 
			
		||||
        Default modules_dir is /usr/share/ifupdownmodules
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        self.logger.info('loading builtin modules from %s' %modules_dir)
 | 
			
		||||
 | 
			
		||||
        if not modules_dir in sys.path:
 | 
			
		||||
                sys.path.append(modules_dir)
 | 
			
		||||
        try:
 | 
			
		||||
            module_list = os.listdir(modules_dir)
 | 
			
		||||
            for module in module_list:
 | 
			
		||||
                if re.search('.*\.pyc', module, 0) != None:
 | 
			
		||||
                    continue
 | 
			
		||||
 | 
			
		||||
                mname, mext = os.path.splitext(module)
 | 
			
		||||
                if mext is not None and mext == '.py':
 | 
			
		||||
                    self.logger.info('loading ' + modules_dir + '/' + module)
 | 
			
		||||
                    try:
 | 
			
		||||
                        m = __import__(mname)
 | 
			
		||||
                        mclass = getattr(m, mname)
 | 
			
		||||
                    except:
 | 
			
		||||
                        raise
 | 
			
		||||
                        
 | 
			
		||||
                    minstance = mclass(force=self.get_force(),
 | 
			
		||||
                                       dryrun=self.get_dryrun(),
 | 
			
		||||
                                       nowait=self.get_nowait())
 | 
			
		||||
                    ops = minstance.get_ops()
 | 
			
		||||
                    for op in ops:
 | 
			
		||||
                        if re.search('up', op) is not None:
 | 
			
		||||
                            self.save_module('up', op, mname, 'pmodule',
 | 
			
		||||
                                             minstance)
 | 
			
		||||
                        else:
 | 
			
		||||
                            self.save_module('down', op, mname, 'pmodule',
 | 
			
		||||
                                             minstance)
 | 
			
		||||
        except: 
 | 
			
		||||
            raise
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def load_modules(self, modules_dir):
 | 
			
		||||
        """ loading user modules from /etc/network/.
 | 
			
		||||
 | 
			
		||||
        Note that previously loaded python modules override modules found
 | 
			
		||||
        under /etc/network if any
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        self.logger.info('loading user modules from %s' %modules_dir)
 | 
			
		||||
        for op, subops in self.operations.items():
 | 
			
		||||
            for subop in subops.keys():
 | 
			
		||||
                msubdir = modules_dir + '/if-%s.d' %subop
 | 
			
		||||
                self.logger.info('loading modules under %s ...' %msubdir)
 | 
			
		||||
                try:
 | 
			
		||||
                    module_list = os.listdir(msubdir)
 | 
			
		||||
                    for module in module_list:
 | 
			
		||||
                        if re.search('.*\.pyc', module, 0) != None:
 | 
			
		||||
                            continue
 | 
			
		||||
 | 
			
		||||
                        mname, mext = os.path.splitext(module)
 | 
			
		||||
                        if mext is not None and mext == '.py':
 | 
			
		||||
                            self.logger.debug('loading ' + msubdir + '/' + module)
 | 
			
		||||
                            try:
 | 
			
		||||
                                m = imp.load_source(module,
 | 
			
		||||
                                        msubdir + '/' + module)
 | 
			
		||||
                                mclass = getattr(m, mname)
 | 
			
		||||
                            except:
 | 
			
		||||
                                raise
 | 
			
		||||
                            minstance = mclass()
 | 
			
		||||
                            self.save_module(op, subop, mname, 'pmodule',
 | 
			
		||||
                                                minstance)
 | 
			
		||||
                        else:
 | 
			
		||||
                            self.save_module(op, subop, mname, 'script',
 | 
			
		||||
                                    msubdir + '/' + module)
 | 
			
		||||
                except: 
 | 
			
		||||
                    raise
 | 
			
		||||
 | 
			
		||||
        #self.logger.debug('modules ...')
 | 
			
		||||
        #self.pp.pprint(self.operations)
 | 
			
		||||
 | 
			
		||||
        # For query, we add a special entry, basically use all 'up' modules
 | 
			
		||||
        self.operations['query'] = self.operations.get('up')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def conv_iface_namelist_to_objlist(self, intf_list):
 | 
			
		||||
        for intf in intf_list:
 | 
			
		||||
            iface_obj = self.get_iface(intf)
 | 
			
		||||
            if iface_obj == None:
 | 
			
		||||
                raise ifupdownInvalidValue('no iface %s', intf)
 | 
			
		||||
 | 
			
		||||
            iface_objs.append(iface_obj)
 | 
			
		||||
 | 
			
		||||
        return iface_objs
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def run_without_dependents(self, op, ifacenames):
 | 
			
		||||
        ifaceSched = ifaceScheduler()
 | 
			
		||||
 | 
			
		||||
        self.logger.debug('run_without_dependents for op %s' %op +
 | 
			
		||||
                ' for %s' %str(ifacenames))
 | 
			
		||||
 | 
			
		||||
        if ifacenames == None:
 | 
			
		||||
            raise ifupdownInvalidValue('no interfaces found')
 | 
			
		||||
 | 
			
		||||
        return ifaceSched.run_iface_list(self, ifacenames, op)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def run_with_dependents(self, op, ifacenames):
 | 
			
		||||
        dependency_graph = {}
 | 
			
		||||
        ret = 0
 | 
			
		||||
        self.logger.debug('run_with_dependents for op %s'
 | 
			
		||||
                          %op + ' for %s' %str(ifacenames))
 | 
			
		||||
 | 
			
		||||
        ifaceSched = ifaceScheduler()
 | 
			
		||||
 | 
			
		||||
        if ifacenames is None:
 | 
			
		||||
            ifacenames = self.ifaceobjdict.keys()
 | 
			
		||||
 | 
			
		||||
        # generate dependency graph of interfaces
 | 
			
		||||
        self.generate_dependency_info(ifacenames, dependency_graph, op)
 | 
			
		||||
 | 
			
		||||
        if self.logger.isEnabledFor(logging.DEBUG) == True:
 | 
			
		||||
            self.logger.debug('dependency graph:')
 | 
			
		||||
            self.pp.pprint(dependency_graph)
 | 
			
		||||
 | 
			
		||||
        if self.njobs > 1:
 | 
			
		||||
            ret = ifaceSched.run_iface_dependency_graph_parallel(self,
 | 
			
		||||
                        dependency_graph, op)
 | 
			
		||||
        else:
 | 
			
		||||
            ret = ifaceSched.run_iface_dependency_graph(self, dependency_graph,
 | 
			
		||||
                        op)
 | 
			
		||||
 | 
			
		||||
        return ret
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def validate_ifaces(self, ifacenames):
 | 
			
		||||
        """ validates interface list for config existance.
 | 
			
		||||
       
 | 
			
		||||
        returns -1 if one or more interface not found. else, returns 0
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        err_iface = ''
 | 
			
		||||
        for i in ifacenames:
 | 
			
		||||
            ifaceobjs = self.get_iface_objs(i)
 | 
			
		||||
            if ifaceobjs is None:
 | 
			
		||||
                err_iface += ' ' + i
 | 
			
		||||
 | 
			
		||||
        if len(err_iface) != 0:
 | 
			
		||||
            self.logger.error('cound not find ifaces: %s' %err_iface)
 | 
			
		||||
            return -1
 | 
			
		||||
 | 
			
		||||
        return 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def iface_whitelisted(self, auto, allow_classes, ifacename):
 | 
			
		||||
        """ Checks if interface is whitelisted depending on set of parameters.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        interfaces are checked against the allow_classes and auto lists.
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        self.logger.debug('checking if iface %s' %ifacename +
 | 
			
		||||
                ' is whitelisted')
 | 
			
		||||
 | 
			
		||||
        ifaceobjs = self.get_iface_objs(ifacename)
 | 
			
		||||
        if ifaceobjs is None:
 | 
			
		||||
            self.logger.debug('iface %s' %ifacename + ' not found')
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        # We check classes first
 | 
			
		||||
        if allow_classes is not None and len(allow_classes) > 0:
 | 
			
		||||
            for i in ifaceobjs:
 | 
			
		||||
                if (len(i.get_classes()) > 0):
 | 
			
		||||
                    common = Set(allow_classes).intersection(
 | 
			
		||||
                                Set(i.get_classes()))
 | 
			
		||||
                    if len(common) > 0:
 | 
			
		||||
                        return True
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        if auto == True:
 | 
			
		||||
            for i in ifaceobjs:
 | 
			
		||||
                if i.get_auto() == True:
 | 
			
		||||
                    return True
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    def generate_running_env(self, ifaceobj, op):
 | 
			
		||||
        """ Generates a dictionary with env variables required for an interface.
 | 
			
		||||
 | 
			
		||||
        Used to support script execution for interfaces.
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        cenv = None
 | 
			
		||||
        iface_env = ifaceobj.get_env()
 | 
			
		||||
        if iface_env is not None:
 | 
			
		||||
            cenv = os.environ
 | 
			
		||||
            if cenv is not None:
 | 
			
		||||
                cenv.update(iface_env)
 | 
			
		||||
            else:
 | 
			
		||||
                cenv = iface_env
 | 
			
		||||
 | 
			
		||||
            cenv['MODE'] = self.compat_conv_op_to_mode(op)
 | 
			
		||||
 | 
			
		||||
        return cenv
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def run(self, op, auto=False, allow_classes=None,
 | 
			
		||||
            ifacenames=None, query_state=None):
 | 
			
		||||
        """ main ifupdown run method """
 | 
			
		||||
 | 
			
		||||
        if auto == True:
 | 
			
		||||
            self.logger.debug('setting flag ALL')
 | 
			
		||||
            self.ALL = True
 | 
			
		||||
 | 
			
		||||
        # Only read new iface config for 'up'
 | 
			
		||||
        # operations. For 'downs' we only rely on
 | 
			
		||||
        # old state
 | 
			
		||||
        if op == 'up' or op == 'query':
 | 
			
		||||
            try:
 | 
			
		||||
                self.read_iface_config()
 | 
			
		||||
            except Exception, e:
 | 
			
		||||
                raise
 | 
			
		||||
        else:
 | 
			
		||||
            # for down we need to look at old state
 | 
			
		||||
            self.logger.debug('down op, looking at old state ..')
 | 
			
		||||
 | 
			
		||||
            if len(self.statemanager.get_ifaceobjdict()) > 0:
 | 
			
		||||
                self.read_old_iface_config()
 | 
			
		||||
            elif self.FORCE == True:
 | 
			
		||||
                # If no old state available 
 | 
			
		||||
                self.logger.info('old state not available. Force option ' +
 | 
			
		||||
                        'set. Loading new iface config file')
 | 
			
		||||
                try:
 | 
			
		||||
                    self.read_iface_config()
 | 
			
		||||
                except Exception, e:
 | 
			
		||||
                    raise Exception('error reading iface config (%s)' %str(e))
 | 
			
		||||
            else:
 | 
			
		||||
                raise Exception('old state not available...aborting.' +
 | 
			
		||||
                        ' try running with --force option')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        if ifacenames is not None:
 | 
			
		||||
            # If iface list is given, always check if iface is present
 | 
			
		||||
           if self.validate_ifaces(ifacenames) != 0:
 | 
			
		||||
               raise Exception('all or some ifaces not found')
 | 
			
		||||
 | 
			
		||||
        # if iface list not given by user, assume all from config file
 | 
			
		||||
        if ifacenames is None: ifacenames = self.ifaceobjdict.keys()
 | 
			
		||||
 | 
			
		||||
        # filter interfaces based on auto and allow classes
 | 
			
		||||
        filtered_ifacenames = [i for i in ifacenames
 | 
			
		||||
             if self.iface_whitelisted(auto, allow_classes, i) == True]
 | 
			
		||||
 | 
			
		||||
        if len(filtered_ifacenames) == 0:
 | 
			
		||||
                raise Exception('no ifaces found matching ' +
 | 
			
		||||
                        'given allow lists')
 | 
			
		||||
 | 
			
		||||
        if op == 'query':
 | 
			
		||||
            if query_state == None:
 | 
			
		||||
                return self.print_ifaceobjs_pretty(filtered_ifacenames)
 | 
			
		||||
            elif query_state == 'presumed':
 | 
			
		||||
                return self.print_ifaceobjs_saved_state_pretty(
 | 
			
		||||
                                    filtered_ifacenames)
 | 
			
		||||
            elif query_state == 'presumeddetailed':
 | 
			
		||||
                return self.print_ifaceobjs_saved_state_detailed_pretty(
 | 
			
		||||
                                    filtered_ifacenames)
 | 
			
		||||
 | 
			
		||||
        if op == 'query' or self.NODEPENDS == True:
 | 
			
		||||
            self.run_without_dependents(op, filtered_ifacenames)
 | 
			
		||||
        else:
 | 
			
		||||
            self.run_with_dependents(op, filtered_ifacenames)
 | 
			
		||||
 | 
			
		||||
        if op == 'query':
 | 
			
		||||
            if query_state == 'curr':
 | 
			
		||||
                return self.print_ifaceobjscurr_pretty(filtered_ifacenames)
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        # Update persistant iface states
 | 
			
		||||
        try:
 | 
			
		||||
            if self.ALL == True:
 | 
			
		||||
                self.statemanager.flush_state(self.ifaceobjdict)
 | 
			
		||||
            else:
 | 
			
		||||
                self.statemanager.flush_state()
 | 
			
		||||
        except Exception, e:
 | 
			
		||||
            if self.logger.isEnabledFor(logging.DEBUG):
 | 
			
		||||
                t = sys.exc_info()[2]
 | 
			
		||||
                traceback.print_tb(t)
 | 
			
		||||
            self.logger.warning('error saving state (%s)' %str(e))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def up(self, auto=False, allow=None, ifacenames=None):
 | 
			
		||||
        return self.run('up', auto, allow, ifacenames)
 | 
			
		||||
 | 
			
		||||
    def down(self, auto=False, allow=None, ifacenames=None):
 | 
			
		||||
        return self.run('down', auto, allow, ifacenames);
 | 
			
		||||
 | 
			
		||||
    def query(self, auto=False, allow=None, ifacenames=None,
 | 
			
		||||
              query_state=False):
 | 
			
		||||
        return self.run('query', auto, allow, ifacenames,
 | 
			
		||||
                        query_state=query_state);
 | 
			
		||||
 | 
			
		||||
    def dump(self):
 | 
			
		||||
        """ all state dump """
 | 
			
		||||
 | 
			
		||||
        print 'ifupdown object dump'
 | 
			
		||||
        print self.pp.pprint(self.modules)
 | 
			
		||||
        print self.pp.pprint(self.ifaces)
 | 
			
		||||
        self.state_manager.dump()
 | 
			
		||||
 | 
			
		||||
    def print_state(self, ifacenames=None):
 | 
			
		||||
        self.statemanager.dump(ifacenames)
 | 
			
		||||
 | 
			
		||||
    def print_ifaceobjs_pretty(self, ifacenames):
 | 
			
		||||
        for i in ifacenames:
 | 
			
		||||
            ifaceobjs = self.get_iface_objs(i)
 | 
			
		||||
            for io in ifaceobjs:
 | 
			
		||||
                io.dump_raw(self.logger)
 | 
			
		||||
 | 
			
		||||
    def print_ifaceobjscurr_pretty(self, ifacenames):
 | 
			
		||||
        for i in ifacenames:
 | 
			
		||||
            ifaceobj = self.get_ifaceobjcurr(i)
 | 
			
		||||
            ifaceobj.dump_pretty(self.logger)
 | 
			
		||||
 | 
			
		||||
    def print_ifaceobjs_saved_state_pretty(self, ifacenames):
 | 
			
		||||
        self.statemanager.print_state_pretty(ifacenames, self.logger)
 | 
			
		||||
 | 
			
		||||
    def print_ifaceobjs_saved_state_detailed_pretty(self, ifacenames):
 | 
			
		||||
        self.statemanager.print_state_detailed_pretty(ifacenames, self.logger)
 | 
			
		||||
							
								
								
									
										35
									
								
								pkg/ifupdownbase.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								pkg/ifupdownbase.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
#!/usr/bin/python
 | 
			
		||||
 | 
			
		||||
import logging
 | 
			
		||||
import subprocess
 | 
			
		||||
import re
 | 
			
		||||
from ifupdown.iface import *
 | 
			
		||||
 | 
			
		||||
class ifupdownBase(object):
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        modulename = self.__class__.__name__
 | 
			
		||||
        self.logger = logging.getLogger('ifupdown.' + modulename)
 | 
			
		||||
 | 
			
		||||
    def exec_command(self, cmd, cmdenv=None, nowait=False):
 | 
			
		||||
        cmd_returncode = 0
 | 
			
		||||
        cmdout = ''
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            self.logger.debug('Executing ' + cmd)
 | 
			
		||||
            ch = subprocess.Popen(cmd.split(),
 | 
			
		||||
                    stdout=subprocess.PIPE,
 | 
			
		||||
                    shell=False, env=cmdenv,
 | 
			
		||||
                    stderr=subprocess.STDOUT)
 | 
			
		||||
            cmdout = ch.communicate()[0]
 | 
			
		||||
            cmd_returncode = ch.wait()
 | 
			
		||||
 | 
			
		||||
        except OSError, e:
 | 
			
		||||
            raise Exception('could not execute ' + cmd +
 | 
			
		||||
                    '(' + str(e) + ')')
 | 
			
		||||
 | 
			
		||||
        if cmd_returncode != 0:
 | 
			
		||||
            raise Exception('error executing cmd \'%s\'' %cmd +
 | 
			
		||||
                '\n(' + cmdout.strip('\n ') + ')')
 | 
			
		||||
 | 
			
		||||
        return cmdout
 | 
			
		||||
							
								
								
									
										28
									
								
								pkg/log.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								pkg/log.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
#!/usr/bin/python
 | 
			
		||||
 | 
			
		||||
import logging
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class log:
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def log_error(obj, prefix, *args, **kwargs):
 | 
			
		||||
        obj.get_logger().logger.log_error(''.join(args))
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def log_warn(obj, *args, **kwargs):
 | 
			
		||||
        msg = ''
 | 
			
		||||
        logger = obj.get_logger()
 | 
			
		||||
        errmsg = obj.get_errmsg()
 | 
			
		||||
        msg += ''.join(args)
 | 
			
		||||
        if errmsg is not None and len(errmsg) > 0:
 | 
			
		||||
            msg += '(%s)' %errmsg
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def log(obj, log_prefix, *args, **kwargs):
 | 
			
		||||
        msg = ''
 | 
			
		||||
        logger = obj.get_logger()
 | 
			
		||||
        msg += ''.join(args)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										210
									
								
								pkg/networkinterfaces.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								pkg/networkinterfaces.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,210 @@
 | 
			
		||||
#!/usr/bin/python
 | 
			
		||||
 | 
			
		||||
import collections
 | 
			
		||||
from iface import *
 | 
			
		||||
import logging
 | 
			
		||||
import glob
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class networkInterfaces():
 | 
			
		||||
 | 
			
		||||
    hotplugs = {}
 | 
			
		||||
    auto_ifaces = []
 | 
			
		||||
    callbacks = {}
 | 
			
		||||
 | 
			
		||||
    ifaces_file = "/etc/network/interfaces"
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.logger = logging.getLogger('ifupdown.' +
 | 
			
		||||
                    self.__class__.__name__)
 | 
			
		||||
        self.callbacks = {'iface_found' : None}
 | 
			
		||||
        self.allow_classes = {}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def subscribe(self, callback_name, callback_func):
 | 
			
		||||
        if callback_name not in self.callbacks.keys():
 | 
			
		||||
            print 'warning: invalid callback ' + callback_name
 | 
			
		||||
            return -1
 | 
			
		||||
 | 
			
		||||
        self.callbacks[callback_name] = callback_func
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def ignore_line(self, line):
 | 
			
		||||
        l = line.strip('\n ')
 | 
			
		||||
 | 
			
		||||
        if len(l) == 0 or l[0] == '#':
 | 
			
		||||
            return 1
 | 
			
		||||
 | 
			
		||||
        return 0
 | 
			
		||||
 | 
			
		||||
    def process_allow(self, lines, cur_idx, lineno):
 | 
			
		||||
        allow_line = self.lines[cur_idx]
 | 
			
		||||
 | 
			
		||||
        words = allow_line.split()
 | 
			
		||||
        if len(words) <= 1:
 | 
			
		||||
            raise Exception('invalid allow line \'%s\'' %allow_line)
 | 
			
		||||
 | 
			
		||||
        allow_class = words[0].split('-')[1]
 | 
			
		||||
        ifacenames = words[1:]
 | 
			
		||||
 | 
			
		||||
        if self.allow_classes.get(allow_class) is not None:
 | 
			
		||||
            for i in ifacenames:
 | 
			
		||||
                self.allow_classes[allow_class].append(i)
 | 
			
		||||
        else:
 | 
			
		||||
                self.allow_classes[allow_class] = ifacenames
 | 
			
		||||
 | 
			
		||||
        return 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def process_source(self, lines, cur_idx, lineno):
 | 
			
		||||
        # Support regex
 | 
			
		||||
        sourced_file = lines[cur_idx].split(' ', 2)[1]
 | 
			
		||||
        if sourced_file is not None:
 | 
			
		||||
            for f in glob.glob(sourced_file):
 | 
			
		||||
                self.read_file(self, sourced_file)
 | 
			
		||||
        else:
 | 
			
		||||
            self.logger.warn('unable to read source line at %d', lineno)
 | 
			
		||||
 | 
			
		||||
        return 0
 | 
			
		||||
 | 
			
		||||
    def process_auto(self, lines, cur_idx, lineno):
 | 
			
		||||
        # XXX: Need to do more
 | 
			
		||||
        attrs = lines[cur_idx].split()
 | 
			
		||||
        if len(attrs) != 2:
 | 
			
		||||
            raise Exception('line%d: ' %lineno + 'incomplete \'auto\' line')
 | 
			
		||||
 | 
			
		||||
        self.auto_ifaces.append(lines[cur_idx].split()[1])
 | 
			
		||||
 | 
			
		||||
        return 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def process_iface(self, lines, cur_idx, lineno):
 | 
			
		||||
        lines_consumed = 0
 | 
			
		||||
 | 
			
		||||
        ifaceobj = iface()
 | 
			
		||||
 | 
			
		||||
        iface_line = lines[cur_idx].strip('\n ')
 | 
			
		||||
        iface_attrs = iface_line.split()
 | 
			
		||||
 | 
			
		||||
        ifaceobj.raw_lines.append(iface_line)
 | 
			
		||||
    
 | 
			
		||||
        iface_config = collections.OrderedDict()
 | 
			
		||||
        for line_idx in range(cur_idx + 1, len(lines)):
 | 
			
		||||
            l = lines[line_idx].strip('\n\t ')
 | 
			
		||||
 | 
			
		||||
            if self.ignore_line(l) == 1:
 | 
			
		||||
                continue
 | 
			
		||||
 | 
			
		||||
            ifaceobj.raw_lines.append(l)
 | 
			
		||||
 | 
			
		||||
            if self.is_keyword(l.split()[0]) == True:
 | 
			
		||||
                line_idx -= 1
 | 
			
		||||
                break
 | 
			
		||||
 | 
			
		||||
            (attr_name, attrs) = l.split(' ', 1)
 | 
			
		||||
 | 
			
		||||
            if iface_config.get(attr_name) == None:
 | 
			
		||||
                iface_config[attr_name] = [attrs.strip(' ')]
 | 
			
		||||
            else:
 | 
			
		||||
                iface_config[attr_name].append(attrs.strip(' '))
 | 
			
		||||
 | 
			
		||||
        lines_consumed = line_idx - cur_idx
 | 
			
		||||
 | 
			
		||||
        # Create iface object
 | 
			
		||||
        ifaceobj.set_name(iface_attrs[1])
 | 
			
		||||
        ifaceobj.set_config(iface_config)
 | 
			
		||||
        ifaceobj.generate_env()
 | 
			
		||||
        if len(iface_attrs) > 2:
 | 
			
		||||
            ifaceobj.set_addr_family(iface_attrs[2])
 | 
			
		||||
            ifaceobj.set_addr_method(iface_attrs[3])
 | 
			
		||||
 | 
			
		||||
        if ifaceobj.get_name() in self.auto_ifaces:
 | 
			
		||||
            ifaceobj.set_auto()
 | 
			
		||||
 | 
			
		||||
        classes = ifaceobj.set_classes(
 | 
			
		||||
                    self.get_allow_classes_for_iface(ifaceobj.get_name()))
 | 
			
		||||
        if classes is not None and len(classes) > 0:
 | 
			
		||||
            for c in classes:
 | 
			
		||||
                ifaceobj.set_class(c)
 | 
			
		||||
 | 
			
		||||
        # Call iface found callback
 | 
			
		||||
        self.logger.debug('saving interface %s' %ifaceobj.get_name())
 | 
			
		||||
        self.callbacks.get('iface_found')(ifaceobj)
 | 
			
		||||
 | 
			
		||||
        return lines_consumed       # Return next index
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    network_elems = { 'source'      : process_source,
 | 
			
		||||
                      'allow'      : process_allow,
 | 
			
		||||
                      'auto'        : process_auto,
 | 
			
		||||
                      'iface'       : process_iface}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def is_keyword(self, str):
 | 
			
		||||
 | 
			
		||||
        # The additional split here is for allow- keyword
 | 
			
		||||
        tmp_str = str.split('-')[0]
 | 
			
		||||
        if tmp_str in self.network_elems.keys():
 | 
			
		||||
            return 1
 | 
			
		||||
 | 
			
		||||
        return 0
 | 
			
		||||
 | 
			
		||||
    def get_keyword_func(self, str):
 | 
			
		||||
        tmp_str = str.split('-')[0]
 | 
			
		||||
 | 
			
		||||
        return self.network_elems.get(tmp_str)
 | 
			
		||||
 | 
			
		||||
    def get_allow_classes_for_iface(self, ifacename):
 | 
			
		||||
        classes = []
 | 
			
		||||
        for class_name, ifacenames in self.allow_classes.items():
 | 
			
		||||
            if ifacename in ifacenames:
 | 
			
		||||
                classes.append(class_name)
 | 
			
		||||
 | 
			
		||||
        return classes
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def read_file(self, filename=None):
 | 
			
		||||
        lineno = 0
 | 
			
		||||
        line_idx = 0
 | 
			
		||||
        lines_consumed = 0
 | 
			
		||||
 | 
			
		||||
        ifaces_file = filename
 | 
			
		||||
        if ifaces_file == None:
 | 
			
		||||
            ifaces_file=self.ifaces_file
 | 
			
		||||
 | 
			
		||||
        self.logger.debug('reading ifaces_file %s' %ifaces_file)
 | 
			
		||||
 | 
			
		||||
        with open(ifaces_file) as f:
 | 
			
		||||
            lines = f.readlines()
 | 
			
		||||
 | 
			
		||||
            while (line_idx < len(lines)):
 | 
			
		||||
                lineno = lineno + 1
 | 
			
		||||
 | 
			
		||||
                if self.ignore_line(lines[line_idx]):
 | 
			
		||||
                    line_idx += 1
 | 
			
		||||
                    continue
 | 
			
		||||
        
 | 
			
		||||
                l = lines[line_idx].strip('\n ')
 | 
			
		||||
                words = l.split()
 | 
			
		||||
 | 
			
		||||
                # Check if first element is a supported keyword
 | 
			
		||||
                if self.is_keyword(words[0]):
 | 
			
		||||
                    keyword_func = self.get_keyword_func(
 | 
			
		||||
                                words[0])
 | 
			
		||||
                    lines_consumed = keyword_func(self,
 | 
			
		||||
                                        lines, line_idx, lineno)
 | 
			
		||||
 | 
			
		||||
                    line_idx += lines_consumed
 | 
			
		||||
                else:
 | 
			
		||||
                    self.logger.warning('could not ' +
 | 
			
		||||
                        'process line %s' %l + ' at' +
 | 
			
		||||
                        ' lineno %d' %lineno)
 | 
			
		||||
 | 
			
		||||
                line_idx += 1
 | 
			
		||||
 | 
			
		||||
        return 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def load(self, filename=None):
 | 
			
		||||
        self.logger.debug('loading ifaces file ..')
 | 
			
		||||
        return self.read_file(filename)
 | 
			
		||||
							
								
								
									
										392
									
								
								pkg/scheduler.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										392
									
								
								pkg/scheduler.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,392 @@
 | 
			
		||||
#!/usr/bin/python
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
import re
 | 
			
		||||
from statemanager import *
 | 
			
		||||
from iface import *
 | 
			
		||||
from graph import *
 | 
			
		||||
from collections import deque
 | 
			
		||||
from collections import OrderedDict
 | 
			
		||||
import imp
 | 
			
		||||
import pprint
 | 
			
		||||
import logging
 | 
			
		||||
from graph import *
 | 
			
		||||
from collections import deque
 | 
			
		||||
from threading import *
 | 
			
		||||
from ifupdownbase import *
 | 
			
		||||
 | 
			
		||||
class ifaceScheduler(ifupdownBase):
 | 
			
		||||
    """ scheduler to schedule configuration of interfaces.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    supports scheduling of interfaces serially in plain interface list
 | 
			
		||||
    or dependency graph format.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.logger = logging.getLogger('ifupdown.' +
 | 
			
		||||
                    self.__class__.__name__)
 | 
			
		||||
 | 
			
		||||
    def run_iface_subop(self, ifupdownobj, ifaceobj, op, subop, mdict, cenv):
 | 
			
		||||
        """ Runs sub operation on an interface """
 | 
			
		||||
 | 
			
		||||
        self.logger.debug('%s: ' %ifaceobj.get_name() + 'op %s' %op +
 | 
			
		||||
                          ' subop = %s' %subop)
 | 
			
		||||
 | 
			
		||||
        for mname, mdata in mdict.items():
 | 
			
		||||
            m = mdata.get('module')
 | 
			
		||||
            err = 0
 | 
			
		||||
            try:
 | 
			
		||||
                if (mdata.get('ftype') == 'pmodule' and
 | 
			
		||||
                    hasattr(m, 'run') == True):
 | 
			
		||||
                    self.logger.debug('%s: ' %ifaceobj.get_name() +
 | 
			
		||||
                                      'running module %s' %mname +
 | 
			
		||||
                                      ' op %s' %op + ' subop %s' %subop)
 | 
			
		||||
                    if op == 'query':
 | 
			
		||||
                        m.run(ifaceobj, subop, query=True,
 | 
			
		||||
                              query_ifaceobj=ifupdownobj.create_ifaceobjcurr(
 | 
			
		||||
                                                    ifaceobj.get_name()))
 | 
			
		||||
                    else:
 | 
			
		||||
                        m.run(ifaceobj, subop)
 | 
			
		||||
                else:
 | 
			
		||||
                    self.logger.debug('%s: ' %ifaceobj.get_name() +
 | 
			
		||||
                                      'running script %s' %mname +
 | 
			
		||||
                                      ' op %s' %op + ' subop %s' %subop)
 | 
			
		||||
                    self.exec_command(m, cmdenv=cenv)
 | 
			
		||||
            except Exception, e:
 | 
			
		||||
                err = 1
 | 
			
		||||
                if ifupdownobj.ignore_error(str(e)) == True:
 | 
			
		||||
                    pass
 | 
			
		||||
                else:
 | 
			
		||||
                    raise
 | 
			
		||||
            finally:
 | 
			
		||||
                if op != 'query':
 | 
			
		||||
                    if err == 1:
 | 
			
		||||
                        ifupdownobj.set_iface_state(ifaceobj,
 | 
			
		||||
                                ifaceState.from_str(subop),
 | 
			
		||||
                                ifaceStatus.ERROR)
 | 
			
		||||
                    else:
 | 
			
		||||
                        ifupdownobj.set_iface_state(ifaceobj,
 | 
			
		||||
                                ifaceState.from_str(subop),
 | 
			
		||||
                                ifaceStatus.SUCCESS)
 | 
			
		||||
 | 
			
		||||
    def run_iface_subops(self, ifupdownobj, ifaceobj, op):
 | 
			
		||||
        """ Runs all sub operations on an interface """
 | 
			
		||||
 | 
			
		||||
        # For backward compatibility execute scripts with
 | 
			
		||||
        # environent set
 | 
			
		||||
        cenv = ifupdownobj.generate_running_env(ifaceobj, op)
 | 
			
		||||
 | 
			
		||||
        # Each sub operation has a module list
 | 
			
		||||
        subopdict = ifupdownobj.operations.get(op)
 | 
			
		||||
        for subop, mdict in subopdict.items():
 | 
			
		||||
            self.run_iface_subop(ifupdownobj, ifaceobj, op, subop, mdict, cenv)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def run_iface(self, ifupdownobj, ifacename, op):
 | 
			
		||||
        """ Runs operation on an interface """
 | 
			
		||||
 | 
			
		||||
        ifaceobjs = ifupdownobj.get_iface_objs(ifacename)
 | 
			
		||||
        for i in ifaceobjs:
 | 
			
		||||
            if (op != 'query' and ifupdownobj.STATE_CHECK == True and
 | 
			
		||||
                ifupdownobj.is_valid_state_transition(i, op) == False and
 | 
			
		||||
                ifupdownobj.FORCE == False):
 | 
			
		||||
                self.logger.warning('%s' %ifacename +
 | 
			
		||||
                        ' already %s' %op)
 | 
			
		||||
                continue
 | 
			
		||||
 | 
			
		||||
            self.run_iface_subops(ifupdownobj, i, op)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def run_iface_list(self, ifupdownobj, ifacenames, operation,
 | 
			
		||||
                      sorted_by_dependency=False):
 | 
			
		||||
        """ Runs interface list serially executing all sub operations on
 | 
			
		||||
        each interface at a time. """
 | 
			
		||||
 | 
			
		||||
        self.logger.debug('run_iface_list: running interface list for ' +
 | 
			
		||||
                          'operation %s' %operation)
 | 
			
		||||
 | 
			
		||||
        iface_run_queue = deque(ifacenames)
 | 
			
		||||
        for i in range(0, len(iface_run_queue)):
 | 
			
		||||
            if operation == 'up':
 | 
			
		||||
                # XXX: simplify this
 | 
			
		||||
                if sorted_by_dependency == True:
 | 
			
		||||
                    ifacename = iface_run_queue.pop()
 | 
			
		||||
                else:
 | 
			
		||||
                    ifacename = iface_run_queue.popleft()
 | 
			
		||||
            else:
 | 
			
		||||
                if sorted_by_dependency == True:
 | 
			
		||||
                    ifacename = iface_run_queue.popleft()
 | 
			
		||||
                else:
 | 
			
		||||
                    ifacename = iface_run_queue.pop()
 | 
			
		||||
 | 
			
		||||
            try:
 | 
			
		||||
                self.run_iface(ifupdownobj, ifacename, operation)
 | 
			
		||||
            except Exception, e:
 | 
			
		||||
                if (ifupdownobj.ignore_error(str(e)) == True):
 | 
			
		||||
                    pass
 | 
			
		||||
                else:
 | 
			
		||||
                    raise
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def run_iface_list_subop(self, ifupdownobj, ifacenames, op, subop, mdict,
 | 
			
		||||
                             sorted_by_dependency=False):
 | 
			
		||||
        """ Runs interface list through sub operation handler. """
 | 
			
		||||
 | 
			
		||||
        self.logger.debug('running sub operation %s on all given interfaces' %op)
 | 
			
		||||
 | 
			
		||||
        iface_run_queue = deque(ifacenames)
 | 
			
		||||
        for i in range(0, len(iface_run_queue)):
 | 
			
		||||
            if op == 'up':
 | 
			
		||||
                # XXX: simplify this
 | 
			
		||||
                if sorted_by_dependency == True:
 | 
			
		||||
                    ifacename = iface_run_queue.pop()
 | 
			
		||||
                else:
 | 
			
		||||
                    ifacename = iface_run_queue.popleft()
 | 
			
		||||
            else:
 | 
			
		||||
                if sorted_by_dependency == True:
 | 
			
		||||
                    ifacename = iface_run_queue.popleft()
 | 
			
		||||
                else:
 | 
			
		||||
                    ifacename = iface_run_queue.pop()
 | 
			
		||||
 | 
			
		||||
            try:
 | 
			
		||||
                ifaceobjs = ifupdownobj.get_iface_objs(ifacename)
 | 
			
		||||
                for ifaceobj in ifaceobjs:
 | 
			
		||||
                    if (op != 'query' and ifupdownobj.STATE_CHECK == True and
 | 
			
		||||
                        ifupdownobj.is_valid_state_transition(ifaceobj,
 | 
			
		||||
                        op) == False and ifupdownobj.FORCE == False):
 | 
			
		||||
                        if subop == 'post-down' or subop == 'post-up':
 | 
			
		||||
                            self.logger.warning('%s: ' %ifacename +
 | 
			
		||||
                                                ' already %s' %op)
 | 
			
		||||
                        continue
 | 
			
		||||
 | 
			
		||||
                    cenv = ifupdownobj.generate_running_env(ifaceobj, op)
 | 
			
		||||
                    self.run_iface_subop(ifupdownobj, ifaceobj, op, subop,
 | 
			
		||||
                                         mdict, cenv)
 | 
			
		||||
            except Exception, e:
 | 
			
		||||
                if (ifupdownobj.ignore_error(str(e)) == True):
 | 
			
		||||
                    pass
 | 
			
		||||
                else:
 | 
			
		||||
                    raise
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def run_iface_list_stages(self, ifupdownobj, ifacenames, op,
 | 
			
		||||
                              sorted_by_dependency=False):
 | 
			
		||||
        """ Runs interface list through sub operations handler
 | 
			
		||||
 | 
			
		||||
        Unlike run_iface_list, this method executes a sub operation on the
 | 
			
		||||
        entire interface list before proceeding to the next sub-operation.
 | 
			
		||||
        ie operation 'pre-up' is run through the entire interface list before
 | 
			
		||||
        'up'
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        self.logger.debug('run_iface_list_stages: running interface list for %s'
 | 
			
		||||
                          %op)
 | 
			
		||||
 | 
			
		||||
        # Each sub operation has a module list
 | 
			
		||||
        subopdict = ifupdownobj.operations.get(op)
 | 
			
		||||
        for subop, mdict in subopdict.items():
 | 
			
		||||
            self.run_iface_list_subop(ifupdownobj, ifacenames, op, subop, mdict,
 | 
			
		||||
                    sorted_by_dependency)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def run_iface_dependency_graph(self, ifupdownobj, dependency_graph,
 | 
			
		||||
                                   operation):
 | 
			
		||||
        """ runs interface dependency graph """
 | 
			
		||||
 | 
			
		||||
        indegrees = OrderedDict()
 | 
			
		||||
 | 
			
		||||
        self.logger.debug('creating indegree array ...')
 | 
			
		||||
        for ifacename in dependency_graph.keys():
 | 
			
		||||
            indegrees[ifacename] = ifupdownobj.get_iface_refcnt(ifacename)
 | 
			
		||||
 | 
			
		||||
        if self.logger.isEnabledFor(logging.DEBUG) == True:
 | 
			
		||||
            self.logger.debug('indegree array :')
 | 
			
		||||
            ifupdownobj.pp.pprint(indegrees)
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            self.logger.debug('calling topological sort on the graph ...')
 | 
			
		||||
            sorted_ifacenames = graph.topological_sort(dependency_graph,
 | 
			
		||||
                                                       indegrees)
 | 
			
		||||
        except Exception, e:
 | 
			
		||||
            raise
 | 
			
		||||
 | 
			
		||||
        self.logger.debug('sorted iface list = %s' %sorted_ifacenames)
 | 
			
		||||
 | 
			
		||||
        #self.run_iface_list(ifupdownobj, sorted_ifacenames, operation,
 | 
			
		||||
        #                    sorted_by_dependency=True)
 | 
			
		||||
 | 
			
		||||
        self.run_iface_list_stages(ifupdownobj, sorted_ifacenames, operation,
 | 
			
		||||
                                   sorted_by_dependency=True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def init_tokens(self, count):
 | 
			
		||||
        self.token_pool = BoundedSemaphore(count)
 | 
			
		||||
        self.logger.debug('initialized bounded semaphore with %d' %count)
 | 
			
		||||
 | 
			
		||||
    def accquire_token(self, logprefix=''):
 | 
			
		||||
        self.token_pool.acquire()
 | 
			
		||||
        self.logger.debug('%s ' %logprefix + 'acquired token')
 | 
			
		||||
 | 
			
		||||
    def release_token(self, logprefix=''):
 | 
			
		||||
        self.token_pool.release()
 | 
			
		||||
        self.logger.debug('%s ' %logprefix + 'release token')
 | 
			
		||||
 | 
			
		||||
    def run_iface_parallel(self, ifupdownobj, ifacename, op):
 | 
			
		||||
        """ Configures interface in parallel.
 | 
			
		||||
        
 | 
			
		||||
        Executes all its direct dependents in parallel
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        self.logger.debug('%s:' %ifacename + ' %s' %op)
 | 
			
		||||
        self.accquire_token(iface)
 | 
			
		||||
 | 
			
		||||
        # Each iface can have a list of objects
 | 
			
		||||
        ifaceobjs = ifupdownobj.get_iface_objs(ifacename)
 | 
			
		||||
        if ifaceobjs is None:
 | 
			
		||||
            self.logger.warning('%s: ' %ifacename + 'not found')
 | 
			
		||||
            self.release_token(ifacename)
 | 
			
		||||
            return -1
 | 
			
		||||
 | 
			
		||||
        for ifaceobj in ifaceobjs:
 | 
			
		||||
            # Run dependents
 | 
			
		||||
            dlist = ifaceobj.get_dependents()
 | 
			
		||||
            if dlist is not None and len(dlist) > 0:
 | 
			
		||||
                self.logger.debug('%s:' %ifacename +
 | 
			
		||||
                    ' found dependents: %s' %str(dlist))
 | 
			
		||||
                try:
 | 
			
		||||
                    self.release_token(ifacename)
 | 
			
		||||
                    self.run_iface_list_parallel(ifacename, ifupdownobj,
 | 
			
		||||
                                                 dlist, op)
 | 
			
		||||
                    self.accquire_token(ifacename)
 | 
			
		||||
                except Exception, e:
 | 
			
		||||
                    if (ifupdownobj.ignore_error(str(e)) == True):
 | 
			
		||||
                        pass
 | 
			
		||||
                    else:
 | 
			
		||||
                        # Dont bring the iface up if children did not come up
 | 
			
		||||
                        self.logger.debug('%s:' %ifacename +
 | 
			
		||||
                            ' there was an error bringing %s' %op +
 | 
			
		||||
                            ' dependents (%s)', str(e))
 | 
			
		||||
                        ifupdownobj.set_iface_state(ifaceobj,
 | 
			
		||||
                            ifaceState.from_str(
 | 
			
		||||
                                    ifupdownobj.get_subops(op)[0]),
 | 
			
		||||
                            ifaceStatus.ERROR)
 | 
			
		||||
                        return -1
 | 
			
		||||
 | 
			
		||||
            if (op != 'query' and ifupdownobj.STATE_CHECK == True and
 | 
			
		||||
                ifupdownobj.is_valid_state_transition(ifaceobj,
 | 
			
		||||
                    op) == False and ifupdownobj.FORCE == False):
 | 
			
		||||
                self.logger.warning('%s:' %ifacename + ' already %s' %op)
 | 
			
		||||
                continue
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            # Run all sub operations sequentially
 | 
			
		||||
            try:
 | 
			
		||||
                self.logger.debug('%s:' %ifacename + ' running sub-operations')
 | 
			
		||||
                self.run_iface_subops(ifupdownobj, ifaceobj, op)
 | 
			
		||||
            except Exception, e:
 | 
			
		||||
                self.logger.error('%s:' %ifacename +
 | 
			
		||||
                    ' error running sub operations (%s)' %str(e))
 | 
			
		||||
 | 
			
		||||
        self.release_token(ifacename)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def run_iface_list_parallel(self, parent, ifupdownobj, ifacenames, op):
 | 
			
		||||
        """ Runs interface list in parallel """
 | 
			
		||||
 | 
			
		||||
        running_threads = OrderedDict()
 | 
			
		||||
        err = 0
 | 
			
		||||
 | 
			
		||||
        for ifacename in ifacenames:
 | 
			
		||||
            try:
 | 
			
		||||
                self.accquire_token(parent)
 | 
			
		||||
                running_threads[ifacename] = Thread(None,
 | 
			
		||||
                    self.run_iface_parallel, ifacename,
 | 
			
		||||
                    args=(ifupdownobj, ifacename, op))
 | 
			
		||||
                running_threads[ifacename].start()
 | 
			
		||||
                self.release_token(parent)
 | 
			
		||||
            except Exception, e:
 | 
			
		||||
                self.release_token(parent)
 | 
			
		||||
                if (ifupdownobj.ignore_error(str(e)) == True):
 | 
			
		||||
                    pass
 | 
			
		||||
                else:
 | 
			
		||||
                    raise Exception('error starting thread for iface %s'
 | 
			
		||||
                            %ifacename)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        self.logger.debug('%s' %parent + 'waiting for all the threads ...')
 | 
			
		||||
        for ifacename, t  in running_threads.items():
 | 
			
		||||
            t.join()
 | 
			
		||||
            if ifupdownobj.get_iface_status(ifacename) != ifaceStatus.SUCCESS:
 | 
			
		||||
                err += 1
 | 
			
		||||
 | 
			
		||||
        return err
 | 
			
		||||
 | 
			
		||||
    def run_iface_graphs_parallel(self, parent, ifupdownobj, ifacenames, op):
 | 
			
		||||
        """ Runs iface graphs in parallel """
 | 
			
		||||
 | 
			
		||||
        running_threads = OrderedDict()
 | 
			
		||||
        err = 0
 | 
			
		||||
 | 
			
		||||
        for ifacename in ifacenames:
 | 
			
		||||
            try:
 | 
			
		||||
                self.accquire_graph_token(parent)
 | 
			
		||||
                running_threads[ifacename] = Thread(None,
 | 
			
		||||
                    self.run_iface_parallel, ifacename,
 | 
			
		||||
                    args=(ifupdownobj, ifacename, op))
 | 
			
		||||
                running_threads[ifacename].start()
 | 
			
		||||
                self.release_graph_token(parent)
 | 
			
		||||
            except Exception, e:
 | 
			
		||||
                self.release_graph_token(parent)
 | 
			
		||||
                if (ifupdownobj.ignore_error(str(e)) == True):
 | 
			
		||||
                    pass
 | 
			
		||||
                else:
 | 
			
		||||
                    raise Exception('error starting thread for iface %s'
 | 
			
		||||
                            %ifacename)
 | 
			
		||||
 | 
			
		||||
        self.logger.info('%s' %parent + 'waiting for all the threads ...')
 | 
			
		||||
        for ifacename, t  in running_threads.items():
 | 
			
		||||
            t.join()
 | 
			
		||||
            # Check status of thread
 | 
			
		||||
            # XXX: Check all objs
 | 
			
		||||
            if ifupdownobj.get_iface_status(ifacename) != ifaceStatus.SUCCESS:
 | 
			
		||||
                err += 1
 | 
			
		||||
 | 
			
		||||
        return err
 | 
			
		||||
 | 
			
		||||
    def run_iface_dependency_graph_parallel(self, ifupdownobj, dependency_graph,
 | 
			
		||||
                                            operation):
 | 
			
		||||
        """ Runs iface dependeny graph in parallel.
 | 
			
		||||
        
 | 
			
		||||
        arguments:
 | 
			
		||||
        ifupdownobj -- ifupdown object (used for getting and updating iface
 | 
			
		||||
                                        object state)
 | 
			
		||||
        dependency_graph -- dependency graph with 
 | 
			
		||||
        operation -- 'up' or 'down' or 'query'
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        self.logger.debug('running dependency graph in parallel ..')
 | 
			
		||||
 | 
			
		||||
        run_queue = []
 | 
			
		||||
 | 
			
		||||
        # Build a list of ifaces that dont have any dependencies
 | 
			
		||||
        for ifacename in dependency_graph.keys():
 | 
			
		||||
            if ifupdownobj.get_iface_refcnt(ifacename) == 0:
 | 
			
		||||
                run_queue.append(ifacename)
 | 
			
		||||
 | 
			
		||||
        self.logger.debug('graph roots (interfaces that dont have dependents):' +
 | 
			
		||||
                          ' %s' %str(run_queue))
 | 
			
		||||
 | 
			
		||||
        self.init_tokens(ifupdownobj.get_njobs())
 | 
			
		||||
 | 
			
		||||
        return self.run_iface_list_parallel('main', ifupdownobj, run_queue,
 | 
			
		||||
                                            operation)
 | 
			
		||||
 | 
			
		||||
        # OR
 | 
			
		||||
        # Run one graph at a time
 | 
			
		||||
        #for iface in run_queue:
 | 
			
		||||
        #    self.run_iface_list_parallel('main', ifupdownobj, [iface],
 | 
			
		||||
        #            operation)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										258
									
								
								pkg/statemanager.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										258
									
								
								pkg/statemanager.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,258 @@
 | 
			
		||||
#!/usr/bin/python
 | 
			
		||||
 | 
			
		||||
import cPickle
 | 
			
		||||
from collections import OrderedDict
 | 
			
		||||
from exceptions import *
 | 
			
		||||
import logging
 | 
			
		||||
import pprint
 | 
			
		||||
import os
 | 
			
		||||
from iface import *
 | 
			
		||||
 | 
			
		||||
class pickling():
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def save(cls, filename, list_of_objects):
 | 
			
		||||
        try:
 | 
			
		||||
            with open(filename, 'w') as f:
 | 
			
		||||
                for obj in list_of_objects:
 | 
			
		||||
                    cPickle.dump(obj, f)
 | 
			
		||||
        except:
 | 
			
		||||
            raise
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def save_obj(cls, f, obj):
 | 
			
		||||
        try:
 | 
			
		||||
            cPickle.dump(obj, f)
 | 
			
		||||
        except:
 | 
			
		||||
            raise
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def load(cls, filename):
 | 
			
		||||
        with open(filename, 'r') as f:
 | 
			
		||||
            while True:
 | 
			
		||||
                try: yield cPickle.load(f)
 | 
			
		||||
                except EOFError: break
 | 
			
		||||
                except: raise
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class stateManager():
 | 
			
		||||
 | 
			
		||||
    state_file = '/run/network/ifstatenew'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.ifaceobjdict = OrderedDict()
 | 
			
		||||
        self.logger = logging.getLogger('ifupdown.' +
 | 
			
		||||
                    self.__class__.__name__)
 | 
			
		||||
 | 
			
		||||
    def save_ifaceobj(self, ifaceobj):
 | 
			
		||||
        if self.ifaceobjdict.get(ifaceobj.get_name()) is None:
 | 
			
		||||
            self.ifaceobjdict[ifaceobj.get_name()] = [ifaceobj]
 | 
			
		||||
        else:
 | 
			
		||||
            self.ifaceobjdict[ifaceobj.get_name()].append(ifaceobj)
 | 
			
		||||
 | 
			
		||||
    def read_saved_state(self, filename=None):
 | 
			
		||||
        pickle_filename = filename
 | 
			
		||||
        if pickle_filename == None:
 | 
			
		||||
            pickle_filename = self.state_file
 | 
			
		||||
 | 
			
		||||
        if not os.path.exists(pickle_filename):
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        # Read all ifaces from file
 | 
			
		||||
        for ifaceobj in pickling.load(pickle_filename):
 | 
			
		||||
            self.save_ifaceobj(ifaceobj)
 | 
			
		||||
            ifaceobj.set_refcnt(0)
 | 
			
		||||
 | 
			
		||||
        return 0
 | 
			
		||||
 | 
			
		||||
    def get_ifaceobjdict(self):
 | 
			
		||||
        return self.ifaceobjdict
 | 
			
		||||
 | 
			
		||||
    def save_state(self, ifaceobjs, filename=None):
 | 
			
		||||
        pickle_filename = filename
 | 
			
		||||
        if pickle_filename == None:
 | 
			
		||||
            pickle_filename = self.state_file
 | 
			
		||||
 | 
			
		||||
        pickling.save(pickle_filename, ifaceobjs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def compare_iface_state(ifaceobj1, ifaceobj2):
 | 
			
		||||
        ifaceobj1_state = ifaceobj1.get_state()
 | 
			
		||||
        ifaceobj2_state = ifaceobj2.get_state()
 | 
			
		||||
 | 
			
		||||
        if ifaceobj1_state < ifaceobj2_state:
 | 
			
		||||
            return -1
 | 
			
		||||
        elif ifaceobj1_state > ifaceobj2_state:
 | 
			
		||||
            return 1
 | 
			
		||||
        elif ifaceobj1_state == ifaceobj2_state:
 | 
			
		||||
            return 0
 | 
			
		||||
 | 
			
		||||
    def compare_iface_with_old(self, ifaceobj):
 | 
			
		||||
        old_ifaceobj = self.ifaceobjdict.get(ifaceobj.get_name())
 | 
			
		||||
        if old_ifaceobj == None:
 | 
			
		||||
            raise ifacenotfound(ifaceobj.get_name())
 | 
			
		||||
 | 
			
		||||
        if ifaceobj.get_addr_family() != old_ifaceobj.get_addr_family():
 | 
			
		||||
            return -1
 | 
			
		||||
 | 
			
		||||
        if ifaceobj.get_method() != old_ifaceobj.get_method():
 | 
			
		||||
            return -1
 | 
			
		||||
 | 
			
		||||
        # compare config items
 | 
			
		||||
        unmatched_item = set(ifaceobj.items()) ^ set(old_ifaceobj.items())
 | 
			
		||||
        if len(unmatched_item) != 0:
 | 
			
		||||
            return -1
 | 
			
		||||
 | 
			
		||||
        return 0
 | 
			
		||||
 | 
			
		||||
    def get_iface_state_old(self, ifaceobj):
 | 
			
		||||
        old_ifaceobj = self.ifaceobjdict.get(ifaceobj.get_name())
 | 
			
		||||
        if old_ifaceobj == None:
 | 
			
		||||
            raise ifacenotfound(ifaceobj.get_name())
 | 
			
		||||
 | 
			
		||||
        return old_ifaceobj.get_state()
 | 
			
		||||
 | 
			
		||||
    def get_iface_status_old(self, ifaceobj):
 | 
			
		||||
        old_ifaceobj = self.ifaceobjdict.get(ifaceobj.get_name())
 | 
			
		||||
        if old_ifaceobj == None:
 | 
			
		||||
            raise ifacenotfound(ifaceobj.get_name())
 | 
			
		||||
 | 
			
		||||
        return old_ifaceobj.get_status()
 | 
			
		||||
 | 
			
		||||
    def cmp_old_new_state(self, ifacename, operation):
 | 
			
		||||
        """ compares current operation with old state """
 | 
			
		||||
 | 
			
		||||
        state_arg = ifaceState.from_str(operation)
 | 
			
		||||
        if state_arg == ifaceState.UP:
 | 
			
		||||
            old_ifaceobj = self.ifaceobjdict.get(ifacename)
 | 
			
		||||
            if old_ifaceobj != None:
 | 
			
		||||
                # found old state for iface
 | 
			
		||||
                # Check its state
 | 
			
		||||
                if (old_ifaceobj.get_state() == state_arg and
 | 
			
		||||
                    old_ifaceobj.get_status() == ifaceStatus.SUCCESS):
 | 
			
		||||
                    self.statemsg = 'iface already up'
 | 
			
		||||
                    return 0
 | 
			
		||||
        elif state_arg == ifaceState.DOWN:
 | 
			
		||||
            old_ifaceobj = self.ifaceobjdict.get(ifname)
 | 
			
		||||
            if old_ifaceobj != None:
 | 
			
		||||
                # found old state for iface
 | 
			
		||||
                # Check its state
 | 
			
		||||
                if (old_ifaceobj.get_state() == state_arg and
 | 
			
		||||
                    old_ifaceobj.get_status() == ifaceStatus.SUCCESS):
 | 
			
		||||
                    self.statemsg = 'iface already down'
 | 
			
		||||
                    return 0
 | 
			
		||||
 | 
			
		||||
        return 1
 | 
			
		||||
 | 
			
		||||
    def iface_obj_compare(self, ifaceobj_a, ifaceobj_b):
 | 
			
		||||
        if ifaceobj_a.get_name() != ifaceobj_b.get_name():
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        if (ifaceobj_a.get_addr_family() is None and
 | 
			
		||||
            ifaceobj_b.get_addr_family() is not None):
 | 
			
		||||
                return False
 | 
			
		||||
 | 
			
		||||
        if (ifaceobj_a.get_addr_family() is not None and
 | 
			
		||||
            ifaceobj_b.get_addr_family() is None):
 | 
			
		||||
                return False
 | 
			
		||||
 | 
			
		||||
        if (ifaceobj_a.get_addr_family() is None and
 | 
			
		||||
            ifaceobj_b.get_addr_family() is None):
 | 
			
		||||
                return True
 | 
			
		||||
 | 
			
		||||
        if ifaceobj_a.get_addr_family() != ifaceobj_b.get_addr_family():
 | 
			
		||||
           return False
 | 
			
		||||
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def update_iface_state(self, ifaceobj):
 | 
			
		||||
        old_ifaceobjs = self.ifaceobjdict.get(ifaceobj.get_name())
 | 
			
		||||
        if old_ifaceobjs is None:
 | 
			
		||||
            self.ifaceobjdict[ifaceobj.get_name()] = [ifaceobj]
 | 
			
		||||
        else:
 | 
			
		||||
            for oi in old_ifaceobjs:
 | 
			
		||||
                if self.iface_obj_compare(ifaceobj, oi) == True:
 | 
			
		||||
                    oi.set_state(ifaceobj.get_state())
 | 
			
		||||
                    oi.set_status(ifaceobj.get_status())
 | 
			
		||||
                    return
 | 
			
		||||
 | 
			
		||||
            self.ifaceobjdict[ifaceobj.get_name()].append(ifaceobj)
 | 
			
		||||
 | 
			
		||||
    def flush_state(self, ifaceobjdict=None):
 | 
			
		||||
        if ifaceobjdict is None:
 | 
			
		||||
            ifaceobjdict = self.ifaceobjdict
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            with open(self.state_file, 'w') as f:
 | 
			
		||||
                for ifaceobjs in ifaceobjdict.values():
 | 
			
		||||
                    for i in ifaceobjs:
 | 
			
		||||
                        pickling.save_obj(f, i)
 | 
			
		||||
        except:
 | 
			
		||||
            raise
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def is_valid_state_transition(self, ifaceobj, tobe_state):
 | 
			
		||||
        if self.ifaceobjdict is None:
 | 
			
		||||
            return True
 | 
			
		||||
 | 
			
		||||
        if tobe_state == 'up':
 | 
			
		||||
            max_tobe_state = ifaceState.POST_UP
 | 
			
		||||
        elif tobe_state == 'down':
 | 
			
		||||
            max_tobe_state = ifaceState.POST_DOWN
 | 
			
		||||
        else:
 | 
			
		||||
            return True
 | 
			
		||||
 | 
			
		||||
        old_ifaceobjs = self.ifaceobjdict.get(ifaceobj.get_name())
 | 
			
		||||
        if old_ifaceobjs is not None:
 | 
			
		||||
            for oi in old_ifaceobjs:
 | 
			
		||||
                if self.iface_obj_compare(ifaceobj, oi) == True:
 | 
			
		||||
                    if (oi.get_state() == max_tobe_state and
 | 
			
		||||
                        oi.get_status() == ifaceStatus.SUCCESS):
 | 
			
		||||
                        # if old state is greater than or equal to
 | 
			
		||||
                        # tobe_state
 | 
			
		||||
                        return False
 | 
			
		||||
                    else:
 | 
			
		||||
                        return True
 | 
			
		||||
 | 
			
		||||
            return True
 | 
			
		||||
        else:
 | 
			
		||||
            return True
 | 
			
		||||
 | 
			
		||||
    def print_state(self, ifaceobj, prefix, indent):
 | 
			
		||||
        print ('%s' %indent + '%s' %prefix +
 | 
			
		||||
               '%s' %firstifaceobj.get_state_str(),
 | 
			
		||||
               ', %s' %firstifaceobj.get_status_str())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def print_state_pretty(self, ifacenames, logger):
 | 
			
		||||
        for ifacename in ifacenames:
 | 
			
		||||
            old_ifaceobjs = self.ifaceobjdict.get(ifacename)
 | 
			
		||||
            if old_ifaceobjs is not None:
 | 
			
		||||
                firstifaceobj = old_ifaceobjs[0]
 | 
			
		||||
                self.print_state(self, firstifaceobj,
 | 
			
		||||
                        '%s: ' %firstifaceobj.get_name(), indent)
 | 
			
		||||
 | 
			
		||||
    def print_state_detailed_pretty(self, ifacenames, logger):
 | 
			
		||||
        for ifacename in ifacenames:
 | 
			
		||||
            old_ifaceobjs = self.ifaceobjdict.get(ifacename)
 | 
			
		||||
            if old_ifaceobjs is not None:
 | 
			
		||||
                for i in old_ifaceobjs:
 | 
			
		||||
                    i.dump_pretty(logger)
 | 
			
		||||
                    self.print_state(self, firstifaceobj, '', indent)
 | 
			
		||||
 | 
			
		||||
    def dump(self, ifacenames=None):
 | 
			
		||||
        print 'iface state:'
 | 
			
		||||
        if ifacenames is not None and len(ifacenames) > 0:
 | 
			
		||||
            for i in ifacenames:
 | 
			
		||||
                ifaceobj = self.ifaces.get(i)
 | 
			
		||||
                if ifaceobj is None:
 | 
			
		||||
                    raise ifaceNotFoundError('ifname %s'
 | 
			
		||||
                        %i + ' not found')
 | 
			
		||||
                ifaceobj.dump(self.logger)
 | 
			
		||||
        else:
 | 
			
		||||
            for ifacename, ifaceobj in self.ifaceobjdict.items():
 | 
			
		||||
                ifaceobj.dump(self.logger)
 | 
			
		||||
							
								
								
									
										184
									
								
								sbin/ifupdown
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										184
									
								
								sbin/ifupdown
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,184 @@
 | 
			
		||||
#!/usr/bin/python
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import os
 | 
			
		||||
import re
 | 
			
		||||
import argparse
 | 
			
		||||
from ifupdown.ifupdown_main import *
 | 
			
		||||
 | 
			
		||||
import logging
 | 
			
		||||
 | 
			
		||||
lockfile="/run/network/.lock"
 | 
			
		||||
logger = None
 | 
			
		||||
 | 
			
		||||
def run(args, op):
 | 
			
		||||
 | 
			
		||||
    logger.debug('args = %s' %str(args))
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        logger.debug('creating ifupdown object ..')
 | 
			
		||||
        ifupdown_handle = ifupdown_main()
 | 
			
		||||
 | 
			
		||||
        if op == 'up' or op == 'down':
 | 
			
		||||
            if args.force == True:
 | 
			
		||||
                ifupdown_handle.set_force(args.force)
 | 
			
		||||
 | 
			
		||||
            if args.jobs > 0:
 | 
			
		||||
                ifupdown_handle.set_njobs(args.jobs)
 | 
			
		||||
 | 
			
		||||
        if args.dryrun == True:
 | 
			
		||||
            ifupdown_handle.set_dryrun(args.dryrun)
 | 
			
		||||
 | 
			
		||||
        if args.nodepends == True:
 | 
			
		||||
            ifupdown_handle.set_nodepends(args.nodepends)
 | 
			
		||||
 | 
			
		||||
        iflist = args.iflist
 | 
			
		||||
        if len(args.iflist) == 0:
 | 
			
		||||
            iflist = None
 | 
			
		||||
 | 
			
		||||
        logger.debug('calling %s' %op + ' for all interfaces ..')
 | 
			
		||||
        if op == 'up':
 | 
			
		||||
            ifupdown_handle.up(args.all, args.allow, iflist)
 | 
			
		||||
        elif op == 'down':
 | 
			
		||||
            ifupdown_handle.down(args.all, args.allow, iflist)
 | 
			
		||||
        elif op == 'query':
 | 
			
		||||
            if args.curstate == True:
 | 
			
		||||
                qstate='curr'
 | 
			
		||||
            elif args.presumedstate == True:
 | 
			
		||||
                qstate='presumed'
 | 
			
		||||
            elif args.presumedstatedetailed == True:
 | 
			
		||||
                qstate='presumeddetailed'
 | 
			
		||||
            else:
 | 
			
		||||
                qstate=None
 | 
			
		||||
            ifupdown_handle.query(args.all, args.allow, iflist,
 | 
			
		||||
                                  query_state=qstate)
 | 
			
		||||
    except:
 | 
			
		||||
        raise
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def init(args):
 | 
			
		||||
    global logger
 | 
			
		||||
 | 
			
		||||
    log_level = logging.WARNING
 | 
			
		||||
 | 
			
		||||
    if args.verbose == True:
 | 
			
		||||
        log_level = logging.INFO
 | 
			
		||||
 | 
			
		||||
    if args.debug == True:
 | 
			
		||||
        log_level = logging.DEBUG
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        logging.basicConfig(level=log_level,
 | 
			
		||||
            format='%(message)s')
 | 
			
		||||
        logger = logging.getLogger('ifupdown')
 | 
			
		||||
    except:
 | 
			
		||||
        raise
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def deinit():
 | 
			
		||||
    print 'deinit called'
 | 
			
		||||
 | 
			
		||||
def update_argparser(argparser):
 | 
			
		||||
 | 
			
		||||
    argparser.add_argument('iflist', metavar='IFACE',
 | 
			
		||||
                nargs='*', help='interfaces list')
 | 
			
		||||
    argparser.add_argument('-a', '--all', action='store_true',
 | 
			
		||||
                help='operate on all interfaces')
 | 
			
		||||
    argparser.add_argument('-n', '--dry-run', dest='dryrun',
 | 
			
		||||
                action='store_true', help='dry run')
 | 
			
		||||
    argparser.add_argument('-v', '--verbose', dest='verbose',
 | 
			
		||||
                action='store_true', help='verbose')
 | 
			
		||||
    argparser.add_argument('-d', '--debug', dest='debug',
 | 
			
		||||
                action='store_true',
 | 
			
		||||
                help='output debug info')
 | 
			
		||||
    argparser.add_argument('-q', '--quiet', dest='quiet',
 | 
			
		||||
                action='store_true',
 | 
			
		||||
                help=argparse.SUPPRESS)
 | 
			
		||||
    argparser.add_argument('--allow', dest='allow', 
 | 
			
		||||
                help='allow class')
 | 
			
		||||
    argparser.add_argument('--nodepends', dest='nodepends',
 | 
			
		||||
                action='store_true', help='dont follow dependents')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def update_ifupdown_argparser(argparser):
 | 
			
		||||
    argparser.add_argument('-f', '--force', dest='force',
 | 
			
		||||
                action='store_true',
 | 
			
		||||
                help='force run all operations')
 | 
			
		||||
    argparser.add_argument('-j', '--jobs', dest='jobs', type=int,
 | 
			
		||||
                default=-1, choices=range(1,12), help=argparse.SUPPRESS)
 | 
			
		||||
 | 
			
		||||
def update_ifup_argparser(argparser):
 | 
			
		||||
    update_ifupdown_argparser(argparser)
 | 
			
		||||
 | 
			
		||||
def update_ifdown_argparser(argparser):
 | 
			
		||||
    update_ifupdown_argparser(argparser)
 | 
			
		||||
 | 
			
		||||
def update_ifquery_argparser(argparser):
 | 
			
		||||
    group = argparser.add_mutually_exclusive_group(required=False)
 | 
			
		||||
    group.add_argument('-s', '--query-state', dest='curstate',
 | 
			
		||||
                       action='store_true', help=argparse.SUPPRESS)
 | 
			
		||||
    group.add_argument('--presumed-state', dest='presumedstate',
 | 
			
		||||
                       action='store_true', help=argparse.SUPPRESS)
 | 
			
		||||
    group.add_argument('--presumed-state-detailed',
 | 
			
		||||
                       dest='presumedstatedetailed',
 | 
			
		||||
                       action='store_true', help=argparse.SUPPRESS)
 | 
			
		||||
 | 
			
		||||
def parse_args(argsv, op):
 | 
			
		||||
    descr = 'interface management'
 | 
			
		||||
 | 
			
		||||
    argparser = argparse.ArgumentParser(description=descr)
 | 
			
		||||
    update_argparser(argparser)
 | 
			
		||||
    if op == 'up':
 | 
			
		||||
        update_ifup_argparser(argparser)
 | 
			
		||||
    elif op == 'down':
 | 
			
		||||
        update_ifdown_argparser(argparser)
 | 
			
		||||
    elif op == 'query':
 | 
			
		||||
        update_ifquery_argparser(argparser)
 | 
			
		||||
 | 
			
		||||
    return argparser.parse_args(argsv)
 | 
			
		||||
 | 
			
		||||
def main(argv):
 | 
			
		||||
    """ main function """
 | 
			
		||||
    try:
 | 
			
		||||
        op = None
 | 
			
		||||
        if re.search(r'ifup', argv[0]) != None:
 | 
			
		||||
            op = 'up'
 | 
			
		||||
        elif re.search(r'ifdown', argv[0]) != None:
 | 
			
		||||
            op = 'down'
 | 
			
		||||
        elif re.search(r'ifquery', argv[0]) != None:
 | 
			
		||||
            op = 'query'
 | 
			
		||||
        else:
 | 
			
		||||
            print ('Unexpected executable.' +
 | 
			
		||||
                   ' Should be \'ifup\' or \'ifdown\' or \'ifquery\'')
 | 
			
		||||
            exit(1)
 | 
			
		||||
 | 
			
		||||
        # Command line arg parser
 | 
			
		||||
        args = parse_args(argv[1:], op)
 | 
			
		||||
        if len(args.iflist) > 0 and args.all is True:
 | 
			
		||||
            print 'iflist and all are mutually exclusive'
 | 
			
		||||
            exit(1)
 | 
			
		||||
 | 
			
		||||
        init(args)
 | 
			
		||||
        run(args, op)
 | 
			
		||||
    except Exception, e:
 | 
			
		||||
        if args.debug == True:
 | 
			
		||||
            raise
 | 
			
		||||
        else:
 | 
			
		||||
            logger.error(str(e))
 | 
			
		||||
    finally:
 | 
			
		||||
        deinit()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
 | 
			
		||||
    if not os.geteuid() == 0:
 | 
			
		||||
        print 'Error: Must be root to run this command'
 | 
			
		||||
        exit(1)
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    if not utilities.lockFile(lockfile):
 | 
			
		||||
        print 'Another instance of this program is already running.'
 | 
			
		||||
        exit(0)
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    main(sys.argv)
 | 
			
		||||
							
								
								
									
										16
									
								
								setup.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										16
									
								
								setup.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
from distutils.core import setup
 | 
			
		||||
 | 
			
		||||
setup(name='ifupdown2',
 | 
			
		||||
      version='0.1',
 | 
			
		||||
      description = "ifupdown 2",
 | 
			
		||||
      author='Roopa Prabhu',
 | 
			
		||||
      author_email='roopa@cumulusnetworks.com',
 | 
			
		||||
      url='cumulusnetworks.com',
 | 
			
		||||
      package_dir = {'ifupdown' : 'pkg'},
 | 
			
		||||
      packages=['ifupdown'],
 | 
			
		||||
      scripts = ['sbin/ifupdown'],
 | 
			
		||||
      data_files=[('share/man/man8/',
 | 
			
		||||
                      ['man/ifup.8', 'man/ifdown.8', 'man/ifquery.8']),
 | 
			
		||||
                  ('/etc/init.d/',
 | 
			
		||||
                      ['init.d/networking'])]
 | 
			
		||||
      )
 | 
			
		||||
		Reference in New Issue
	
	Block a user