2013-03-18 01:06:52 +04:00
#
2013-10-28 00:59:46 +04:00
# Copyright 2009, 2013 Red Hat, Inc.
2013-03-18 01:06:52 +04:00
# Cole Robinson <crobinso@redhat.com>
#
2018-04-04 16:35:41 +03:00
# This work is licensed under the GNU GPLv2 or later.
2018-03-20 22:00:02 +03:00
# See the COPYING file in the top-level directory.
2013-03-18 01:06:52 +04:00
"""
Classes for building and installing libvirt interface xml
"""
2017-10-11 14:35:48 +03:00
import ipaddress
2013-03-18 01:06:52 +04:00
import logging
2013-09-10 01:14:16 +04:00
import libvirt
2014-09-12 23:59:22 +04:00
from . import util
from . xmlbuilder import XMLBuilder , XMLChildProperty , XMLProperty
2013-09-10 01:14:16 +04:00
class _IPAddress ( XMLBuilder ) :
_XML_PROP_ORDER = [ " address " , " prefix " ]
2018-03-21 17:53:34 +03:00
XML_NAME = " ip "
2013-09-10 01:14:16 +04:00
2018-09-03 23:13:49 +03:00
address = XMLProperty ( " ./@address " )
2013-09-10 01:14:16 +04:00
prefix = XMLProperty ( " ./@prefix " , is_int = True )
class InterfaceProtocol ( XMLBuilder ) :
INTERFACE_PROTOCOL_FAMILY_IPV4 = " ipv4 "
INTERFACE_PROTOCOL_FAMILY_IPV6 = " ipv6 "
INTERFACE_PROTOCOL_FAMILIES = [ INTERFACE_PROTOCOL_FAMILY_IPV4 ,
INTERFACE_PROTOCOL_FAMILY_IPV6 ]
2018-03-21 17:53:34 +03:00
XML_NAME = " protocol "
2013-09-10 01:14:16 +04:00
_XML_PROP_ORDER = [ " autoconf " , " dhcp " , " dhcp_peerdns " , " ips " , " gateway " ]
family = XMLProperty ( " ./@family " )
2018-02-23 04:44:09 +03:00
dhcp = XMLProperty ( " ./dhcp " , is_bool = True )
2013-09-10 01:14:16 +04:00
dhcp_peerdns = XMLProperty ( " ./dhcp/@peerdns " , is_yesno = True )
2018-02-23 04:44:09 +03:00
gateway = XMLProperty ( " ./route/@gateway " )
autoconf = XMLProperty ( " ./autoconf " , is_bool = True )
2013-03-18 02:18:22 +04:00
2013-03-18 01:06:52 +04:00
2013-09-10 01:14:16 +04:00
#####################
# IP child handling #
#####################
def add_ip ( self , addr , prefix = None ) :
2018-02-08 01:27:56 +03:00
ip = self . ips . add_new ( )
2013-09-10 01:14:16 +04:00
ip . address = addr
ip . prefix = prefix
def remove_ip ( self , ip ) :
2015-09-04 22:45:45 +03:00
self . remove_child ( ip )
2013-09-10 01:14:16 +04:00
ip . clear ( )
ips = XMLChildProperty ( _IPAddress )
2018-03-21 17:49:29 +03:00
class _BondConfig ( XMLBuilder ) :
2018-03-21 17:53:34 +03:00
XML_NAME = " bond "
2018-03-21 17:49:29 +03:00
class _BridgeConfig ( XMLBuilder ) :
2018-03-21 17:53:34 +03:00
XML_NAME = " bridge "
2018-03-21 17:49:29 +03:00
class _VLANConfig ( XMLBuilder ) :
2018-03-21 17:53:34 +03:00
XML_NAME = " vlan "
2018-03-21 17:49:29 +03:00
2013-09-10 01:14:16 +04:00
class Interface ( XMLBuilder ) :
2013-03-18 01:06:52 +04:00
"""
Base class for building any libvirt interface object .
Mostly meaningless to directly instantiate .
"""
INTERFACE_TYPE_BRIDGE = " bridge "
INTERFACE_TYPE_BOND = " bond "
INTERFACE_TYPE_ETHERNET = " ethernet "
INTERFACE_TYPE_VLAN = " vlan "
INTERFACE_TYPES = [ INTERFACE_TYPE_BRIDGE , INTERFACE_TYPE_BOND ,
INTERFACE_TYPE_ETHERNET , INTERFACE_TYPE_VLAN ]
INTERFACE_START_MODE_NONE = " none "
INTERFACE_START_MODE_ONBOOT = " onboot "
INTERFACE_START_MODE_HOTPLUG = " hotplug "
INTERFACE_START_MODES = [ INTERFACE_START_MODE_NONE ,
INTERFACE_START_MODE_ONBOOT ,
INTERFACE_START_MODE_HOTPLUG ]
2013-09-10 01:14:16 +04:00
INTERFACE_BOND_MODES = [ " active-backup " , " balance-alb " , " balance-rr " ,
" balance-tlb " , " balance-xor " , " broadcast " ,
" 802.3ad " ]
INTERFACE_BOND_MONITOR_MODE_ARP = " arpmon "
INTERFACE_BOND_MONITOR_MODE_MII = " miimon "
INTERFACE_BOND_MONITOR_MODES = [ INTERFACE_BOND_MONITOR_MODE_ARP ,
INTERFACE_BOND_MONITOR_MODE_MII ]
INTERFACE_BOND_MONITOR_MODE_ARP_VALIDATE_MODES = [ " active " , " backup " ,
" all " ]
INTERFACE_BOND_MONITOR_MODE_MII_CARRIER_TYPES = [ " netif " , " ioctl " ]
2013-03-18 01:06:52 +04:00
@staticmethod
def find_free_name ( conn , prefix ) :
"""
Generate an unused interface name based on prefix . For example ,
if prefix = " br " , we find the first unused name such as " br0 " , " br1 " ,
etc .
"""
2013-04-11 18:27:02 +04:00
return util . generate_name ( prefix , conn . interfaceLookupByName , sep = " " ,
2013-09-10 01:14:16 +04:00
force_num = True )
2018-03-21 17:53:34 +03:00
XML_NAME = " interface "
2013-09-10 01:14:16 +04:00
_XML_PROP_ORDER = [ " type " , " name " , " start_mode " , " macaddr " , " mtu " ,
" stp " , " delay " , " bond_mode " , " arp_interval " ,
" arp_target " , " arp_validate_mode " , " mii_frequency " ,
" mii_downdelay " , " mii_updelay " , " mii_carrier_mode " ,
" tag " , " parent_interface " ,
2018-03-21 17:49:29 +03:00
" protocols " , " _bond " , " _bridge " , " _vlan " ]
2013-09-10 01:14:16 +04:00
2018-03-21 17:49:29 +03:00
######################
# Interface handling #
######################
# The recursive nature of nested interfaces complicates things here,
# which is why this is strange. See bottom of the file for more
# weirdness
_bond = XMLChildProperty ( _BondConfig , is_single = True )
_bridge = XMLChildProperty ( _BridgeConfig , is_single = True )
_vlan = XMLChildProperty ( _VLANConfig , is_single = True )
2013-09-10 01:14:16 +04:00
def add_interface ( self , obj ) :
2018-03-21 17:49:29 +03:00
getattr ( self , " _ " + self . type ) . add_child ( obj )
2013-09-10 01:14:16 +04:00
def remove_interface ( self , obj ) :
2018-03-21 17:49:29 +03:00
getattr ( self , " _ " + self . type ) . remove_child ( obj )
2013-09-10 01:14:16 +04:00
2018-03-21 17:49:29 +03:00
@property
def interfaces ( self ) :
if self . type != " ethernet " :
return getattr ( self , " _ " + self . type ) . interfaces
return [ ]
2013-09-10 01:14:16 +04:00
######################
# Validation helpers #
######################
2018-09-03 22:45:26 +03:00
@staticmethod
def validate_name ( conn , name ) :
2013-03-18 01:06:52 +04:00
try :
2018-09-03 22:45:26 +03:00
conn . interfaceLookupByName ( name )
2013-03-18 01:06:52 +04:00
except libvirt . libvirtError :
return
raise ValueError ( _ ( " Name ' %s ' already in use by another interface. " ) %
name )
2013-09-10 01:14:16 +04:00
##################
# General params #
##################
type = XMLProperty ( " ./@type " )
2018-02-23 04:44:09 +03:00
mtu = XMLProperty ( " ./mtu/@size " , is_int = True )
start_mode = XMLProperty ( " ./start/@mode " )
2013-09-10 01:14:16 +04:00
2018-09-03 22:45:26 +03:00
name = XMLProperty ( " ./@name " )
2018-09-03 23:13:49 +03:00
macaddr = XMLProperty ( " ./mac/@address " )
2013-09-10 01:14:16 +04:00
2018-03-21 17:49:29 +03:00
def add_protocol ( self , obj ) :
self . add_child ( obj )
def remove_protocol ( self , obj ) :
self . remove_child ( obj )
protocols = XMLChildProperty ( InterfaceProtocol )
2013-09-10 01:14:16 +04:00
#################
# Bridge params #
#################
2013-03-18 01:06:52 +04:00
2018-02-23 04:44:09 +03:00
stp = XMLProperty ( " ./bridge/@stp " , is_onoff = True )
delay = XMLProperty ( " ./bridge/@delay " )
2013-03-18 01:06:52 +04:00
2013-09-10 01:14:16 +04:00
###############
# Bond params #
###############
2013-03-18 01:06:52 +04:00
2018-02-23 04:44:09 +03:00
bond_mode = XMLProperty ( " ./bond/@mode " )
arp_interval = XMLProperty ( " ./bond/arpmon/@interval " , is_int = True )
arp_target = XMLProperty ( " ./bond/arpmon/@target " )
arp_validate_mode = XMLProperty ( " ./bond/arpmon/@validate " )
mii_carrier_mode = XMLProperty ( " ./bond/miimon/@carrier " )
mii_frequency = XMLProperty ( " ./bond/miimon/@freq " , is_int = True )
mii_updelay = XMLProperty ( " ./bond/miimon/@updelay " , is_int = True )
mii_downdelay = XMLProperty ( " ./bond/miimon/@downdelay " , is_int = True )
2013-03-18 01:06:52 +04:00
2013-09-10 01:14:16 +04:00
###############
# VLAN params #
###############
2013-03-18 01:06:52 +04:00
2018-02-23 04:44:09 +03:00
tag = XMLProperty ( " ./vlan/@tag " , is_int = True )
parent_interface = XMLProperty ( " ./vlan/interface/@name " )
2013-09-10 01:14:16 +04:00
##################
# Build routines #
##################
def validate ( self ) :
2018-09-03 22:45:26 +03:00
self . validate_name ( self . conn , self . name )
2018-09-03 23:13:49 +03:00
if self . macaddr :
util . validate_macaddr ( self . macaddr )
for protocol in self . protocols :
for ip in protocol . ips :
ipaddress . ip_address ( ip . address )
2018-09-03 22:45:26 +03:00
2013-09-10 01:14:16 +04:00
if ( self . type == self . INTERFACE_TYPE_VLAN and
( self . tag is None or self . parent_interface is None ) ) :
raise ValueError ( _ ( " VLAN Tag and parent interface are required. " ) )
2013-03-18 01:06:52 +04:00
def install ( self , meter = None , create = True ) :
"""
Install network interface xml .
"""
2016-04-18 23:42:12 +03:00
ignore = meter
2018-08-31 23:52:02 +03:00
xml = self . get_xml ( )
2013-03-18 01:06:52 +04:00
logging . debug ( " Creating interface ' %s ' with xml: \n %s " ,
self . name , xml )
try :
iface = self . conn . interfaceDefineXML ( xml , 0 )
2017-05-05 19:47:21 +03:00
except Exception as e :
2015-06-02 15:21:58 +03:00
raise RuntimeError ( _ ( " Could not define interface: %s " ) % str ( e ) )
2013-03-18 01:06:52 +04:00
errmsg = None
if create and not errmsg :
try :
iface . create ( 0 )
2017-05-05 19:47:21 +03:00
except Exception as e :
2015-06-02 15:21:58 +03:00
errmsg = _ ( " Could not create interface: %s " ) % str ( e )
2013-03-18 01:06:52 +04:00
if errmsg :
# Try and clean up the leftover pool
try :
iface . undefine ( )
2017-05-05 19:47:21 +03:00
except Exception as e :
2018-03-02 11:01:23 +03:00
logging . debug ( " Error cleaning up interface after failure: %s " ,
str ( e ) )
2013-03-18 01:06:52 +04:00
raise RuntimeError ( errmsg )
return iface
2018-03-21 17:49:29 +03:00
# Interface can recursively have child interfaces which we can't define
# inline in the class config, hence this hackery
_BondConfig . interfaces = XMLChildProperty ( Interface )
_BridgeConfig . interfaces = XMLChildProperty ( Interface )
_VLANConfig . interfaces = XMLChildProperty ( Interface )