Dan Kenigsberg has uploaded a new change for review.
Change subject: virt: let Engine start a VM on an UNKOWN OS
......................................................................
virt: let Engine start a VM on an UNKOWN OS
This superflouse validation was introduced as a "bandage" to avoid
https://bugzilla.redhat.com/716705, where Vdsm failed to recognize
VMs with "UNKOWN" os injected to their bios.
Now that we recognize VMs based on guest channels existence, we can let
Engine start a VM on whatever host it deems valid.
Backward compatibility caveat: if a VM is started on an UNKOWN os, and
then migrated to an old Vdsm (pre ovirt-3.4.2), it would be killed when
that old Vdsm is to be restarted. It's not probable that someone would
start a long-running VM on an UNKOWN platform, we may want to wait with
this patch until ovirt-3.3 is deprecated.
Change-Id: Iee7b3913e76923043daab8fb85854c3290208237
Signed-off-by: Dan Kenigsberg <danken(a)redhat.com>
---
M vdsm/API.py
1 file changed, 0 insertions(+), 5 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/59/32459/1
diff --git a/vdsm/API.py b/vdsm/API.py
index 8d1bca6..d6f318f 100644
--- a/vdsm/API.py
+++ b/vdsm/API.py
@@ -237,11 +237,6 @@
vmParams['vmId'])
vmParams['volatileFloppy'] = True
- if caps.osversion()['name'] == caps.OSName.UNKNOWN:
- return {'status': {'code': errCode['createErr']
- ['status']['code'],
- 'message': 'Unknown host operating system'}}
-
if 'sysprepInf' in vmParams:
if not self._createSysprepFloppyFromInf(vmParams['sysprepInf'],
vmParams['floppy']):
--
To view, visit http://gerrit.ovirt.org/32459
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Iee7b3913e76923043daab8fb85854c3290208237
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Dan Kenigsberg <danken(a)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>
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>
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@/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>
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>
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>