Change in vdsm[master]: virt: enable libgfapi with snapshot support
by Federico Simoncelli
Federico Simoncelli has uploaded a new change for review.
Change subject: virt: enable libgfapi with snapshot support
......................................................................
virt: enable libgfapi with snapshot support
Change-Id: Ie0965bef605ba67297670c0bf7924f88fa3b0460
Signed-off-by: Federico Simoncelli <fsimonce(a)redhat.com>
---
M vdsm/storage/hsm.py
M vdsm/virt/vm.py
2 files changed, 38 insertions(+), 17 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/68/33768/1
diff --git a/vdsm/storage/hsm.py b/vdsm/storage/hsm.py
index cd6f4b9..bde04be 100644
--- a/vdsm/storage/hsm.py
+++ b/vdsm/storage/hsm.py
@@ -3225,8 +3225,7 @@
path = os.path.join(dom.domaindir, sd.DOMAIN_IMAGES, imgUUID,
volUUID)
volInfo = {'domainID': sdUUID, 'imageID': imgUUID,
- 'volumeID': volUUID, 'path': path,
- 'volType': "path"}
+ 'volumeID': volUUID, 'path': path}
leasePath, leaseOffset = dom.getVolumeLease(imgUUID, volUUID)
@@ -3237,8 +3236,8 @@
})
imgVolumesInfo.append(volInfo)
- if volUUID == leafUUID:
- leafInfo = volInfo
+
+ leafInfo = dom.produceVolume(imgUUID, volUUID).getVmVolumeInfo()
return {'path': leafPath, 'info': leafInfo,
'imgVolumesInfo': imgVolumesInfo}
diff --git a/vdsm/virt/vm.py b/vdsm/virt/vm.py
index 1eebb69..af0830a 100644
--- a/vdsm/virt/vm.py
+++ b/vdsm/virt/vm.py
@@ -3821,20 +3821,43 @@
def snapshot(self, snapDrives, memoryParams):
"""Live snapshot command"""
- def _diskSnapshot(vmDev, newPath, sourceType):
+ def _diskSnapshot(vmDev, oldDrive, newDriveDict):
"""Libvirt snapshot XML"""
+ sourceType = 'file'
+ sourceAttrs = {}
+ hostAttrs = {}
+
+ # TODO: unify these with the Drive.getXML() method
+ if oldDrive.networkDev:
+ sourceType = 'network'
+ sourceAttrs.update({
+ 'name': newDriveDict['volumeInfo']['path'],
+ 'protocol': newDriveDict['volumeInfo']['protocol']})
+ hostAttrs.update({
+ 'name': newDriveDict['volumeInfo']['volfileServer'],
+ 'port': newDriveDict['volumeInfo']['volPort'],
+ 'transport': newDriveDict['volumeInfo']['volTransport']})
+ else:
+ sourceAttrs.update({'file': newDriveDict['path']})
+
+ # Libvirt versions before 1.2.2 do not understand 'type'
+ # and treat all snapshots as if they are type='file'.
+ # In order to ensure proper handling of block snapshots
+ # in modern libvirt versions, we specify type='block'
+ # and dev=path for block volumes but we always speficy
+ # the file=path for backwards compatibility.
+ if oldDrive.blockDev:
+ sourceType = 'block'
+ sourceAttrs.update({'dev': newDriveDict['path']})
disk = vmxml.Element('disk', name=vmDev, snapshot='external',
type=sourceType)
- # Libvirt versions before 1.2.2 do not understand 'type' and treat
- # all snapshots as if they are type='file'. In order to ensure
- # proper handling of block snapshots in modern libvirt versions,
- # we specify type='block' and dev=path for block volumes but we
- # always speficy the file=path for backwards compatibility.
- args = {'type': sourceType, 'file': newPath}
- if sourceType == 'block':
- args['dev'] = newPath
- disk.appendChildWithArgs('source', **args)
+
+ source = disk.appendChildWithArgs('source', **sourceAttrs)
+
+ if hostAttrs:
+ source.appendChildWithArgs('host', **hostAttrs)
+
return disk
def _normSnapDriveParams(drive):
@@ -3964,9 +3987,8 @@
_rollbackDrives(preparedDrives)
return errCode['snapshotErr']
- snapType = 'block' if vmDrives[vmDevName].blockDev else 'file'
- snapelem = _diskSnapshot(vmDevName, newDrives[vmDevName]["path"],
- snapType)
+ snapelem = _diskSnapshot(vmDevName, vmDrives[vmDevName],
+ newDrives[vmDevName])
disks.appendChild(snapelem)
snap.appendChild(disks)
--
To view, visit http://gerrit.ovirt.org/33768
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie0965bef605ba67297670c0bf7924f88fa3b0460
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Federico Simoncelli <fsimonce(a)redhat.com>
8 years, 10 months
Change in vdsm[master]: net_func_tests: Make use of TEST-NET range instead of future...
by asegurap@redhat.com
Antoni Segura Puimedon has uploaded a new change for review.
Change subject: net_func_tests: Make use of TEST-NET range instead of future reserved range
......................................................................
net_func_tests: Make use of TEST-NET range instead of future reserved range
IPv4 has, according to RFC 5737, three network ranges that are
specifically designed to be used for tests and code samples. Up
until now we were using 240.0.0.0/24 that is part of 240.0.0.0/4
which according to RFC 6890 is reserved for future use. Thus, it
is more appropriate to use one of the test networks and this patch
does just that.
Change-Id: I31ed725b3092da48723ea213ad80205961d9e65a
Signed-off-by: Antoni S. Puimedon <asegurap(a)redhat.com>
---
M tests/functional/networkTests.py
1 file changed, 7 insertions(+), 6 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/59/31259/1
diff --git a/tests/functional/networkTests.py b/tests/functional/networkTests.py
index f02c2bc..3afd932 100644
--- a/tests/functional/networkTests.py
+++ b/tests/functional/networkTests.py
@@ -53,16 +53,17 @@
NETWORK_NAME = 'test-network'
VLAN_ID = '27'
BONDING_NAME = 'bond0'
-IP_ADDRESS = '240.0.0.1'
-IP_NETWORK = '240.0.0.0'
-IP_ADDRESS_IN_NETWORK = '240.0.0.50'
+# Use TEST-NET network (RFC 5737)
+IP_ADDRESS = '192.0.2.1'
+IP_NETWORK = '192.0.2.0'
+IP_ADDRESS_IN_NETWORK = '192.0.2.2'
IP_CIDR = '24'
IP_NETWORK_AND_CIDR = IP_NETWORK + '/' + IP_CIDR
-IP_GATEWAY = '240.0.0.254'
+IP_GATEWAY = '192.0.2.254'
+DHCP_RANGE_FROM = '192.0.2.10'
+DHCP_RANGE_TO = '192.0.2.100'
# Current implementation converts ip to its 32 bit int representation
IP_TABLE = '4026531841'
-DHCP_RANGE_FROM = '240.0.0.10'
-DHCP_RANGE_TO = '240.0.0.100'
CUSTOM_PROPS = {'linux': 'rules', 'vdsm': 'as well'}
IPv6_ADDRESS = 'fdb3:84e5:4ff4:55e3::1/64'
--
To view, visit http://gerrit.ovirt.org/31259
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I31ed725b3092da48723ea213ad80205961d9e65a
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Antoni Segura Puimedon <asegurap(a)redhat.com>
8 years, 10 months
Change in vdsm[master]: extra_ipv4_addrs_hook: Add a hook for configuring secondary ...
by asegurap@redhat.com
Antoni Segura Puimedon has uploaded a new change for review.
Change subject: extra_ipv4_addrs_hook: Add a hook for configuring secondary addrs
......................................................................
extra_ipv4_addrs_hook: Add a hook for configuring secondary addrs
Sometimes it might be useful to set up extra addresses for the top
network device. This patch creates an after_network_setup hook that
allows just that, thanks to the custom network properties.
Change-Id: Id465870df6274552a68f6c9c0b907a843f08bf58
Signed-off-by: Antoni S. Puimedon <asegurap(a)redhat.com>
---
M configure.ac
A debian/vdsm-hook-extra-ipv4-addrs.docs
A debian/vdsm-hook-extra-ipv4-addrs.install
M vdsm.spec.in
M vdsm_hooks/Makefile.am
A vdsm_hooks/extra_ipv4_addrs/Makefile.am
A vdsm_hooks/extra_ipv4_addrs/README
A vdsm_hooks/extra_ipv4_addrs/extra_ipv4_addrs.py
A vdsm_hooks/extra_ipv4_addrs/sudoers
9 files changed, 147 insertions(+), 0 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/38/29738/1
diff --git a/configure.ac b/configure.ac
index d741c1b..c319196 100644
--- a/configure.ac
+++ b/configure.ac
@@ -287,6 +287,7 @@
vdsm_hooks/directlun/Makefile
vdsm_hooks/ethtool_options/Makefile
vdsm_hooks/extnet/Makefile
+ vdsm_hooks/extra_ipv4_addrs/Makefile
vdsm_hooks/fakevmstats/Makefile
vdsm_hooks/faqemu/Makefile
vdsm_hooks/fileinject/Makefile
diff --git a/debian/vdsm-hook-extra-ipv4-addrs.docs b/debian/vdsm-hook-extra-ipv4-addrs.docs
new file mode 100644
index 0000000..5ecd9c6
--- /dev/null
+++ b/debian/vdsm-hook-extra-ipv4-addrs.docs
@@ -0,0 +1 @@
+COPYING
diff --git a/debian/vdsm-hook-extra-ipv4-addrs.install b/debian/vdsm-hook-extra-ipv4-addrs.install
new file mode 100644
index 0000000..f31188d
--- /dev/null
+++ b/debian/vdsm-hook-extra-ipv4-addrs.install
@@ -0,0 +1 @@
+usr/libexec/vdsm/hooks/after_network_setup/30_extra_ipv4_addrs
diff --git a/vdsm.spec.in b/vdsm.spec.in
index 2b67962..4fedafd 100644
--- a/vdsm.spec.in
+++ b/vdsm.spec.in
@@ -1282,6 +1282,10 @@
%{_libexecdir}/%{vdsm_name}/hooks/after_vm_destroy/50_directlun
%{_libexecdir}/%{vdsm_name}/hooks/before_vm_migrate_destination/50_directlun
+%files hook-extra-ipv4-addrs
+%defattr(-, root, root, -)
+%{_libexecdir}/%{vdsm_name}/hooks/after_network_setup/30_extra_ipv4_addrs
+
%files hook-fakevmstats
%defattr(-, root, root, -)
%{_libexecdir}/%{vdsm_name}/hooks/after_get_all_vm_stats/10_fakevmstats
diff --git a/vdsm_hooks/Makefile.am b/vdsm_hooks/Makefile.am
index 5e4d731..e05bf84 100644
--- a/vdsm_hooks/Makefile.am
+++ b/vdsm_hooks/Makefile.am
@@ -28,6 +28,7 @@
checkimages \
directlun \
extnet \
+ extra_ipv4_addrs \
fileinject \
fakevmstats \
floppy \
diff --git a/vdsm_hooks/extra_ipv4_addrs/Makefile.am b/vdsm_hooks/extra_ipv4_addrs/Makefile.am
new file mode 100644
index 0000000..1d987fe
--- /dev/null
+++ b/vdsm_hooks/extra_ipv4_addrs/Makefile.am
@@ -0,0 +1,38 @@
+#
+# Copyright 2014 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Refer to the README and COPYING files for full details of the license
+#
+
+EXTRA_DIST = \
+ extra_ipv4_addrs.py
+
+install-data-local:
+ $(MKDIR_P) $(DESTDIR)$(vdsmhooksdir)/after_network_setup
+ $(INSTALL_SCRIPT) $(srcdir)/extra_ipv4_addrs.py \
+ $(DESTDIR)$(vdsmhooksdir)/after_network_setup/30_extra_ipv4_addrs
+
+uninstall-local:
+ $(RM) $(DESTDIR)$(vdsmhooksdir)/after_network_setup/30_extra_ipv4_addrs
+
+install-data-sudoers:
+ $(MKDIR_P) $(DESTDIR)$(sysconfdir)/sudoers.d
+ $(INSTALL_DATA) $(srcdir)/sudoers \
+ $(DESTDIR)$(sysconfdir)/sudoers.d/50_vdsm_hook_extra_ipv4_addrs
+
+uninstall-data-sudoers:
+ $(RM) $(DESTDIR)$(sysconfdir)/sudoers.d/50_vdsm_hook_extra_ipv4_addrs
diff --git a/vdsm_hooks/extra_ipv4_addrs/README b/vdsm_hooks/extra_ipv4_addrs/README
new file mode 100644
index 0000000..01e4675
--- /dev/null
+++ b/vdsm_hooks/extra_ipv4_addrs/README
@@ -0,0 +1,17 @@
+extra_ipv4_addrs vdsm hook
+=================================
+This hook allows the user to set extra ipv4 addresses for vdsm networks.
+
+Requirements:
+* oVirt-3.5
+
+Usage:
+Configure the engine to enable setting the ipv4_addrs custom property by doing:
+
+ $ engine-config -s 'UserDefinedNetworkCustomProperties=ipv4_addrs=.*' \
+ --cver='3.5'
+
+In the oVirt UI edit custom network properties and, for the key 'ipv4_addrs'
+set the extra addresses in the following format:
+
+ 'addr/prefix, addr2/prefix2, ..., addrN/prefixN'
diff --git a/vdsm_hooks/extra_ipv4_addrs/extra_ipv4_addrs.py b/vdsm_hooks/extra_ipv4_addrs/extra_ipv4_addrs.py
new file mode 100644
index 0000000..419e7bf
--- /dev/null
+++ b/vdsm_hooks/extra_ipv4_addrs/extra_ipv4_addrs.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+# Copyright 2014 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Refer to the README and COPYING files for full details of the license
+#
+import sys
+import hooking
+import traceback
+
+from vdsm import ipwrapper, utils
+
+
+def test():
+ opts = {'ipv4_addrs': '192.168.234.211/24, 192.168.211.234/24'}
+
+ nets = {'brless_bonded': {'bonding': 'james', 'custom': opts,
+ 'bootproto': 'dhcp', 'STP': 'no',
+ 'bridged': 'false', 'top_dev': 'james'},
+ 'brless_nic': {'nic': 'em1', 'custom': opts, 'bootproto': 'none',
+ 'ipaddr': '192.168.23.24',
+ 'netmask': '255.255.255.0', 'bridged': 'false',
+ 'top_dev': 'em1'},
+ 'brnet': {'nic': 'em1', 'custom': opts, 'bootproto': 'none',
+ 'ipaddr': '192.168.23.24', 'netmask': '255.255.255.0',
+ 'bridged': 'true', 'top_dev': 'brnet'}}
+
+ for net, attrs in nets.items():
+ print('Top device of network %s(%r) is %s' %
+ (net, attrs, _top_dev(net, attrs)))
+
+
+def main():
+ """Read ipv4_addrs from the network 'custom' properties and apply them
+ to the network's top device"""
+ setup_nets_config = hooking.read_json()
+ for network, attrs in setup_nets_config['request']['networks'].items():
+ if 'remove' in attrs:
+ continue
+ elif 'custom' in attrs:
+ _process_network(network, attrs)
+
+
+def _process_network(network, attrs):
+ """Applies extra ipv4 addresses to the network if necessary"""
+ options = attrs['custom'].get('ipv4_addrs')
+ if options is not None:
+ top_dev = _top_dev(network, attrs)
+ addresses = options.split(', ')
+ for addr in addresses:
+ ip, prefix = addr.split('/')
+ ipwrapper.addrAdd(top_dev, ip, prefix)
+
+
+def _top_dev(network, attrs):
+ if utils.tobool(attrs.get('bridged')):
+ return network
+ else: # bridgeless
+ return attrs.get('bonding') or attrs.get('nic')
+
+
+if __name__ == '__main__':
+ try:
+ if '--test' in sys.argv:
+ test()
+ else:
+ main()
+ except:
+ hooking.exit_hook('extra ipv4 addrs hook: [unexpected error]: %s\n' %
+ traceback.format_exc())
diff --git a/vdsm_hooks/extra_ipv4_addrs/sudoers b/vdsm_hooks/extra_ipv4_addrs/sudoers
new file mode 100644
index 0000000..f996069
--- /dev/null
+++ b/vdsm_hooks/extra_ipv4_addrs/sudoers
@@ -0,0 +1 @@
+vdsm ALL=(ALL) NOPASSWD: /usr/sbin/ip, /sbin/ip, /usr/bin/ip
--
To view, visit http://gerrit.ovirt.org/29738
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Id465870df6274552a68f6c9c0b907a843f08bf58
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Antoni Segura Puimedon <asegurap(a)redhat.com>
8 years, 10 months
Change in vdsm[master]: arbitrary_vlan_name: Fix network deletion
by asegurap@redhat.com
Antoni Segura Puimedon has uploaded a new change for review.
Change subject: arbitrary_vlan_name: Fix network deletion
......................................................................
arbitrary_vlan_name: Fix network deletion
Up until now, when the network deletion operations were not being
forced, the assertion that the bridge was clean, i.e., that it did
not have other ports (vnics most likely) would fail because it
expected
bondname.vlanid
or
nic.vlanid
when the name could be any string. This patch addresses the issue
by making netinfo give us the exact vlan name.
Change-Id: I715806db38ce621098fe5f364e16e874a5ed01ed
Bug-Url: http://bugzilla.redhat.com/1119182
Signed-off-by: Antoni S. Puimedon <asegurap(a)redhat.com>
---
M lib/vdsm/netinfo.py
M vdsm/network/api.py
M vdsm/network/models.py
3 files changed, 28 insertions(+), 17 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/13/30013/1
diff --git a/lib/vdsm/netinfo.py b/lib/vdsm/netinfo.py
index 95c3860..d7e7b6c 100644
--- a/lib/vdsm/netinfo.py
+++ b/lib/vdsm/netinfo.py
@@ -929,6 +929,7 @@
def getNicsVlanAndBondingForNetwork(self, network):
vlan = None
+ vlanid = None
bonding = None
lnics = []
@@ -943,7 +944,8 @@
if port in self.vlans:
assert vlan is None
nic = getVlanDevice(port)
- vlan = getVlanID(port)
+ vlanid = getVlanID(port)
+ vlan = port # vlan devices can have an arbitrary name
assert self.vlans[port]['iface'] == nic
port = nic
if port in self.bondings:
@@ -953,7 +955,7 @@
elif port in self.nics:
lnics.append(port)
- return lnics, vlan, bonding
+ return lnics, vlan, vlanid, bonding
def ifaceUsers(self, iface):
"Returns a list of entities using the interface"
diff --git a/vdsm/network/api.py b/vdsm/network/api.py
index ba99f3e..32e26c1 100755
--- a/vdsm/network/api.py
+++ b/vdsm/network/api.py
@@ -66,7 +66,7 @@
persistence = _getPersistenceModule()
-def objectivizeNetwork(bridge=None, vlan=None, bonding=None,
+def objectivizeNetwork(bridge=None, vlan=None, vlan_id=None, bonding=None,
bondingOptions=None, nics=None, mtu=None, ipaddr=None,
netmask=None, gateway=None, bootproto=None,
ipv6addr=None, ipv6gateway=None, ipv6autoconf=None,
@@ -78,7 +78,8 @@
that is passed in the parameters.
:param bridge: name of the bridge.
- :param vlan: vlan tag id.
+ :param vlan: vlan device name.
+ :param vlan_id: vlan tag id.
:param bonding: name of the bond.
:param bondingOptions: bonding options separated by spaces.
:param nics: list of nic names.
@@ -129,7 +130,10 @@
'enslaved to %s' % (nic, bond))
topNetDev = Nic(nic, configurator, mtu=mtu, _netinfo=_netinfo)
if vlan is not None:
- topNetDev = Vlan(topNetDev, vlan, configurator, mtu=mtu)
+ tag = netinfo.getVlanID(vlan) if vlan_id is None else vlan_id
+ topNetDev = Vlan(topNetDev, tag, configurator, mtu=mtu, name=vlan)
+ elif vlan_id is not None:
+ topNetDev = Vlan(topNetDev, vlan_id, configurator, mtu=mtu)
if bridge is not None:
stp = None
if 'stp' in opts:
@@ -315,7 +319,7 @@
bootproto = options.pop('bootproto', None)
netEnt = objectivizeNetwork(
- bridge=network if bridged else None, vlan=vlan, bonding=bonding,
+ bridge=network if bridged else None, vlan_id=vlan, bonding=bonding,
bondingOptions=bondingOptions, nics=nics, mtu=mtu, ipaddr=ipaddr,
netmask=netmask, gateway=gateway, bootproto=bootproto,
blockingdhcp=blockingdhcp, ipv6addr=ipv6addr, ipv6gateway=ipv6gateway,
@@ -332,7 +336,7 @@
ports = set(netinfo.ports(bridge))
ifaces = set(nics)
if vlan is not None:
- ifaces.add('%s.%s' % ((bonding or nics[0]), vlan))
+ ifaces.add(vlan)
else:
ifaces.add(bonding)
@@ -352,7 +356,8 @@
bridged = _netinfo.networks[network]['bridged']
print "Network %s(Bridged: %s):" % (network, bridged)
- nics, vlan, bonding = _netinfo.getNicsVlanAndBondingForNetwork(network)
+ nics, vlan, vlan_id, bonding = _netinfo.getNicsVlanAndBondingForNetwork(
+ network)
if bridged:
ipaddr = _netinfo.networks[network]['addr']
@@ -365,7 +370,7 @@
netmask = _netinfo.nics[iface]['netmask']
print "ipaddr=%s, netmask=%s" % (ipaddr, netmask)
- print "vlan=%s, bonding=%s, nics=%s" % (vlan, bonding, nics)
+ print "vlan=%s, bonding=%s, nics=%s" % (vlan_id, bonding, nics)
def listNetworks():
@@ -408,8 +413,9 @@
def _delNonVdsmNetwork(network, vlan, bonding, nics, _netinfo, configurator):
if network in netinfo.bridges():
- netEnt = objectivizeNetwork(bridge=network, vlan=vlan, bonding=bonding,
- nics=nics, _netinfo=_netinfo,
+ netEnt = objectivizeNetwork(bridge=network, vlan_id=vlan,
+ bonding=bonding, nics=nics,
+ _netinfo=_netinfo,
configurator=configurator,
implicitBonding=False)
netEnt.remove()
@@ -436,7 +442,8 @@
configurator)
return
- nics, vlan, bonding = _netinfo.getNicsVlanAndBondingForNetwork(network)
+ nics, vlan, vlan_id, bonding = _netinfo.getNicsVlanAndBondingForNetwork(
+ network)
bridged = _netinfo.networks[network]['bridged']
logging.info("Removing network %s with vlan=%s, bonding=%s, nics=%s,"
@@ -446,8 +453,8 @@
_validateDelNetwork(network, vlan, bonding, nics, bridged, _netinfo)
netEnt = objectivizeNetwork(bridge=network if bridged else None, vlan=vlan,
- bonding=bonding, nics=nics, _netinfo=_netinfo,
- configurator=configurator,
+ vlan_id=vlan_id, bonding=bonding, nics=nics,
+ _netinfo=_netinfo, configurator=configurator,
implicitBonding=implicitBonding)
netEnt.ip.bootproto = netinfo.getBootProtocol(netEnt.name)
diff --git a/vdsm/network/models.py b/vdsm/network/models.py
index 402a4b5..c3b9409 100644
--- a/vdsm/network/models.py
+++ b/vdsm/network/models.py
@@ -115,7 +115,8 @@
class Vlan(NetDevice):
MAX_ID = 4094
- def __init__(self, device, tag, configurator, ipconfig=None, mtu=None):
+ def __init__(self, device, tag, configurator, ipconfig=None, mtu=None,
+ name=None):
self.validateTag(tag)
if device is None:
raise ConfigNetworkError(ne.ERR_BAD_PARAMS, 'Missing required vlan'
@@ -123,8 +124,9 @@
device.master = self
self.device = device
self.tag = tag
- super(Vlan, self).__init__('%s.%s' % (device.name, tag), configurator,
- ipconfig, mtu)
+ # control for arbitrary vlan names
+ name = '%s.%s' % (device.name, tag) if name is None else name
+ super(Vlan, self).__init__(name, configurator, ipconfig, mtu)
def __repr__(self):
return 'Vlan(%s: %r)' % (self.name, self.device)
--
To view, visit http://gerrit.ovirt.org/30013
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I715806db38ce621098fe5f364e16e874a5ed01ed
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Antoni Segura Puimedon <asegurap(a)redhat.com>
8 years, 10 months
Change in vdsm[master]: netinfo: Drop ifcfg reading from _getNetInfo
by asegurap@redhat.com
Antoni Segura Puimedon has uploaded a new change for review.
Change subject: netinfo: Drop ifcfg reading from _getNetInfo
......................................................................
netinfo: Drop ifcfg reading from _getNetInfo
For backwards compatibility we need to report the bridge 'cfg' field
in the network attributes dictionary. Up until now, this was done by
re-reading the 'ifcfg' files of the bridge. After this change, we
will just be adding the 'cfg' field that we already generated for the
bridge device.
Note that 'BOOTPROTO' reporting is already part of _devinfo, so we
don't need that part.
Change-Id: I2a80251cc45792ba5511d22bce9451fb3b36689d
Signed-off-by: Antoni S. Puimedon <asegurap(a)redhat.com>
---
M lib/vdsm/netinfo.py
1 file changed, 5 insertions(+), 10 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/12/35012/1
diff --git a/lib/vdsm/netinfo.py b/lib/vdsm/netinfo.py
index d2ef90b..20eadbe 100644
--- a/lib/vdsm/netinfo.py
+++ b/lib/vdsm/netinfo.py
@@ -448,8 +448,8 @@
data = {}
try:
if bridged:
- data.update({'ports': ports(iface), 'stp': bridge_stp_state(iface),
- 'cfg': getIfaceCfg(iface)})
+ data.update({'ports': ports(iface),
+ 'stp': bridge_stp_state(iface)})
else:
# ovirt-engine-3.1 expects to see the "interface" attribute iff the
# network is bridgeless. Please remove the attribute and this
@@ -647,13 +647,6 @@
return d
-def _cfgBootprotoCompat(networks):
- """Set network 'cfg' 'BOOTPROTO' for backwards engine compatibility."""
- for netAttrs in networks.itervalues():
- if netAttrs['bridged'] and 'BOOTPROTO' not in netAttrs['cfg']:
- netAttrs['cfg']['BOOTPROTO'] = netAttrs['bootproto4']
-
-
def get(vdsmnets=None):
d = {'bondings': {}, 'bridges': {}, 'networks': {}, 'nics': {},
'vlans': {}}
@@ -683,7 +676,9 @@
if dev.isBOND():
_bondOptsCompat(devinfo)
- _cfgBootprotoCompat(d['networks'])
+ for net, attrs in d['networks']:
+ if attrs['bridged']:
+ attrs['cfg'] = d['bridges'][net]['cfg']
return d
--
To view, visit http://gerrit.ovirt.org/35012
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I2a80251cc45792ba5511d22bce9451fb3b36689d
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Antoni Segura Puimedon <asegurap(a)redhat.com>
8 years, 10 months
Change in vdsm[master]: net_func_tests: restore when tests don't clean up after them...
by asegurap@redhat.com
Antoni Segura Puimedon has uploaded a new change for review.
Change subject: net_func_tests: restore when tests don't clean up after themselves
......................................................................
net_func_tests: restore when tests don't clean up after themselves
After the patch that made the rollback after each test happen only
in case of exception, some tests could fail if the previous test did
not perform a good cleanup.
With this change, we check that the Running Config is always the
original one between tests and that at the end of all the tests
we'll have the original RunningConfig and PersistentConfig.
Change-Id: I0678e1194c31b71c0179c7b46d697a186d44e1c1
Signed-off-by: Antoni S. Puimedon <asegurap(a)redhat.com>
---
M tests/functional/networkTests.py
1 file changed, 39 insertions(+), 5 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/10/35710/1
diff --git a/tests/functional/networkTests.py b/tests/functional/networkTests.py
index 3ea1db0..17fe59b 100644
--- a/tests/functional/networkTests.py
+++ b/tests/functional/networkTests.py
@@ -41,11 +41,13 @@
from vdsm.ipwrapper import (routeExists, ruleExists, addrFlush, LinkType,
getLinks, routeShowTable)
+from vdsm.config import config
from vdsm.constants import EXT_BRCTL
from vdsm.utils import RollbackContext, execCmd, running
from vdsm.netinfo import (bridges, operstate, prefix2netmask, getRouteDeviceTo,
getDhclientIfaces)
from vdsm import ipwrapper
+from vdsm import netconfpersistence
from vdsm.utils import pgrep
import caps
@@ -80,16 +82,18 @@
def setupModule():
"""Persists network configuration."""
- vdsm = VdsProxy()
- vdsm.save_config()
+ if config.get('vars', 'net_persistence') == 'ifcfg':
+ vdsm = VdsProxy()
+ vdsm.save_config()
for _ in range(DUMMY_POOL_SIZE):
dummyPool.add(dummy.create())
def tearDownModule():
"""Restores the network configuration previous to running tests."""
- vdsm = VdsProxy()
- vdsm.restoreNetConfig()
+ if config.get('vars', 'net_persistence') == 'ifcfg':
+ vdsm = VdsProxy()
+ vdsm.restoreNetConfig()
for nic in dummyPool:
dummy.remove(nic)
@@ -220,6 +224,21 @@
def setUp(self):
self.vdsm_net = VdsProxy()
+ if self.vdsm_net.config is not None: # unified persistence
+ self.pre_running_config = self.vdsm_net.config
+ self.pre_persistent_config = netconfpersistence.PersistentConfig()
+ self.skip_rest = False
+
+ def tearDown(self):
+ if self.vdsm_net.config is not None: # unified persistence
+ diff = self.pre_running_config.diffFrom(self.vdsm_net.config)
+ if diff:
+ self.vdsm_net.setupNetworks(
+ diff.networks, diff.bonds,
+ {'connectivityCheck': False, '_inRollback=True': True})
+
+ # Put back whichever persistent config was at the start
+ self.pre_persistent_config.store()
def cleanupNet(func):
"""
@@ -230,9 +249,24 @@
@wraps(func)
def wrapper(*args, **kwargs):
+ self = args[0]
+ if self.vdsm_net.config is not None and self.skip_rest:
+ raise SkipTest('The environment is not clean due to a '
+ 'previous test. Skipping!')
with RollbackContext(on_exception_only=True) as rollback:
- rollback.prependDefer(args[0].vdsm_net.restoreNetConfig)
+ rollback.prependDefer(self.vdsm_net.restoreNetConfig)
func(*args, **kwargs)
+ if self.vdsm_net.config is not None: # unified persistence
+ # Cleaning up after messy non-failing tests
+ diff = self.pre_running_config.diffFrom(
+ self.vdsm_net.config)
+ if diff:
+ status, msg = self.vdsm_net.setupNetworks(
+ diff.networks, diff.bonds,
+ {'connectivityCheck': False,
+ '_inRollback=True': True})
+ if status != SUCCESS:
+ self.skip_rest = True
return wrapper
def assertNetworkExists(self, networkName, bridged=None, bridgeOpts=None,
--
To view, visit http://gerrit.ovirt.org/35710
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I0678e1194c31b71c0179c7b46d697a186d44e1c1
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Antoni Segura Puimedon <asegurap(a)redhat.com>
8 years, 10 months
Change in vdsm[master]: netconf_persistence: teach PersistentConfig to atomically st...
by asegurap@redhat.com
Antoni Segura Puimedon has uploaded a new change for review.
Change subject: netconf_persistence: teach PersistentConfig to atomically store itself
......................................................................
netconf_persistence: teach PersistentConfig to atomically store itself
This will be used by the test code and in the future by a python
vdsm-store-net-config.
Change-Id: Ida957b6c68607743b9efa85f4263451c955b398a
Signed-off-by: Antoni S. Puimedon <asegurap(a)redhat.com>
---
M lib/vdsm/netconfpersistence.py
1 file changed, 37 insertions(+), 2 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/09/35709/1
diff --git a/lib/vdsm/netconfpersistence.py b/lib/vdsm/netconfpersistence.py
index f0aac38..80b2ab7 100644
--- a/lib/vdsm/netconfpersistence.py
+++ b/lib/vdsm/netconfpersistence.py
@@ -19,9 +19,11 @@
#
import errno
+import glob
import json
import logging
import os
+import time
from .config import config
from .tool.restore_nets import restore
@@ -33,7 +35,8 @@
# The persistent path is inside of an extra "persistence" dir in order to get
# oVirt Node to persist the symbolic links that are necessary for the
# atomic storage of running config into persistent config.
-CONF_PERSIST_DIR = constants.P_VDSM_LIB + 'persistence/netconf/'
+CONF_PERSIST_DIR = constants.P_VDSM_LIB + 'persistence/'
+CONF_PERSIST_NETCONF_DIR = CONF_PERSIST_DIR + 'netconf/'
class BaseConfig(object):
@@ -194,12 +197,44 @@
class PersistentConfig(Config):
def __init__(self):
- super(PersistentConfig, self).__init__(CONF_PERSIST_DIR)
+ super(PersistentConfig, self).__init__(CONF_PERSIST_NETCONF_DIR)
def restore(self):
restore()
return RunningConfig()
+ def store(self):
+ """Atomically stores PersistentConfig"""
+ symlink_path = os.path.dirname(CONF_PERSIST_NETCONF_DIR)
+ timestamp = _nano_timestamp()
+ new_dir = symlink_path + '.' + timestamp
+ super(PersistentConfig, self).__init__(new_dir)
+ new_symlink = symlink_path + '.link.' + timestamp
+
+ logging.debug('Persistence: persisting "%s"' % new_dir)
+ self.save()
+ os.symlink(new_dir, new_symlink)
+ logging.debug('Persistence: atomically making "%s" point to the new '
+ 'configuration directory "%s' %
+ (CONF_PERSIST_NETCONF_DIR, new_dir))
+ os.rename(new_symlink, os.path.dirname(CONF_PERSIST_NETCONF_DIR))
+
+
+def _nano_timestamp():
+ return ('%.20f' % time.time()).replace('.', '')[:19]
+
+
+def _cleanupPersistence(keep=()):
+ """Cleans up CONF_PERSIST_DIR from netconfs not in 'keep'"""
+ for path in glob.iglob(os.path.dirname(CONF_PERSIST_NETCONF_DIR) + '.*'):
+ if path in keep:
+ continue
+ logging.debug('Persistence: removing old config "%s"' % path)
+ if os.path.islink(path) or os.path.isfile(path):
+ utils.rmFile(path)
+ else: # Directory
+ utils.rmTree(path)
+
def configuredPorts(nets, bridge):
"""Return the configured ports for the bridge"""
--
To view, visit http://gerrit.ovirt.org/35709
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ida957b6c68607743b9efa85f4263451c955b398a
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Antoni Segura Puimedon <asegurap(a)redhat.com>
8 years, 10 months
Change in vdsm[master]: vdsm-store-net-config: make use of oVirt node bindings
by asegurap@redhat.com
Antoni Segura Puimedon has uploaded a new change for review.
Change subject: vdsm-store-net-config: make use of oVirt node bindings
......................................................................
vdsm-store-net-config: make use of oVirt node bindings
Up until now, vdsm-store-net-config was a bash script that relied on
oVirt node's bash bindings for their python scripts. This patch
avoids the extra step to have a more fine grained access to the
new style ovirt.node.utils.fs package.
This patch depends on the oVirt node patches that make oVirt node
support symlink persistence.
Change-Id: Iee19cb9f6e1ba007631e7e6d315726d6efa03d09
Signed-off-by: Antoni S. Puimedon <asegurap(a)redhat.com>
---
M .gitignore
M vdsm/Makefile.am
A vdsm/vdsm-store-net-config
D vdsm/vdsm-store-net-config.in
4 files changed, 170 insertions(+), 85 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/55/29355/1
diff --git a/.gitignore b/.gitignore
index 5e8b53f..24ddb94 100644
--- a/.gitignore
+++ b/.gitignore
@@ -65,7 +65,6 @@
vdsm/vdsm-gencerts.sh
vdsm/vdsm-logrotate.conf
vdsm/vdsm-sosplugin.py
-vdsm/vdsm-store-net-config
vdsm/vdsm.rwtab
vdsm/vdsmd.8
vdsm/gluster/hostname.py
diff --git a/vdsm/Makefile.am b/vdsm/Makefile.am
index 763ef2a..66b7a69 100644
--- a/vdsm/Makefile.am
+++ b/vdsm/Makefile.am
@@ -60,7 +60,6 @@
nodist_vdsm_SCRIPTS = \
mk_sysprep_floppy \
- vdsm-store-net-config
nodist_noinst_DATA = \
logger.conf \
@@ -80,6 +79,7 @@
supervdsmServer \
vdsm \
vdsm-restore-net-config \
+ vdsm-store-net-config \
$(NULL)
nodist_man8_MANS = \
@@ -118,7 +118,6 @@
vdsm-logrotate \
vdsm-logrotate.conf.in \
vdsm-modules-load.d.conf \
- vdsm-store-net-config.in \
vdsm-sysctl.conf \
vdsm.rwtab.in \
vdsmd.8.in \
diff --git a/vdsm/vdsm-store-net-config b/vdsm/vdsm-store-net-config
new file mode 100644
index 0000000..a54da13
--- /dev/null
+++ b/vdsm/vdsm-store-net-config
@@ -0,0 +1,169 @@
+#!/usr/bin/env python2
+#
+# Copyright 2009-2014 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Refer to the README and COPYING files for full details of the license
+"""
+Stores all the vdsm configured networks persistently
+"""
+import glob
+import logging
+import logging.config
+import os
+import time
+import shutil
+
+from vdsm import config, constants, utils
+
+# ifcfg persistence directories
+NET_CONF_DIR = '/etc/sysconfig/network-scripts/'
+NET_CONF_BACK_DIR = constants.P_VDSM_LIB + '/netconfback'
+
+# Unified persistence directories
+RUN_CONF_DIR = constants.P_VDSM_RUN + '/netconf'
+PERSISTENT_SYMLINK_PATH = constants.P_VDSM_LIB + 'persistence/netconf'
+
+
+def _ifcfg_non_node_persist():
+ """Removes the backed up configuration files, thus implicitly marking those
+ under /etc/sysconfig/network-scripts as safe"""
+ logging.debug('Persistence: Marking /etc/sysconfig/network-scripts as safe'
+ )
+ _rm_dir_contents(NET_CONF_BACK_DIR)
+
+
+def _ifcfg_node_persist():
+ """Removes the backed up configuration files and leverages oVirt node's
+ facilities to make /etc/sysconfig/netwrok-scripts persistent"""
+ node_conf = fs.Config()
+ for path in os.listdir(NET_CONF_BACK_DIR):
+ filename = os.path.basename(path)
+ sysconf_ifcfg_path = NET_CONF_DIR + filename
+ if os.path.exists(sysconf_ifcfg_path):
+ # If we currently have a running configuration for the file, we
+ # should make sure that it is persisted by the node
+ logging.debug('Persistence: oVirt node persisting "%s"' %
+ sysconf_ifcfg_path)
+ node_conf.persist(sysconf_ifcfg_path)
+ else:
+ # If there is no current file, we should make sure that there is
+ # no persistent version either
+ logging.debug('Persistence: oVirt node deleting "%s"' %
+ sysconf_ifcfg_path)
+ node_conf.delete(sysconf_ifcfg_path)
+ # remove the backup in case there's restore nets before reboot (on
+ # reboot the file would be gone anyway)
+ utils.rmFile(path)
+
+
+def _unified_non_node_persist():
+ """Atomically set RUN_CONF_DIR configuration as the new persistent vdsm
+ network configuration"""
+ timestamp = _nano_timestamp()
+ new_dir = PERSISTENT_SYMLINK_PATH + '.' + timestamp
+ new_symlink = PERSISTENT_SYMLINK_PATH + '.link.' + timestamp
+
+ logging.debug('Persistence: persisting "%s"' % new_dir)
+ shutil.copytree(RUN_CONF_DIR, new_dir, symlinks=True)
+ os.symlink(new_dir, new_symlink)
+ logging.debug('Persistence: atomically making "%s" point to the new '
+ 'configuration directory "%s' % (PERSISTENT_SYMLINK_PATH,
+ new_dir))
+ os.rename(new_symlink, PERSISTENT_SYMLINK_PATH)
+
+ for path in glob.iglob(PERSISTENT_SYMLINK_PATH + '.*'):
+ if path == new_dir:
+ continue
+ logging.debug('Persistence: removing old config "%s"' % path)
+ if os.path.islink(path) or os.path.isfile(path):
+ utils.rmFile(path)
+ else: # Directory
+ utils.rmTree(path)
+
+
+def _unified_node_persist():
+ node_conf = fs.Config()
+ timestamp = _nano_timestamp()
+ new_dir = PERSISTENT_SYMLINK_PATH + '.' + timestamp
+ new_symlink = PERSISTENT_SYMLINK_PATH + '.link.' + timestamp
+
+ shutil.copytree(RUN_CONF_DIR, new_dir, symlinks=True)
+ logging.debug('Persistence: oVirt node persisting "%s"' % new_dir)
+ node_conf.persist(new_dir)
+
+ os.symlink(new_dir, new_symlink)
+ logging.debug('Persistence: atomically making "%s" point to the new '
+ 'configuration directory "%s' % (PERSISTENT_SYMLINK_PATH,
+ new_dir))
+ os.rename(new_symlink, PERSISTENT_SYMLINK_PATH)
+
+ logging.debug('Persistence: oVirt node persisting symlink "%s", which now '
+ 'points to the new configuration directory "%s' %
+ (PERSISTENT_SYMLINK_PATH, new_dir))
+ node_conf.persist(PERSISTENT_SYMLINK_PATH)
+
+ # Now that the oVirt node has properly persisted the new directory and
+ # the new version of the symlinks, let's cleanup the old network
+ # configurations
+ for path in glob.iglob(PERSISTENT_SYMLINK_PATH + '.*'):
+ if path == new_dir:
+ continue
+ logging.debug('Persistence: oVirt node shredding old config "%s"' %
+ path)
+ node_conf.delete(path)
+
+
+def _nano_timestamp():
+ return ('%.20f' % time.time()).replace('.', '')[:19]
+
+
+def _rm_dir_contents(dirpath):
+ """Empties a directory"""
+ for path in os.listdir(dirpath):
+ if os.path.islink(path) or os.path.isfile(path):
+ utils.rmFile(path)
+ else: # Directory
+ utils.rmTree(path)
+
+
+_unified = config.config.get('vars', 'net_persistence') == 'unified'
+if utils.isOvirtNode():
+ from ovirt.node.utils import fs
+ if _unified:
+ persist = _unified_node_persist
+ else:
+ persist = _ifcfg_node_persist
+else:
+ if _unified:
+ persist = _unified_non_node_persist
+ else:
+ persist = _ifcfg_non_node_persist
+
+if __name__ == '__main__':
+ try:
+ logging.config.fileConfig('/etc/vdsm/svdsm.logger.conf',
+ disable_existing_loggers=False)
+ except:
+ logging.basicConfig(filename='/dev/stdout', filemode='w+',
+ level=logging.DEBUG)
+ logging.error('Could not init proper logging', exc_info=True)
+
+ try:
+ persist()
+ except Exception:
+ logging.error('Failed to store vdsm network configuration.',
+ sys_exc=True)
diff --git a/vdsm/vdsm-store-net-config.in b/vdsm/vdsm-store-net-config.in
deleted file mode 100755
index 94e658b..0000000
--- a/vdsm/vdsm-store-net-config.in
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/bin/bash
-#
-# vdsm-store-net-config: store network configuration files persistently
-#
-
-. @LIBEXECDIR(a)/ovirt_functions.sh
-
-# ifcfg persistence directories
-NET_CONF_DIR='/etc/sysconfig/network-scripts/'
-NET_CONF_BACK_DIR='@VDSMLIBDIR@/netconfback'
-
-# Unified persistence directories
-RUN_CONF_DIR='@VDSMRUNDIR@/netconf'
-PERS_CONF_PATH='@VDSMLIBDIR@/persistence'
-PERS_NET_CONF_PATH="$PERS_CONF_PATH/netconf"
-
-PERSISTENCE=$1
-
-ifcfg_node_persist() {
- for f in "$NET_CONF_BACK_DIR"/*;
- do
- [ ! -f "$f" ] && continue
- bf=`basename "$f"`
- if [ -f "$NET_CONF_DIR/$bf" ];
- then
- ovirt_store_config "$NET_CONF_DIR/$bf"
- else
- ovirt_safe_delete_config "$NET_CONF_DIR/$bf"
- fi
- rm "$NET_CONF_BACK_DIR/$bf"
- done
-}
-
-ifcfg_nonnode_persist() {
- # Remove the backed up configuration files thus marking the ones under
- # /etc/sysconfig as "safe".
- rm -rf "$NET_CONF_BACK_DIR"/*
-}
-
-unified_node_persist() {
- unified_nonnode_persist
-
- # oVirt node ovirt_store_config puts the dir in persistent storage and
- # bind mounts it in the original place. So that's all we really need to do.
- ovirt_store_config "$PERS_CONF_PATH"
-}
-
-unified_nonnode_persist() {
- # Atomic directory copy by using the atomicity of overwriting a link
- # (rename syscall).
- TIMESTAMP=$(date +%s%N)
- PERS_CONF_SYMLINK=$PERS_NET_CONF_PATH
- PERS_CONF_DIR_ROOTNAME="$PERS_CONF_SYMLINK."
- PERS_CONF_NEW_DIR="$PERS_CONF_DIR_ROOTNAME$TIMESTAMP"
- PERS_CONF_NEW_SYMLINK="$PERS_CONF_SYMLINK.link.$TIMESTAMP"
-
- cp -r "$RUN_CONF_DIR" "$PERS_CONF_NEW_DIR"
- ln -s "$PERS_CONF_NEW_DIR" "$PERS_CONF_NEW_SYMLINK"
- mv -fT "$PERS_CONF_NEW_SYMLINK" "$PERS_CONF_SYMLINK"
- find "$PERS_CONF_PATH" -type d -path "$PERS_CONF_DIR_ROOTNAME*" | \
- grep -v "$PERS_CONF_NEW_DIR" | xargs rm -fr
-}
-
-
-if isOvirtNode
-then
- # for node, persist the changed configuration files
-
- . /usr/libexec/ovirt-functions
-
- if [ "$PERSISTENCE" == "unified" ]; then
- unified_node_persist
- else
- ifcfg_node_persist
- fi
-else
- if [ "$PERSISTENCE" == "unified" ]; then
- unified_nonnode_persist
- else
- ifcfg_nonnode_persist
- fi
-fi
--
To view, visit http://gerrit.ovirt.org/29355
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Iee19cb9f6e1ba007631e7e6d315726d6efa03d09
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Antoni Segura Puimedon <asegurap(a)redhat.com>
8 years, 10 months
Change in vdsm[master]: virt: graphdev: support headless VM
by fromani@redhat.com
Francesco Romani has uploaded a new change for review.
Change subject: virt: graphdev: support headless VM
......................................................................
virt: graphdev: support headless VM
This patch add support for headless VMs, aka VMs without
a graphic device.
Noteworthy side effects of this patch:
* It is now possible to create a VM without any display
(aka headless VM), and they are supported.
* The input 'display' parameter of the Vm.create API is
no longer mandatory
* In the API schema, the display* parameters are now
marked as optional, even though Engine is expected to still
send them in the near/medium term.
* setTicket and the internally used _reviveTicket can now
fail if they are invoked against a VM without graphic devices.
Change-Id: Iafeb0bebfb43c089614127d94c054175c111ce54
Signed-off-by: Francesco Romani <fromani(a)redhat.com>
---
M tests/functional/virtTests.py
M tests/vmTests.py
M vdsm/API.py
M vdsm/virt/vm.py
M vdsm_api/vdsmapi-schema.json
5 files changed, 117 insertions(+), 72 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/46/27846/1
diff --git a/tests/functional/virtTests.py b/tests/functional/virtTests.py
index a074e62..9a25850 100644
--- a/tests/functional/virtTests.py
+++ b/tests/functional/virtTests.py
@@ -225,6 +225,14 @@
self._waitForStartup(vm, VM_MINIMAL_UPTIME)
@requireKVM
+ def testHeadlessVm(self):
+ customization = {'vmId': '77777777-ffff-3333-bbbb-222222222222',
+ 'vmName': 'testHeadlessVm'}
+
+ with RunningVm(self.vdsm, customization) as vm:
+ self._waitForStartup(vm, VM_MINIMAL_UPTIME)
+
+ @requireKVM
@permutations([['localfs'], ['iscsi'], ['nfs']])
def testVmWithStorage(self, backendType):
disk = storage.StorageTest()
diff --git a/tests/vmTests.py b/tests/vmTests.py
index 69d5643..4022dfb 100644
--- a/tests/vmTests.py
+++ b/tests/vmTests.py
@@ -1077,6 +1077,11 @@
devs = fake.buildConfDevices()
self.assertTrue(devs['graphics'])
+ def testGraphicDeviceHeadless(self):
+ with FakeVM(self.conf) as fake:
+ devs = fake.buildConfDevices()
+ self.assertFalse(devs['graphics'])
+
def testGraphicsDeviceMixed(self):
"""
if proper Graphics Devices are supplied, display* params must be
diff --git a/vdsm/API.py b/vdsm/API.py
index 14e7bae..4747be1 100644
--- a/vdsm/API.py
+++ b/vdsm/API.py
@@ -200,7 +200,7 @@
self.log.error("Error restoring VM parameters",
exc_info=True)
- requiredParams = ['vmId', 'memSize', 'display']
+ requiredParams = ['vmId', 'memSize']
for param in requiredParams:
if param not in vmParams:
self.log.error('Missing required parameter %s' % (param))
@@ -252,11 +252,6 @@
'No space on /tmp?'}}
return errCode['createErr']
- if not vm.GraphicsDevice.isSupportedDisplayType(vmParams):
- return {'status': {'code': errCode['createErr']
- ['status']['code'],
- 'message': 'Unknown display type %s' %
- vmParams.get('display')}}
if 'nicModel' not in vmParams:
vmParams['nicModel'] = config.get('vars', 'nic_model')
return self._cif.createVm(vmParams)
diff --git a/vdsm/virt/vm.py b/vdsm/virt/vm.py
index a547a5e..5d08cea 100644
--- a/vdsm/virt/vm.py
+++ b/vdsm/virt/vm.py
@@ -1344,10 +1344,6 @@
'main', 'display', 'inputs', 'cursor', 'playback',
'record', 'smartcard', 'usbredir')
- @staticmethod
- def isSupportedDisplayType(vmParams):
- return vmParams.get('display') in ('vnc', 'qxl', 'qxlnc')
-
def __init__(self, conf, log, **kwargs):
super(GraphicsDevice, self).__init__(conf, log, **kwargs)
self.port = self.LIBVIRT_PORT_AUTOSELECT
@@ -1840,8 +1836,8 @@
if len(devices[device]) > 1:
raise ValueError("only a single %s device is "
"supported" % device)
- if len(devices[GRAPHICS_DEVICES]) != 1:
- raise ValueError("one graphics device is required")
+ if len(devices[GRAPHICS_DEVICES]) > 1:
+ raise ValueError("only one graphics device is supported")
def getConfController(self):
"""
@@ -1866,12 +1862,16 @@
devType = DEFAULT_VIDEOS[self.arch]
elif self.hasSpice:
devType = 'qxl'
+ else:
+ devType = None
- monitors = int(self.conf.get('spiceMonitors', '1'))
- vram = '65536' if (monitors <= 2) else '32768'
- for idx in range(monitors):
- vcards.append({'type': VIDEO_DEVICES, 'specParams': {'vram': vram},
- 'device': devType})
+ if devType:
+ monitors = int(self.conf.get('spiceMonitors', '1'))
+ vram = '65536' if (monitors <= 2) else '32768'
+ for idx in range(monitors):
+ vcards.append({'type': VIDEO_DEVICES,
+ 'specParams': {'vram': vram},
+ 'device': devType})
return vcards
@@ -1885,13 +1885,18 @@
for oldName, newName in GraphicsDevice.LEGACY_MAP.iteritems()
if oldName in conf)
- return [{
- 'type': GRAPHICS_DEVICES,
- 'device': (
- 'spice'
- if self.conf['display'] in ('qxl', 'qxlnc')
- else 'vnc'),
- 'specParams': makeSpecParams(self.conf)}]
+ graphDevs = []
+
+ if 'display' in self.conf:
+ graphDevs.append({
+ 'type': GRAPHICS_DEVICES,
+ 'device': (
+ 'spice'
+ if self.conf['display'] in ('qxl', 'qxlnc')
+ else 'vnc'),
+ 'specParams': makeSpecParams(self.conf)})
+
+ return graphDevs
def getConfSound(self):
"""
@@ -2520,10 +2525,6 @@
return self._getExitedVmStats()
stats = {
- 'displayPort': self.conf['displayPort'],
- 'displaySecurePort': self.conf['displaySecurePort'],
- 'displayType': self.conf['display'],
- 'displayIp': self.conf['displayIp'],
'pid': self.conf['pid'],
'vmType': self.conf['vmType'],
'kvmEnable': self._kvmEnable,
@@ -2534,6 +2535,8 @@
stats['cdrom'] = self.conf['cdrom']
if 'boot' in self.conf:
stats['boot'] = self.conf['boot']
+
+ stats.update(self._getGraphicsStats())
decStats = {}
try:
@@ -2602,6 +2605,16 @@
'exitReason': self.conf['exitReason']}
if 'timeOffset' in self.conf:
stats['timeOffset'] = self.conf['timeOffset']
+ return stats
+
+ def _getGraphicsStats(self):
+ stats = {}
+ if 'display' in self.conf:
+ stats['displayType'] = self.conf['display']
+ stats['displayPort'] = self.conf['displayPort']
+ stats['displaySecurePort'] = self.conf['displaySecurePort']
+ stats['displayIp'] = self.conf['displayIp']
+ # else headless VM
return stats
def isMigrating(self):
@@ -4266,8 +4279,13 @@
return {'status': doneCode, 'vmList': self.status()}
def setTicket(self, otp, seconds, connAct, params):
- graphics = _domParseStr(self._dom.XMLDesc(0)).childNodes[0]. \
- getElementsByTagName('graphics')[0]
+ try:
+ graphics = _domParseStr(self._dom.XMLDesc(0)).childNodes[0]. \
+ getElementsByTagName('graphics')[0]
+ except IndexError:
+ return {
+ 'status': {'code': errCode['ticketErr']['status']['code'],
+ 'message': 'no graphics devices configured'}}
graphics.setAttribute('passwd', otp)
if int(seconds) > 0:
validto = time.strftime('%Y-%m-%dT%H:%M:%S',
@@ -4288,9 +4306,13 @@
def _reviveTicket(self, newlife):
"""Revive an existing ticket, if it has expired or about to expire"""
- graphics = _domParseStr(
- self._dom.XMLDesc(libvirt.VIR_DOMAIN_XML_SECURE)). \
- childNodes[0].getElementsByTagName('graphics')[0]
+ try:
+ graphics = _domParseStr(
+ self._dom.XMLDesc(libvirt.VIR_DOMAIN_XML_SECURE)). \
+ childNodes[0].getElementsByTagName('graphics')[0]
+ except IndexError:
+ self.log.error('no graphics devices configured')
+ return
validto = max(time.strptime(graphics.getAttribute('passwdValidTo'),
'%Y-%m-%dT%H:%M:%S'),
time.gmtime(time.time() + newlife))
@@ -4855,19 +4877,20 @@
device of each type (sdl, vnc, spice) is supported
"""
graphicsXml = _domParseStr(self._lastXMLDesc).childNodes[0]. \
- getElementsByTagName('devices')[0].getElementsByTagName('graphics')[0]
+ getElementsByTagName('devices')[0].getElementsByTagName('graphics')
- graphicsType = graphicsXml.getAttribute('type')
- for dev in self.conf['devices']:
- if dev.get('device') == graphicsType:
- port = graphicsXml.getAttribute('port')
- if port:
- dev['port'] = port
- tlsPort = graphicsXml.getAttribute('tlsPort')
- if tlsPort:
- dev['tlsPort'] = tlsPort
- self._updateLegacyConf(dev)
- break
+ for gxml in graphicsXml:
+ graphicsType = gxml.getAttribute('type')
+
+ for dev in self.conf['devices']:
+ if dev.get('device') == graphicsType:
+ port = gxml.getAttribute('port')
+ if port:
+ dev['port'] = port
+ tlsPort = gxml.getAttribute('tlsPort')
+ if tlsPort:
+ dev['tlsPort'] = tlsPort
+ self._updateLegacyConf(dev)
def _getUnderlyingNetworkInterfaceInfo(self):
"""
@@ -5051,11 +5074,12 @@
return True
def _initLegacyConf(self):
- self.conf['displayPort'] = GraphicsDevice.LIBVIRT_PORT_AUTOSELECT
- self.conf['displaySecurePort'] = \
- GraphicsDevice.LIBVIRT_PORT_AUTOSELECT
- self.conf['displayIp'] = _getNetworkIp(
- self.conf.get('displayNetwork'))
+ if 'display' in self.conf:
+ self.conf['displayPort'] = GraphicsDevice.LIBVIRT_PORT_AUTOSELECT
+ self.conf['displaySecurePort'] = \
+ GraphicsDevice.LIBVIRT_PORT_AUTOSELECT
+ self.conf['displayIp'] = _getNetworkIp(
+ self.conf.get('displayNetwork'))
def _updateLegacyConf(self, dev):
self.conf['display'] = 'qxl' if dev['device'] == 'spice' else 'vnc'
diff --git a/vdsm_api/vdsmapi-schema.json b/vdsm_api/vdsmapi-schema.json
index a9332ee..64d4179 100644
--- a/vdsm_api/vdsmapi-schema.json
+++ b/vdsm_api/vdsmapi-schema.json
@@ -3175,13 +3175,17 @@
#
# @devices: #optional An array of VM devices present
#
-# @display: The type of display
+# @display: #optional The type of display
+# (made optional in version 4.15.0)
#
-# @displayIp: The IP address to use for accessing the VM display
+# @displayIp: #optional The IP address to use for accessing the VM display
+# (made optional in version 4.15.0)
#
-# @displayPort: The port in use for unencrypted display data
+# @displayPort: #optional The port in use for unencrypted display data
+# (made optional in version 4.15.0)
#
-# @displaySecurePort: The port in use for encrypted display data
+# @displaySecurePort: #optional The port in use for encrypted display data
+# (made optional in version 4.15.0)
#
# @emulatedMachine: #optional The machine specification being emulated
#
@@ -3235,8 +3239,8 @@
{'type': 'VmDefinition',
'data': {'acpiEnable': 'bool', 'clientIp': 'str', 'cpuShares': 'str',
'*cpuType': 'str', '*custom': 'StringMap', '*devices': ['VmDevice'],
- 'display': 'VmDisplayType', 'displayIp': 'str',
- 'displayPort': 'int', 'displaySecurePort': 'int',
+ '*display': 'VmDisplayType', '*displayIp': 'str',
+ '*displayPort': 'int', '*displaySecurePort': 'int',
'*emulatedMachine': 'str', '*keyboardLayout': 'str',
'kvmEnable': 'bool', '*maxVCpus': 'uint', 'memSize': 'uint',
'memGuaranteedSize': 'uint', 'nicModel': 'str', 'nice': 'int',
@@ -3264,7 +3268,8 @@
#
# @devices: #optional An array of VM devices requested
#
-# @display: The type of display
+# @display: #optional The type of display
+# (made optional in version 4.15.0)
#
# @kvmEnable: Indicates if KVM hardware acceleration is enabled
#
@@ -3300,7 +3305,7 @@
{'type': 'VmParameters',
'data': {'acpiEnable': 'bool', '*bootMenuEnable': 'bool',
'*cpuShares': 'str', '*custom': 'StringMap', '*devices': ['VmDevice'],
- 'display': 'VmDisplayType', 'kvmEnable': 'bool', 'memSize': 'uint',
+ '*display': 'VmDisplayType', 'kvmEnable': 'bool', 'memSize': 'uint',
'nice': 'int', 'smp': 'uint', '*smpCoresPerSocket': 'uint',
'*smpThreadsPerCore': 'uint', 'timeOffset': 'uint',
'transparentHugePages': 'bool', 'vmId': 'UUID', 'vmName': 'str',
@@ -3347,7 +3352,8 @@
#
# @devices: An array of VM devices requested
#
-# @display: The type of display
+# @display: #optional The type of display
+# (made optional in version 4.15.0)
#
# @kvmEnable: Indicates if KVM hardware acceleration is enabled
#
@@ -3372,7 +3378,8 @@
#
# @memGuaranteedSize: The amount of memory guaranteed to the VM in MB
#
-# @displaySecurePort: The port in use for encrypted display data
+# @displaySecurePort: #optional The port in use for encrypted display data
+# (made optional in version 4.15.0)
#
# @spiceSecureChannels: Secure space channels comma separated
#
@@ -3394,11 +3401,13 @@
# @guestFQDN: Fully qualified domain name of the guest OS. (Reported
# by the guest agent)
#
-# @displayIp: The IP address to use for accessing the VM display
+# @displayIp: #optional The IP address to use for accessing the VM display
+# (made optional in version 4.15.0)
#
# @keyboardLayout: The keyboard layout string (eg. 'en-us')
#
-# @displayPort: The port in use for unencrypted display data
+# @displayPort: #optional The port in use for unencrypted display data
+# (made optional in version 4.15.0)
#
# @guestIPs: A space separated string of assigned IPv4 addresses
#
@@ -3416,15 +3425,15 @@
##
{'type': 'VMFullInfo',
'data': {'acpiEnable': 'bool', 'custom': 'StringMap', 'devices': ['VmDevice'],
- 'display': 'VmDisplayType', 'kvmEnable': 'bool', 'memSize': 'uint',
+ '*display': 'VmDisplayType', 'kvmEnable': 'bool', 'memSize': 'uint',
'nice': 'int', 'smp': 'uint', 'smpCoresPerSocket': 'uint',
'timeOffset': 'uint', 'transparentHugePages': 'bool', 'vmId': 'UUID',
'vmName': 'str', 'vmType': 'VmType', 'memGuaranteedSize': 'uint',
- 'displaySecurePort': 'uint', 'spiceSecureChannels': 'str',
+ '*displaySecurePort': 'uint', 'spiceSecureChannels': 'str',
'username': 'str', 'emulatedMachine': 'str', 'pid': 'uint',
'spiceSslCipherSuite': 'str', 'cpuType': 'str', 'pauseCode': 'str',
- 'guestFQDN': 'str', 'displayIp': 'str', 'keyboardLayout': 'str',
- 'displayPort': 'uint', 'guestIPs': 'str', 'smartcardEnable': 'bool',
+ 'guestFQDN': 'str', '*displayIp': 'str', 'keyboardLayout': 'str',
+ '*displayPort': 'uint', 'guestIPs': 'str', 'smartcardEnable': 'bool',
'nicModel': 'VmInterfaceDeviceModel', 'pitReinjection': 'bool',
'status': 'str', 'clientIp': 'str'}}
@@ -6016,13 +6025,17 @@
#
# Statistics for a running virtual machine.
#
-# @displayPort: The port in use for unencrypted display data
+# @displayPort: #optional The port in use for unencrypted display data
+# (made optional in version 4.15.0)
#
-# @displaySecurePort: The port in use for encrypted display data
+# @displaySecurePort: #optional The port in use for encrypted display data
+# (made optional in version 4.15.0)
#
-# @displayType: The type of display in use
+# @displayType: #optional The type of display in use
+# (made optional in version 4.15.0)
#
-# @displayIp: The IP address to use for accessing the VM display
+# @displayIp: #optional The IP address to use for accessing the VM display
+# (made optional in version 4.15.0)
#
# @pid: The process ID of the underlying qemu process
#
@@ -6089,8 +6102,8 @@
# Since: 4.10.0
##
{'type': 'RunningVmStats',
- 'data': {'displayPort': 'uint', 'displaySecurePort': 'uint',
- 'displayType': 'VmDisplayType', 'displayIp': 'str', 'pid': 'uint',
+ 'data': {'*displayPort': 'uint', '*displaySecurePort': 'uint',
+ '*displayType': 'VmDisplayType', '*displayIp': 'str', 'pid': 'uint',
'vmType': 'VmType', 'kvmEnable': 'bool',
'network': 'NetworkInterfaceStatsMap',
'disks': 'VmDiskStatsMap', 'monitorResponse': 'int',
--
To view, visit http://gerrit.ovirt.org/27846
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Iafeb0bebfb43c089614127d94c054175c111ce54
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Francesco Romani <fromani(a)redhat.com>
8 years, 10 months
Change in vdsm[master]: vm: run before_vm_create hook only in the VM boot
by fromani@redhat.com
Francesco Romani has uploaded a new change for review.
Change subject: vm: run before_vm_create hook only in the VM boot
......................................................................
vm: run before_vm_create hook only in the VM boot
The 'before_vm_create' hook is running in two flows:
* as expected, in the VM creation flow.
* as may not be expected, in the VM dehybernation flow.
The latter is surprising and, most important,
contractdicting because in the dehibernation flow
* the domain XML returned by the before_vm_create
is never used
* just after the before_vm_create hook, we run
the before_vm_dehibernate hook with the stored
domain XML.
At risk to breaking some probably already incorrect
hook, this patch makes the before_vm_create hook
run only in the VM creation path.
Change-Id: I2ad05e39029acc7b898c7b2af2141bba1d7d3c8e
Signed-off-by: Francesco Romani <fromani(a)redhat.com>
---
M vdsm/virt/vm.py
1 file changed, 3 insertions(+), 4 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/30/34530/1
diff --git a/vdsm/virt/vm.py b/vdsm/virt/vm.py
index 6e46119..751947e 100644
--- a/vdsm/virt/vm.py
+++ b/vdsm/virt/vm.py
@@ -2667,10 +2667,6 @@
# we need to complete the initialization, including
# domDependentInit, after the migration is completed.
- if not self.recovering and initDomain:
- domxml = hooks.before_vm_start(self._buildDomainXML(), self.conf)
- self.log.debug(domxml)
-
if self.recovering:
self._dom = NotifyingVirDomain(
self._connection.lookupByUUIDString(self.id),
@@ -2698,6 +2694,9 @@
self._connection.lookupByUUIDString(self.id),
self._timeoutExperienced)
else:
+ domxml = hooks.before_vm_start(self._buildDomainXML(), self.conf)
+ self.log.debug(domxml)
+
flags = libvirt.VIR_DOMAIN_NONE
if 'launchPaused' in self.conf:
flags |= libvirt.VIR_DOMAIN_START_PAUSED
--
To view, visit http://gerrit.ovirt.org/34530
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I2ad05e39029acc7b898c7b2af2141bba1d7d3c8e
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Francesco Romani <fromani(a)redhat.com>
8 years, 10 months