2013-09-21 04:40:07 +04:00
#
# Copyright 2013 Red Hat, Inc.
# Cole Robinson <crobinso@redhat.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
2013-10-28 00:59:47 +04:00
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
2013-09-21 04:40:07 +04:00
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA.
"""
Classes for building and installing libvirt < network > XML
"""
2013-09-30 23:06:52 +04:00
import logging
2013-09-21 04:40:07 +04:00
import libvirt
2014-09-12 23:59:22 +04:00
from . import util
from . xmlbuilder import XMLBuilder , XMLChildProperty , XMLProperty
2013-09-21 04:40:07 +04:00
class _NetworkDHCPRange ( XMLBuilder ) :
_XML_ROOT_NAME = " range "
start = XMLProperty ( " ./@start " )
end = XMLProperty ( " ./@end " )
class _NetworkDHCPHost ( XMLBuilder ) :
_XML_ROOT_NAME = " host "
macaddr = XMLProperty ( " ./@mac " )
name = XMLProperty ( " ./@name " )
ip = XMLProperty ( " ./@ip " )
class _NetworkIP ( XMLBuilder ) :
_XML_ROOT_NAME = " ip "
family = XMLProperty ( " ./@family " )
address = XMLProperty ( " ./@address " )
prefix = XMLProperty ( " ./@prefix " , is_int = True )
netmask = XMLProperty ( " ./@netmask " )
tftp = XMLProperty ( " ./tftp/@root " )
bootp_file = XMLProperty ( " ./dhcp/bootp/@file " )
bootp_server = XMLProperty ( " ./dhcp/bootp/@server " )
ranges = XMLChildProperty ( _NetworkDHCPRange , relative_xpath = " ./dhcp " )
hosts = XMLChildProperty ( _NetworkDHCPHost , relative_xpath = " ./dhcp " )
2013-09-23 21:21:35 +04:00
def add_range ( self ) :
r = _NetworkDHCPRange ( self . conn )
2015-09-04 22:45:45 +03:00
self . add_child ( r )
2013-09-23 21:21:35 +04:00
return r
2013-09-21 04:40:07 +04:00
class _NetworkRoute ( XMLBuilder ) :
_XML_ROOT_NAME = " route "
family = XMLProperty ( " ./@family " )
address = XMLProperty ( " ./@address " )
prefix = XMLProperty ( " ./@prefix " , is_int = True )
gateway = XMLProperty ( " ./@gateway " )
2013-09-23 17:10:43 +04:00
netmask = XMLProperty ( " ./@netmask " )
2013-09-21 04:40:07 +04:00
class _NetworkForward ( XMLBuilder ) :
_XML_ROOT_NAME = " forward "
mode = XMLProperty ( " ./@mode " )
dev = XMLProperty ( " ./@dev " )
def pretty_desc ( self ) :
return Network . pretty_forward_desc ( self . mode , self . dev )
2014-06-25 14:27:00 +04:00
class _NetworkBandwidth ( XMLBuilder ) :
_XML_ROOT_NAME = " bandwidth "
inbound_average = XMLProperty ( " ./inbound/@average " )
inbound_peak = XMLProperty ( " ./inbound/@peak " )
inbound_burst = XMLProperty ( " ./inbound/@burst " )
inbound_floor = XMLProperty ( " ./inbound/@floor " )
outbound_average = XMLProperty ( " ./outbound/@average " )
outbound_peak = XMLProperty ( " ./outbound/@peak " )
outbound_burst = XMLProperty ( " ./outbound/@burst " )
def is_inbound ( self ) :
2015-07-10 15:07:02 +03:00
return bool ( self . inbound_average or self . inbound_peak or
self . inbound_burst or self . inbound_floor )
2014-06-25 14:27:00 +04:00
def is_outbound ( self ) :
2015-07-10 15:07:02 +03:00
return bool ( self . outbound_average or self . outbound_peak or
self . outbound_burst )
2014-06-25 14:27:00 +04:00
def pretty_desc ( self , inbound = True , outbound = True ) :
items_in = [ ( self . inbound_average , _ ( " Average " ) , " KiB/s " ) ,
( self . inbound_peak , _ ( " Peak " ) , " KiB " ) ,
( self . inbound_burst , _ ( " Burst " ) , " KiB/s " ) ,
( self . inbound_floor , _ ( " Floor " ) , " KiB/s " ) ]
items_out = [ ( self . outbound_average , _ ( " Average " ) , " KiB/s " ) ,
( self . outbound_peak , _ ( " Peak " ) , " KiB " ) ,
( self . outbound_burst , _ ( " Burst " ) , " KiB/s " ) ]
def stringify_items ( items ) :
return " , " . join ( [ " %s : %s %s " % ( desc , val , unit )
for val , desc , unit in items if val ] )
ret = " "
show_name = inbound and outbound
if inbound :
if show_name :
ret + = _ ( " Inbound: " )
ret + = stringify_items ( items_in )
if outbound :
if ret :
ret + = " \n "
if show_name :
ret + = _ ( " Outbound: " )
ret + = stringify_items ( items_out )
return ret
2014-05-31 22:20:56 +04:00
class _NetworkPortgroup ( XMLBuilder ) :
_XML_ROOT_NAME = " portgroup "
name = XMLProperty ( " ./@name " )
default = XMLProperty ( " ./@default " , is_yesno = True )
2013-09-21 04:40:07 +04:00
class Network ( XMLBuilder ) :
"""
Top level class for < network > object XML
"""
@staticmethod
def pretty_forward_desc ( mode , dev ) :
if mode or dev :
if not mode or mode == " nat " :
if dev :
desc = _ ( " NAT to %s " ) % dev
else :
desc = _ ( " NAT " )
elif mode == " route " :
if dev :
desc = _ ( " Route to %s " ) % dev
else :
desc = _ ( " Routed network " )
else :
if dev :
desc = " %s to %s " % ( mode , dev )
else :
desc = " %s network " % mode . capitalize ( )
else :
desc = _ ( " Isolated network, internal and host routing only " )
return desc
def __init__ ( self , * args , * * kwargs ) :
XMLBuilder . __init__ ( self , * args , * * kwargs )
self . _random_uuid = None
2013-09-23 01:04:22 +04:00
###################
# Helper routines #
###################
def can_pxe ( self ) :
forward = self . forward . mode
if forward and forward != " nat " :
return True
for ip in self . ips :
if ip . bootp_file :
return True
return False
2013-09-21 04:40:07 +04:00
######################
# Validation helpers #
######################
2014-01-18 03:40:30 +04:00
def _validate_name ( self , name ) :
util . validate_name ( _ ( " Network " ) , name )
2013-09-21 04:40:07 +04:00
try :
self . conn . networkLookupByName ( name )
except libvirt . libvirtError :
return
raise ValueError ( _ ( " Name ' %s ' already in use by another network. " %
name ) )
def _get_default_uuid ( self ) :
if self . _random_uuid is None :
self . _random_uuid = util . generate_uuid ( self . conn )
return self . _random_uuid
##################
# XML properties #
##################
_XML_ROOT_NAME = " network "
_XML_PROP_ORDER = [ " ipv6 " , " name " , " uuid " , " forward " ,
" bridge " , " stp " , " delay " , " domain_name " ,
2014-06-25 14:27:00 +04:00
" macaddr " , " ips " , " routes " , " bandwidth " ]
2013-09-21 04:40:07 +04:00
ipv6 = XMLProperty ( " ./@ipv6 " , is_yesno = True )
2014-01-18 03:40:30 +04:00
name = XMLProperty ( " ./name " , validate_cb = _validate_name )
2013-09-21 04:40:07 +04:00
uuid = XMLProperty ( " ./uuid " ,
validate_cb = lambda s , v : util . validate_uuid ( v ) ,
default_cb = _get_default_uuid )
# Not entirely correct, there can be multiple routes
forward = XMLChildProperty ( _NetworkForward , is_single = True )
domain_name = XMLProperty ( " ./domain/@name " )
bridge = XMLProperty ( " ./bridge/@name " )
stp = XMLProperty ( " ./bridge/@stp " , is_onoff = True )
delay = XMLProperty ( " ./bridge/@delay " , is_int = True )
macaddr = XMLProperty ( " ./mac/@address " )
2014-05-31 22:20:56 +04:00
portgroups = XMLChildProperty ( _NetworkPortgroup )
2013-09-21 04:40:07 +04:00
ips = XMLChildProperty ( _NetworkIP )
routes = XMLChildProperty ( _NetworkRoute )
2014-06-25 14:27:00 +04:00
bandwidth = XMLChildProperty ( _NetworkBandwidth , is_single = True )
2013-09-21 04:40:07 +04:00
2013-09-23 21:21:35 +04:00
def add_ip ( self ) :
ip = _NetworkIP ( self . conn )
2015-09-04 22:45:45 +03:00
self . add_child ( ip )
2013-09-23 21:21:35 +04:00
return ip
def add_route ( self ) :
2013-09-21 04:40:07 +04:00
route = _NetworkRoute ( self . conn )
2015-09-04 22:45:45 +03:00
self . add_child ( route )
2013-09-23 21:21:35 +04:00
return route
2013-09-30 23:06:52 +04:00
2014-05-31 22:20:56 +04:00
2013-09-30 23:06:52 +04:00
##################
# build routines #
##################
def install ( self , start = True , autostart = True ) :
xml = self . get_xml_config ( )
logging . debug ( " Creating virtual network ' %s ' with xml: \n %s " ,
self . name , xml )
net = self . conn . networkDefineXML ( xml )
try :
if start :
net . create ( )
if autostart :
net . setAutostart ( autostart )
except :
net . undefine ( )
raise
return net