Change in vdsm[master]: Add shutdown based on qemu-ga(qemu guest agent) in vdsm
by shaohef@linux.vnet.ibm.com
Hello Bing Bu Cao,
I'd like you to do a code review. Please visit
http://gerrit.ovirt.org/9655
to review the following change.
Change subject: Add shutdown based on qemu-ga(qemu guest agent) in vdsm
......................................................................
Add shutdown based on qemu-ga(qemu guest agent) in vdsm
As previously what we agreed, the agent-assisted shutdown and fsfreeze
would be handled by the qemu guest agent while oVirt-specific functionality
such as Single-Sign-On would continue to be managed by the ovirt guest agent.
http://www.ovirt.org/wiki/Guest_agent_proposals
This patch changes the shutdown verb, add an shutdown approach by qemu guest
agent
Change-Id: I86977c1b717d63de21ba4818c6b66e43976d65de
Signed-off-by: ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
Signed-off-by: BingBu Cao <mars(a)linux.vnet.ibm.com>
---
M vdsm/libvirtvm.py
M vdsm/vm.py
2 files changed, 84 insertions(+), 28 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/55/9655/1
diff --git a/vdsm/libvirtvm.py b/vdsm/libvirtvm.py
index f20968f..f1d82d7 100644
--- a/vdsm/libvirtvm.py
+++ b/vdsm/libvirtvm.py
@@ -1222,6 +1222,8 @@
self._releaseLock = threading.Lock()
self.saveState()
+ self.shutdownMethodUpdate()
+
def _buildLease(self, domainID, volumeID, leasePath, leaseOffset):
"""
Add a single SANLock lease.
@@ -2326,9 +2328,45 @@
physical, alloc)
self.extendDriveVolume(d)
+ def shutdownMethodUpdate(self):
+ self._shutdownMethods = []
+ self._shutdownMethods.append({'qemugaShutdown':
+ self.qemugaShutdown})
+ self._shutdownMethods.append({'guestAgentShutdown':
+ self.guestAgentShutdown})
+ self._shutdownMethods.append({'acpiShutdown':
+ self.acpiShutdown})
+
def _acpiShutdown(self):
self._dom.shutdownFlags(libvirt.VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN)
+ def acpiShutdown(self, now, *args):
+ if utils.tobool(self.conf.get('acpiEnable', 'true')):
+ self.log.debug("acpiShutdown vm")
+ self._guestEventTime = now
+ self._guestEvent = 'Powering down'
+ self._acpiShutdown()
+ else:
+ return None
+
+ return {'status': {'code': doneCode['code'],
+ 'message': 'Machine shut down'}}
+
+ def _qemugaShutdown(self):
+ self._dom.shutdownFlags(libvirt.VIR_DOMAIN_SHUTDOWN_GUEST_AGENT)
+
+ def qemugaShutdown(self, now, *args):
+ if utils.tobool(self.conf.get('qgaEnable', 'true')):
+ self.log.debug("qemugaShutdown vm")
+ self._guestEventTime = now
+ self._guestEvent = 'Powering down'
+ self._qemugaShutdown()
+ else:
+ return None
+
+ return {'status': {'code': doneCode['code'],
+ 'message': 'Machine shut down'}}
+
def _getPid(self):
pid = '0'
try:
diff --git a/vdsm/vm.py b/vdsm/vm.py
index cb0e552..bf6ee8b 100644
--- a/vdsm/vm.py
+++ b/vdsm/vm.py
@@ -364,6 +364,8 @@
CONTROLLER_DEVICES: [], GENERAL_DEVICES: [],
BALLOON_DEVICES: [], REDIR_DEVICES: [],
WATCHDOG_DEVICES: []}
+ self._shutdownMethods = []
+ self.shutdownMethodUpdate()
def _get_lastStatus(self):
PAUSED_STATES = ('Powering down', 'RebootInProgress', 'Up')
@@ -970,35 +972,51 @@
if not guestCpuLocked:
self._guestCpuLock.release()
+ def shutdownMethodUpdate(self):
+ self._shutdownMethods = []
+ self._shutdownMethods.append({'guestAgentShutdown':
+ self._guestAgentShutdown})
+
def shutdown(self, timeout, message):
- try:
- now = time.time()
- if self.lastStatus == 'Down':
- return
- if self.guestAgent and self.guestAgent.isResponsive():
- self._guestEventTime = now
- self._guestEvent = 'Powering down'
- self.log.debug('guestAgent shutdown called')
- self.guestAgent.desktopShutdown(timeout, message)
- agent_timeout = (int(timeout) +
- config.getint('vars', 'sys_shutdown_timeout'))
- timer = threading.Timer(agent_timeout, self._timedShutdown)
- timer.start()
- elif utils.tobool(self.conf.get('acpiEnable', 'true')):
- self._guestEventTime = now
- self._guestEvent = 'Powering down'
- self._acpiShutdown()
- # No tools, no ACPI
- else:
- return {
- 'status': {
- 'code': errCode['exist']['status']['code'],
- 'message': 'VM without ACPI or active SolidICE tools. '
- 'Try Forced Shutdown.'}}
- except:
- self.log.error("Shutdown failed", exc_info=True)
- return {'status': {'code': errCode['exist']['status']['code'],
- 'message': 'Failed to shutdown VM. Try Forced Shutdown.'}}
+ if self.lastStatus == 'Down':
+ return
+ now = time.time()
+
+ status = None
+ for method, func in self._shutdownMethods:
+ try:
+ status = func(now, timeout, message)
+ except:
+ self.log.error("%s failed", method, exc_info=True)
+ status = {'status':
+ {'code': errCode['exist']['status']['code'],
+ 'message': 'Failed to shutdown VM. '
+ 'Try Forced Shutdown.'}}
+ # if one shutdown method failed, will try another method
+ # the loop will stop once a shutdown method is successful
+ if doneCode['code'] == status['status']['code']:
+ return status
+ if not status:
+ return {'status':
+ {'code': errCode['exist']['status']['code'],
+ 'message': 'VM without ACPI or active SolidICE tools. '
+ 'Try Forced Shutdown.'}}
+
+ return status
+
+ def guestAgentShutdown(self, now, timeout, message):
+ if self.guestAgent and self.guestAgent.isResponsive():
+ self._guestEventTime = time.time()
+ self._guestEvent = 'Powering down'
+ self.log.debug('guestAgent shutdown called')
+ self.guestAgent.desktopShutdown(timeout, message)
+ agent_timeout = (int(timeout) +
+ config.getint('vars', 'sys_shutdown_timeout'))
+ timer = threading.Timer(agent_timeout, self._timedShutdown)
+ timer.start()
+ else:
+ return None
+
return {'status': {'code': doneCode['code'],
'message': 'Machine shut down'}}
--
To view, visit http://gerrit.ovirt.org/9655
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I86977c1b717d63de21ba4818c6b66e43976d65de
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
Gerrit-Reviewer: Bing Bu Cao <mars(a)linux.vnet.ibm.com>
10 years, 6 months
Change in vdsm[master]: vdsm: report remaining values in migration stats
by peet@redhat.com
Peter V. Saveliev has uploaded a new change for review.
Change subject: vdsm: report remaining values in migration stats
......................................................................
vdsm: report remaining values in migration stats
So it would be possible to use such values to draw
eye-candy bars about migration statistics in the frontend.
Signed-off-by: Peter V. Saveliev <peet(a)redhat.com>
Change-Id: Idc32fa00eaa1b90c3ba9d0afffdeb1cdd8150f9a
---
M vdsm/libvirtvm.py
M vdsm/vm.py
2 files changed, 9 insertions(+), 2 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/25/15125/1
diff --git a/vdsm/libvirtvm.py b/vdsm/libvirtvm.py
index 5b16d69..2fcf249 100644
--- a/vdsm/libvirtvm.py
+++ b/vdsm/libvirtvm.py
@@ -377,6 +377,8 @@
self.daemon = True
self.data_progress = 0
self.mem_progress = 0
+ self.remaining = 0
+ self.remaining_lowmark = 0
def run(self):
def calculateProgress(remaining, total):
@@ -422,6 +424,8 @@
if jobType == 0:
continue
+ self.remaining = remaining
+ self.remaining_lowmark = lowmark
self.data_progress = calculateProgress(dataRemaining, dataTotal)
self.mem_progress = calculateProgress(memRemaining, memTotal)
diff --git a/vdsm/vm.py b/vdsm/vm.py
index 2b76662..53def15 100644
--- a/vdsm/vm.py
+++ b/vdsm/vm.py
@@ -124,9 +124,12 @@
"""
if self._monitorThread is not None:
# fetch migration status from the monitor thread
+ # shortcut to make flake8 happy
+ t = self._monitorThread
self.status['progress'] = int(
- float(self._monitorThread.data_progress +
- self._monitorThread.mem_progress) / 2)
+ float(t.data_progress + t.mem_progress) / 2)
+ self.status['remaining'] = t.remaining
+ self.status['remaining_lowmark'] = t.remaining_lowmark
return self.status
def _setupVdsConnection(self):
--
To view, visit http://gerrit.ovirt.org/15125
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Idc32fa00eaa1b90c3ba9d0afffdeb1cdd8150f9a
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Peter V. Saveliev <peet(a)redhat.com>
10 years, 6 months
Change in vdsm[master]: move kernelBootImages to a new file functionalUtils.py
by shaohef@linux.vnet.ibm.com
ShaoHe Feng has uploaded a new change for review.
Change subject: move kernelBootImages to a new file functionalUtils.py
......................................................................
move kernelBootImages to a new file functionalUtils.py
There is already a good functional test for xmlrpc test.
The jsonrpc test should benefit from the xmlrpc test.
So move some kernelBootImages to new file, jsonrpc test
can share with xmlrpc test.
Change-Id: If38afd417e5bb32066b13de4ff8f7b1f766f8215
Signed-off-by: ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
---
M tests/functional/Makefile.am
A tests/functional/functionalUtils.py
M tests/functional/xmlrpcTests.py
3 files changed, 77 insertions(+), 53 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/85/11385/1
diff --git a/tests/functional/Makefile.am b/tests/functional/Makefile.am
index e3374e8..98f0a60 100644
--- a/tests/functional/Makefile.am
+++ b/tests/functional/Makefile.am
@@ -21,6 +21,7 @@
vdsmfunctestsdir = ${vdsmtestsdir}/functional
dist_vdsmfunctests_PYTHON = \
+ functionalUtils.py \
jsonrpcSeverClient.py \
momTests.py \
sosPluginTests.py \
diff --git a/tests/functional/functionalUtils.py b/tests/functional/functionalUtils.py
new file mode 100644
index 0000000..78cdb50
--- /dev/null
+++ b/tests/functional/functionalUtils.py
@@ -0,0 +1,74 @@
+#
+# Copyright 2012 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 os
+import tempfile
+from contextlib import contextmanager
+
+from nose.plugins.skip import SkipTest
+
+from vdsm.constants import QEMU_PROCESS_USER, EXT_SUDO
+from storage.misc import execCmd
+from vdsm.utils import CommandPath
+
+_mkinitrd = CommandPath("mkinird", "/usr/bin/mkinitrd")
+
+
+def readableBy(filePath, user):
+ rc, out, err = execCmd([EXT_SUDO, '-u', user, 'head', '-c', '0', filePath])
+ return rc == 0
+
+
+@contextmanager
+def kernelBootImages():
+ kernelVer = os.uname()[2]
+ kernelPath = "/boot/vmlinuz-" + kernelVer
+ initramfsPath = "/boot/initramfs-%s.img" % kernelVer
+
+ if not os.path.isfile(kernelPath):
+ raise SkipTest("Can not locate kernel image for release %s" %
+ kernelVer)
+ if not readableBy(kernelPath, QEMU_PROCESS_USER):
+ raise SkipTest("qemu process can not read the file %s" % kernelPath)
+
+ if os.path.isfile(initramfsPath):
+ # There is an initramfs shipped with the distro, try use it
+ if not readableBy(initramfsPath, QEMU_PROCESS_USER):
+ raise SkipTest("qemu process can not read the file %s" %
+ initramfsPath)
+ try:
+ yield (kernelPath, initramfsPath)
+ finally:
+ pass
+ else:
+ # Generate an initramfs on demand, use it, delete it
+ initramfsPath = genInitramfs(kernelVer)
+ try:
+ yield (kernelPath, initramfsPath)
+ finally:
+ os.unlink(initramfsPath)
+
+
+def genInitramfs(kernelVer):
+ fd, path = tempfile.mkstemp()
+ cmd = [_mkinitrd.cmd, "-f", path, kernelVer]
+ rc, out, err = execCmd(cmd, sudo=False)
+ os.chmod(path, 0644)
+ return path
diff --git a/tests/functional/xmlrpcTests.py b/tests/functional/xmlrpcTests.py
index a898539..1ba00d3 100644
--- a/tests/functional/xmlrpcTests.py
+++ b/tests/functional/xmlrpcTests.py
@@ -23,9 +23,7 @@
import pwd
import grp
import shutil
-from contextlib import contextmanager
from functools import partial, wraps
-
from testrunner import VdsmTestCase as TestCaseBase
from testrunner import permutations, expandPermutations
from nose.plugins.skip import SkipTest
@@ -35,61 +33,12 @@
pass
from vdsm.config import config
-from vdsm.constants import VDSM_USER, VDSM_GROUP, QEMU_PROCESS_USER, EXT_SUDO
+from vdsm.constants import VDSM_USER, VDSM_GROUP
import storage.sd
import storage.volume
-from storage.misc import execCmd
from storage.misc import RollbackContext
-from vdsm.utils import CommandPath
from vdsm import vdscli
-
-if not config.getboolean('vars', 'xmlrpc_enable'):
- raise SkipTest("XML-RPC Bindings are disabled")
-
-_mkinitrd = CommandPath("mkinird", "/usr/bin/mkinitrd")
-
-
-def readableBy(filePath, user):
- rc, out, err = execCmd([EXT_SUDO, '-u', user, 'head', '-c', '0', filePath])
- return rc == 0
-
-
-@contextmanager
-def kernelBootImages():
- kernelVer = os.uname()[2]
- kernelPath = "/boot/vmlinuz-" + kernelVer
- initramfsPath = "/boot/initramfs-%s.img" % kernelVer
-
- if not os.path.isfile(kernelPath):
- raise SkipTest("Can not locate kernel image for release %s" %
- kernelVer)
- if not readableBy(kernelPath, QEMU_PROCESS_USER):
- raise SkipTest("qemu process can not read the file %s" % kernelPath)
-
- if os.path.isfile(initramfsPath):
- # There is an initramfs shipped with the distro, try use it
- if not readableBy(initramfsPath, QEMU_PROCESS_USER):
- raise SkipTest("qemu process can not read the file %s" %
- initramfsPath)
- try:
- yield (kernelPath, initramfsPath)
- finally:
- pass
- else:
- # Generate an initramfs on demand, use it, delete it
- initramfsPath = genInitramfs(kernelVer)
- try:
- yield (kernelPath, initramfsPath)
- finally:
- os.unlink(initramfsPath)
-
-
-def genInitramfs(kernelVer):
- fd, path = tempfile.mkstemp()
- cmd = [_mkinitrd.cmd, "-f", path, kernelVer]
- rc, out, err = execCmd(cmd, sudo=False)
- os.chmod(path, 0644)
- return path
+from functionalUtils import kernelBootImages
def skipNoKVM(method):
--
To view, visit http://gerrit.ovirt.org/11385
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: If38afd417e5bb32066b13de4ff8f7b1f766f8215
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
10 years, 6 months
Change in vdsm[master]: [WIP] rest-api: Model Networks
by lilei@linux.vnet.ibm.com
Lei Li has uploaded a new change for review.
Change subject: [WIP] rest-api: Model Networks
......................................................................
[WIP] rest-api: Model Networks
API Implemented:
----------------
/api/networks
* list, create, confirm and edit configuration for network
Actions:
/api/networks/add
- Add a new network
/api/networks/confirm
- Mark the current network configurations as safe
/api/networks/<id>/delete
- DELETE a network
/api/networks/<id>/edit
- Add a new network and replace the old one
API as TODO:
---------------
/api/networks/<id...>/setup
- Add/Edit/Remove configuration for networks
Change-Id: Ic7eca74c16699a5cc35c4077192fb6ecfe706470
Signed-off-by: Lei Li <lilei(a)linux.vnet.ibm.com>
---
M vdsm/rest/Controller.py
M vdsm/rest/templates/Makefile.am
M vdsm/rest/templates/api.xsd
A vdsm/rest/templates/network.json.x
A vdsm/rest/templates/network.xml.x
A vdsm/rest/templates/networks.json.x
A vdsm/rest/templates/networks.xml.x
M vdsm/rest/templates/root.json.x
M vdsm/rest/templates/root.xml.x
M vdsm/rest/templates/rsdl.xml
10 files changed, 377 insertions(+), 0 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/81/5881/1
--
To view, visit http://gerrit.ovirt.org/5881
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ic7eca74c16699a5cc35c4077192fb6ecfe706470
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Lei Li <lilei(a)linux.vnet.ibm.com>
10 years, 6 months
Change in vdsm[master]: Include vds_name parameter for node registration
by fgranha@linux.vnet.ibm.com
Fernando Granha Jeronimo has uploaded a new change for review.
Change subject: Include vds_name parameter for node registration
......................................................................
Include vds_name parameter for node registration
Motivation: in ovirt, the vds_name does not need to be resolvable.
In order to allow an arbitrary name, a new kernel parameter was created
(node_name). If this paramter is not passed, vdsm-reg will stick to
the hostname of the node (the previous behavior).
Change-Id: Ic1b0bcc473ef1a034736f80e1424e211ddf02946
Signed-off-by: Fernando Granha Jeronimo <fgranha(a)linux.vnet.ibm.com>
---
M vdsm_reg/config.py.in
M vdsm_reg/vdsm-config
M vdsm_reg/vdsm-reg-cmdline
M vdsm_reg/vdsm-reg-setup.in
M vdsm_reg/vdsm-reg.conf.in
5 files changed, 19 insertions(+), 1 deletion(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/36/8036/1
diff --git a/vdsm_reg/config.py.in b/vdsm_reg/config.py.in
index 6519ec2..d00b427 100644
--- a/vdsm_reg/config.py.in
+++ b/vdsm_reg/config.py.in
@@ -35,5 +35,6 @@
config.set('vars', 'vdc_host_port', '80')
config.set('vars', 'vdc_reg_port', '54321')
config.set('vars', 'vdc_reg_uri', '/SolidICE/VdsAutoRegistration.aspx')
+config.set('vars', 'vds_name', 'None')
config.set('vars', 'vdsm_conf_file', '/etc/vdsm/vdsm.conf')
config.set('vars', 'vdsm_dir', '@VDSMDIR@')
diff --git a/vdsm_reg/vdsm-config b/vdsm_reg/vdsm-config
index 1cb4c2c..6e0f7f3 100755
--- a/vdsm_reg/vdsm-config
+++ b/vdsm_reg/vdsm-config
@@ -65,6 +65,9 @@
rhevm_admin_password=*)
rhevm_admin_password=${i#rhevm_admin_password=}
;;
+ node_name=*)
+ node_name=${i#node_name=}
+ ;;
*)
;;
esac
@@ -75,6 +78,7 @@
vdc_managment_server=${managment_server%:*}
vdc_managment_port=${managment_server#*:}
strRHEVMAddress=$vdc_managment_server
+ vds_name=${node_name}
tmp_vdsm_reg_conf=`mktemp`
cat /etc/vdsm-reg/vdsm-reg.conf > "$tmp_vdsm_reg_conf"
echo "checkpoint 3::management_server: $vdc_managment_server, management_port: $vdc_managment_port" >> $LOG 2>&1
@@ -108,6 +112,11 @@
echo "No management_server_fingerprint found." | tee -a $LOG
fi
+ if [ ! -z "$vds_name" ]; then
+ sed --copy -i "s/\(^vds_name=\)\(..*$\)/\1${vds_name}/" \
+ /etc/vdsm-reg/vdsm-reg.conf
+ fi
+
## Set new configuration
fWriteConfig=1
else
diff --git a/vdsm_reg/vdsm-reg-cmdline b/vdsm_reg/vdsm-reg-cmdline
index 92ed468..e7f0047 100644
--- a/vdsm_reg/vdsm-reg-cmdline
+++ b/vdsm_reg/vdsm-reg-cmdline
@@ -3,4 +3,5 @@
management_server
management_server_fingerprint
rhevm_admin_password
+node_name
ovirt_vdsm_disable
diff --git a/vdsm_reg/vdsm-reg-setup.in b/vdsm_reg/vdsm-reg-setup.in
index 492e38d..8652293 100644
--- a/vdsm_reg/vdsm-reg-setup.in
+++ b/vdsm_reg/vdsm-reg-setup.in
@@ -48,7 +48,12 @@
self.vdsmDir = config.get('vars', 'vdsm_dir')
if self.vdcURL != "None":
self.ovirtURL = deployUtil.getMGTIP(self.vdsmDir, self.vdcName)
- self.ovirtName = socket.gethostname()
+
+ # use the name from config file, otherwise get the fqdn
+ self.ovirtName = config.get('vars', 'vds_name')
+ if self.ovirtName is None or self.ovirtName == "None":
+ self.ovirtName = socket.gethostname()
+
self.ovirtUID = deployUtil.getHostID()
else:
self.ovirtURL = "None"
diff --git a/vdsm_reg/vdsm-reg.conf.in b/vdsm_reg/vdsm-reg.conf.in
index 2e9df0d..c38401c 100644
--- a/vdsm_reg/vdsm-reg.conf.in
+++ b/vdsm_reg/vdsm-reg.conf.in
@@ -13,6 +13,8 @@
vdc_host_port=443
#The registrtion uri
vdc_reg_uri=/OvirtEngineWeb/register
+# The name of this node (it does not need to be resolvable)
+vds_name=None
#Upgrade settings
upgrade_iso_file=@VDSMUPGRADEDIR(a)/ovirt-node-image.iso
upgrade_mount_point=/live
--
To view, visit http://gerrit.ovirt.org/8036
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ic1b0bcc473ef1a034736f80e1424e211ddf02946
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Fernando Granha Jeronimo <fgranha(a)linux.vnet.ibm.com>
10 years, 6 months
Change in vdsm[master]: configNetwork: provide IPv6 configuration editing API
by mhuntxu@gmail.com
Hunt Xu has uploaded a new change for review.
Change subject: configNetwork: provide IPv6 configuration editing API
......................................................................
configNetwork: provide IPv6 configuration editing API
Change-Id: Ibf39d8cba75e8879a84e83e22a46a4a00eab1384
Signed-off-by: huntxu <mhuntxu(a)gmail.com>
---
M vdsm/configNetwork.py
M vdsm_api/vdsmapi-schema.json
2 files changed, 157 insertions(+), 19 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/41/11741/1
diff --git a/vdsm/configNetwork.py b/vdsm/configNetwork.py
index 963528c..4f1be10 100755
--- a/vdsm/configNetwork.py
+++ b/vdsm/configNetwork.py
@@ -415,7 +415,8 @@
def _createConfFile(self, conf, name, ipaddr=None, netmask=None,
gateway=None, bootproto=None, mtu=None, onboot='yes',
- **kwargs):
+ ipv6=False, ipv6addrs=None, ipv6gateway=None,
+ dhcpv6=False, **kwargs):
""" Create ifcfg-* file with proper fields per device """
cfg = """DEVICE=%s\nONBOOT=%s\n""" % (pipes.quote(name),
@@ -435,6 +436,25 @@
if mtu:
cfg = cfg + 'MTU=%d\n' % mtu
cfg += 'NM_CONTROLLED=no\n'
+
+ if ipv6:
+ cfg += 'IPV6INIT=yes\n'
+ ipv6autoconf = 'no'
+ if ipv6addrs is not None:
+ ipv6addrs = ipv6addrs.split(',')
+ primary = ipv6addrs[0]
+ secs = ' '.join(ipv6addrs[1:]).strip()
+ cfg += 'IPV6ADDR=%s\n' % pipes.quote(primary)
+ if secs:
+ cfg += 'IPV6ADDR_SECONDARIES=%s\n' % pipes.quote(secs)
+ if ipv6gateway is not None:
+ cfg += 'IPV6_DEFAULTGW=%s\n' % pipes.quote(ipv6gateway)
+ elif dhcpv6:
+ cfg += 'DHCPV6C=yes\n'
+ else:
+ ipv6autoconf = 'yes'
+ cfg += 'IPV6_AUTOCONF=%s\n' % pipes.quote(ipv6autoconf)
+
BLACKLIST = ['TYPE', 'NAME', 'DEVICE', 'bondingOptions',
'force', 'blockingdhcp',
'connectivityCheck', 'connectivityTimeout',
@@ -489,6 +509,22 @@
if mtu:
mtu = int(mtu)
+ if not utils.tobool(kwargs.get('ipv6', False)):
+ if confParams.get('IPV6INIT', 'no') == 'yes':
+ kwargs['ipv6'] = True
+ kwargs['ipv6gateway'] = confParams.get('IPV6_DEFAULTGW',
+ None)
+ kwargs['dhcpv6'] = (confParams.get('DHCPV6C', 'no')
+ == 'yes')
+
+ primary = confParams.get('IPV6ADDR', '')
+ secs = confParams.get('IPV6ADDR_SECONDARIES', '')
+ ipv6addrs = (primary + ' ' + secs).strip()
+ if len(ipv6addrs) > 0:
+ kwargs['ipv6addrs'] = ','.join(ipv6addrs.split(' '))
+ else:
+ kwargs['ipv6addrs'] = None
+
self._createConfFile(conf, bonding, ipaddr, netmask, gateway,
bootproto, mtu, onboot, **kwargs)
@@ -521,6 +557,22 @@
mtu = confParams.get('MTU', None)
if mtu:
mtu = int(mtu)
+
+ if not utils.tobool(kwargs.get('ipv6', False)):
+ if confParams.get('IPV6INIT', 'no') == 'yes':
+ kwargs['ipv6'] = True
+ kwargs['ipv6gateway'] = confParams.get('IPV6_DEFAULTGW',
+ None)
+ kwargs['dhcpv6'] = (confParams.get('DHCPV6C', 'no')
+ == 'yes')
+
+ primary = confParams.get('IPV6ADDR', '')
+ secs = confParams.get('IPV6ADDR_SECONDARIES', '')
+ ipv6addrs = (primary + ' ' + secs).strip()
+ if len(ipv6addrs) > 0:
+ kwargs['ipv6addrs'] = ','.join(ipv6addrs.split(' '))
+ else:
+ kwargs['ipv6addrs'] = None
self._createConfFile(conf, nic, ipaddr, netmask, gateway,
bootproto, mtu, onboot, **kwargs)
@@ -718,6 +770,37 @@
"Bad gateway: %r" % gateway)
+def _validateIPv6Address(address):
+ try:
+ socket.inet_pton(socket.AF_INET6, address)
+ except socket.error:
+ return False
+ return True
+
+
+def validateIPv6Address(addr):
+ if not _validateIPv6Address(addr):
+ raise ConfigNetworkError(ne.ERR_BAD_ADDR,
+ "Bad IPv6 address: %r" % addr)
+
+
+def validateIPv6Prefixlen(prefixlen):
+ try:
+ prefixlen = int(prefixlen)
+ if prefixlen < 0 or prefixlen > 127:
+ raise ConfigNetworkError(ne.ERR_BAD_ADDR,
+ "Bad IPv6 prefixlen: %r" % prefixlen)
+ except ValueError:
+ raise ConfigNetworkError(ne.ERR_BAD_ADDR,
+ "Bad IPv6 prefixlen: %r" % prefixlen)
+
+
+def validateIPv6Gateway(gateway):
+ if not _validateIPv6Address(gateway):
+ raise ConfigNetworkError(ne.ERR_BAD_ADDR,
+ "Bad IPv6 gateway: %r" % gateway)
+
+
def validateBondingName(bonding):
if not re.match('^bond[0-9]+$', bonding):
raise ConfigNetworkError(ne.ERR_BAD_BONDING,
@@ -790,8 +873,9 @@
def _addNetworkValidation(_netinfo, network, vlan, bonding, nics, ipaddr,
- netmask, gateway, bondingOptions, bridged=True,
- implicitBonding=False, **options):
+ netmask, gateway, bondingOptions, ipv6=False,
+ ipv6addrs=None, ipv6gateway=None, dhcpv6=False,
+ bridged=True, implicitBonding=False, **options):
# The (relatively) new setupNetwork verb allows to specify a network on
# top of an existing bonding device. The nics of this bonds are taken
# implictly from current host configuration
@@ -825,6 +909,24 @@
if netmask or gateway:
raise ConfigNetworkError(ne.ERR_BAD_ADDR,
'Specified netmask or gateway but not ip')
+
+ # Check IPv6
+ if ipv6:
+ if ipv6addrs:
+ if dhcpv6:
+ raise ConfigNetworkError(ne.ERR_BAD_PARAMS, 'Specified both'
+ 'IPv6 addresses and DHCPv6')
+ for addr in ipv6addrs.split(','):
+ if '/' in addr: # prefixlen is optional
+ addr, prefixlen = addr.split('/')
+ validateIPv6Prefixlen(prefixlen)
+ validateIPv6Address(addr)
+ if ipv6gateway:
+ validateIPv6Gateway(ipv6gateway)
+ else:
+ if ipv6addrs or ipv6gateway or dhcpv6:
+ raise ConfigNetworkError(ne.ERR_BAD_PARAMS, 'Specified IPv6-'
+ 'related params with IPv6 disabled')
# Check bonding
if bonding:
@@ -876,6 +978,11 @@
nics = nics or ()
_netinfo = netinfo.NetInfo()
bridged = utils.tobool(bridged)
+
+ if 'ipv6' in options:
+ options['ipv6'] = utils.tobool(options['ipv6'])
+ if 'dhcpv6' in options:
+ options['dhcpv6'] = utils.tobool(options['dhcpv6'])
if mtu:
mtu = int(mtu)
@@ -932,6 +1039,8 @@
# reset ip, netmask, gateway and bootproto for lower level devices
bridgeBootproto = options.get('bootproto')
ipaddr = netmask = gateway = options['bootproto'] = None
+ options['ipv6'] = options['dhcpv6'] = False
+ options['ipv6addrs'] = options['ipv6gateway'] = None
# For VLAN we should attach bridge only to the VLAN device
# rather than to underlying NICs or bond
@@ -952,6 +1061,8 @@
vlanBootproto = options.get('bootproto')
# reset ip, netmask, gateway and bootproto for lower level devices
ipaddr = netmask = gateway = options['bootproto'] = None
+ options['ipv6'] = options['dhcpv6'] = False
+ options['ipv6addrs'] = options['ipv6gateway'] = None
# First we need to prepare all conf files
if bonding:
@@ -963,6 +1074,8 @@
bondBootproto = options.get('bootproto')
# reset ip, netmask, gateway and bootproto for lower level devices
ipaddr = netmask = gateway = options['bootproto'] = None
+ options['ipv6'] = options['dhcpv6'] = False
+ options['ipv6addrs'] = options['ipv6gateway'] = None
for nic in nics:
configWriter.addNic(nic, bonding=bonding,
@@ -1302,6 +1415,10 @@
ipaddr="<ip>"
netmask="<ip>"
gateway="<ip>"
+ ipv6=True|False
+ ipv6addrs="<ip>[/<prefixlen>], ..." | dhcpv6=True|False
+ (ipv6addrs and dhcpv6 are mutually exclusive)
+ ipv6gateway="<ip>"
bootproto="..."
delay="..."
onboot="yes"|"no"
diff --git a/vdsm_api/vdsmapi-schema.json b/vdsm_api/vdsmapi-schema.json
index e2512ea..6d9c64e 100644
--- a/vdsm_api/vdsmapi-schema.json
+++ b/vdsm_api/vdsmapi-schema.json
@@ -54,6 +54,15 @@
#
# @gateway: #optional IP address of the network gateway
#
+# @ipv6: #optional Whether to use IPv6 on the interface
+#
+# @ipv6addrs: #optional A list of IPv6 addresses to be assigned to the
+# interface (in the format of '<ip>[/<prefixlen>], ...')
+#
+# @ipv6gateway: #optional IPv6 address of the gateway of the network
+#
+# @dhcpv6: #optional Whether to use DHCPv6 on the interface
+#
# @bootproto: #optional Interface autoconfiguration protocol (typically
# 'dhcp' or 'static')
#
@@ -67,8 +76,9 @@
##
{'type': 'NetworkOptions',
'data': {'*ipaddr': 'str', '*netmask': 'str', '*gateway': 'str',
- '*bootproto': 'str', '*delay': 'uint', '*onboot': 'str',
- '*bondingOptions', 'str'}}
+ '*ipv6': 'bool', '*ipv6addrs': 'str', '*ipv6gateway': 'str',
+ '*dhcpv6': 'bool', '*bootproto': 'str', '*delay': 'uint',
+ '*onboot': 'str', '*bondingOptions', 'str'}}
##
# @Host.addNetwork:
@@ -141,34 +151,45 @@
#
# Configuration attributes for a single host network.
#
-# @vlan: #optional The name of an associated vlan
+# @vlan: #optional The name of an associated vlan
#
-# @bonding: #optional If the network is bonded, the name of the bond device
+# @bonding: #optional If the network is bonded, the name of the bond device
#
-# @nic: #optional If the network is not bonded, an array containing a
-# single network device name
+# @nic: #optional If the network is not bonded, an array containing a
+# single network device name
#
-# @ipaddr: #optional Assign this static IP address to the network
+# @ipaddr: #optional Assign this static IP address to the network
#
-# @netmask: #optional Assign this netmask to the network
+# @netmask: #optional Assign this netmask to the network
#
-# @gateway: #optional Assign this gateway to the network
+# @gateway: #optional Assign this gateway to the network
#
-# @bootproto: #optional Interface autoconfiguration protocol (typically 'dhcp'
-# or 'static')
+# @ipv6: #optional Whether to use IPv6 on the interface
#
-# @delay: #optional The time to wait before starting the network device
+# @ipv6addrs: #optional A list of IPv6 addresses to be assigned to the
+# interface (in the format of '<ip>[/<prefixlen>], ...')
#
-# @onboot: #optional Start the network device automatically during boot
+# @ipv6gateway: #optional IPv6 address of the gateway of the network
#
-# @remove: #optional If True, remove existing network only
+# @dhcpv6: #optional Whether to use DHCPv6 on the interface
+#
+# @bootproto: #optional Interface autoconfiguration protocol (typically
+# 'dhcp' or 'static')
+#
+# @delay: #optional The time to wait before starting the network device
+#
+# @onboot: #optional Start the network device automatically during boot
+#
+# @remove: #optional If True, remove existing network only
#
# Since: 4.10.0
##
{'type': 'SetupNetworkNetAttributes',
'data': {'*vlan': 'str', '*bonding': 'str', '*nic': ['str'], '*ipaddr': 'str',
- '*netmask': 'str', '*gateway': 'str', '*bootproto': 'str',
- '*delay': 'uint', '*onboot': 'bool', '*remove': 'bool'}}
+ '*netmask': 'str', '*gateway': 'str', '*ipv6': 'bool',
+ '*ipv6addrs': 'str', '*ipv6gateway': 'str', '*dhcpv6': 'bool',
+ '*bootproto': 'str', '*delay': 'uint', '*onboot': 'bool',
+ '*remove': 'bool'}}
##
# @SetupNetworkBondAttributes:
--
To view, visit http://gerrit.ovirt.org/11741
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ibf39d8cba75e8879a84e83e22a46a4a00eab1384
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Hunt Xu <mhuntxu(a)gmail.com>
10 years, 7 months
Change in vdsm[master]: Added utility to ensure that files written to the file syste...
by asegurap@redhat.com
Antoni Segura Puimedon has uploaded a new change for review.
Change subject: Added utility to ensure that files written to the file system happen atomically.
......................................................................
Added utility to ensure that files written to the file system happen atomically.
The only way in python to make a file be written in an atomic way is to take
advantage of the fact that in POSIX filesystems the rename operation is atomic.
Thus, we write the context to a temporary file on the same filesystem, sync on
the file descriptor and finally do the atomic file rename to the original file
we wanted to write.
For more info:
http://stackoverflow.com/questions/2333872/atomic-writing-to-file-with-py...
http://stackoverflow.com/questions/7433057/is-rename-without-fsync-safe
Change-Id: Ibecd61d6746231a5a8cb17bad9a3302b01454f27
Signed-off-by: Antoni S. Puimedon <asegurap(a)redhat.com>
---
M vdsm/configNetwork.py
M vdsm/utils.py
2 files changed, 17 insertions(+), 1 deletion(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/56/7656/1
diff --git a/vdsm/configNetwork.py b/vdsm/configNetwork.py
index 58117f8..b943574 100755
--- a/vdsm/configNetwork.py
+++ b/vdsm/configNetwork.py
@@ -369,7 +369,8 @@
'''Backs up the previous contents of the file referenced by fileName
writes the new configuration and sets the specified access mode.'''
self._backup(fileName)
- open(fileName, 'w').write(configuration)
+ with utils.atomicWrite(fileName) as f:
+ f.write(configuration)
os.chmod(fileName, 0664)
try:
selinux.restorecon(fileName)
diff --git a/vdsm/utils.py b/vdsm/utils.py
index 5e2d4e5..bb8a842 100644
--- a/vdsm/utils.py
+++ b/vdsm/utils.py
@@ -36,6 +36,7 @@
import fcntl
import functools
import stat
+from contextlib import contextmanager
import ethtool
@@ -829,3 +830,17 @@
def __unicode__(self):
return unicode(self.cmd)
+
+@contextmanager
+def atomicWrite(file):
+ '''Context manager that makes the write happen to a temporary file and if
+ and only it is successful, overwrites the original file. It creates the
+ temporary file in the same directory of the destination file, as rename is
+ only atomic within the same filesystem.'''
+ tempFile = file+'vdsm_temp'
+ f = open(tempFile, 'w')
+ yield f
+ f.flush()
+ os.fsync(f.fileno())
+ f.close()
+ os.rename(tempFile, file)
--
To view, visit http://gerrit.ovirt.org/7656
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ibecd61d6746231a5a8cb17bad9a3302b01454f27
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Antoni Segura Puimedon <asegurap(a)redhat.com>
10 years, 7 months
Change in vdsm[master]: Add deathSignal options to better peopen
by smizrahi@redhat.com
Saggi Mizrahi has uploaded a new change for review.
Change subject: Add deathSignal options to better peopen
......................................................................
Add deathSignal options to better peopen
This allows VDSM to specify as signal that will be sent by the kernel to
the child when VDSM dies.
- Also fixes problem in the makefile that would cause make not to
recompile the SO when the C file was changed
Change-Id: I9f987129cea112e2a75d6f02477369417cc50dc7
Signed-off-by: Saggi Mizrahi <smizrahi(a)redhat.com>
---
M vdsm/betterPopen/Makefile.am
M vdsm/betterPopen/__init__.py
M vdsm/betterPopen/createprocess.c
3 files changed, 35 insertions(+), 5 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/41/6241/1
--
To view, visit http://gerrit.ovirt.org/6241
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I9f987129cea112e2a75d6f02477369417cc50dc7
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Saggi Mizrahi <smizrahi(a)redhat.com>
10 years, 7 months
Change in vdsm[master]: Add build-dep packages so yum-builddep is effective
by Ryan Harper
Ryan Harper has uploaded a new change for review.
Change subject: Add build-dep packages so yum-builddep is effective
......................................................................
Add build-dep packages so yum-builddep is effective
yum-builddep doesn't get all of the required packages
needed to build vdsm and vdsm rpms. Update the specfile
Build-Requires to include the needed packages.
Change-Id: Ia5b96b5b30a9efea06261f40d1f6df61754b8253
Signed-off-by: Ryan Harper <ryanh(a)us.ibm.com>
---
M vdsm.spec.in
1 file changed, 3 insertions(+), 0 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/55/7955/1
diff --git a/vdsm.spec.in b/vdsm.spec.in
index 56a42b4..300dbe5 100644
--- a/vdsm.spec.in
+++ b/vdsm.spec.in
@@ -29,6 +29,9 @@
BuildRequires: pyflakes
BuildRequires: python-nose
BuildRequires: python-pep8
+BuildRequires: gcc
+BuildRequires: automake
+BuildRequires: rpm-build
# BuildRequires needed by the tests during the build
BuildRequires: python-ethtool
--
To view, visit http://gerrit.ovirt.org/7955
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ia5b96b5b30a9efea06261f40d1f6df61754b8253
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Ryan Harper <ryanh(a)us.ibm.com>
10 years, 7 months
Change in vdsm[master]: [WIP]wait vdsm instead of poking it
by lvroyce@linux.vnet.ibm.com
Royce Lv has uploaded a new change for review.
Change subject: [WIP]wait vdsm instead of poking it
......................................................................
[WIP]wait vdsm instead of poking it
wait vdsm the subprocess, handling signal and error flow
as to terminate the subprocess.
Change-Id: Id2067cbd317cebfb7e0ad5aee64788adef591cf6
Signed-off-by: Royce Lv<lvroyce(a)linux.vnet.ibm.com>
---
M Makefile.am
M vdsm/supervdsmServer.py
2 files changed, 28 insertions(+), 19 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/92/11192/1
diff --git a/Makefile.am b/Makefile.am
index 48bdc5e..f0876a8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -54,7 +54,7 @@
vdsm/*.py.in \
vdsm/sos/vdsm.py.in \
vdsm/storage \
- vdsm/vdsm \
+ vdsm/vdsmServer.py \
vdsm_api \
vdsm_cli \
vdsm_hooks \
diff --git a/vdsm/supervdsmServer.py b/vdsm/supervdsmServer.py
index d64076b..77d2798 100755
--- a/vdsm/supervdsmServer.py
+++ b/vdsm/supervdsmServer.py
@@ -32,6 +32,7 @@
from gluster import cli as gcli
import storage.misc as misc
from vdsm import utils
+from vdsmServer import startVdsm
from parted_utils import getDevicePartedInfo as _getDevicePartedInfo
from md_utils import getMdDeviceUuidMap as _getMdDeviceUuidMap
@@ -44,7 +45,7 @@
from storage.fileUtils import chown, resolveGid, resolveUid
from storage.fileUtils import validateAccess as _validateAccess
from vdsm.constants import METADATA_GROUP, EXT_UDEVADM, \
- DISKIMAGE_USER, DISKIMAGE_GROUP, P_LIBVIRT_VMCHANNELS
+ DISKIMAGE_USER, DISKIMAGE_GROUP, P_LIBVIRT_VMCHANNELS, P_VDSM_RUN
from storage.devicemapper import _removeMapping, _getPathsStatus
import configNetwork
from vdsm.config import config
@@ -61,6 +62,7 @@
"%s-%s" + _UDEV_RULE_FILE_EXT
RUN_AS_TIMEOUT = config.getint("irs", "process_pool_timeout")
+ADDRESS = os.path.join(P_VDSM_RUN, "svdsm.sock")
class Timeout(RuntimeError):
@@ -332,18 +334,25 @@
return self.__udevVersion() > self.UDEV_WITH_RELOAD_VERSION
-def __pokeParent(parentPid, address, log):
+def initLogger():
try:
- while True:
- os.kill(parentPid, 0)
- sleep(2)
- except Exception:
- utils.rmFile(address)
- log.debug("Killing SuperVdsm Process")
- os.kill(os.getpid(), signal.SIGTERM)
+ logging.config.fileConfig(LOG_CONF_PATH)
+ except:
+ logging.basicConfig(filename='/dev/stdout', filemode='w+',
+ level=logging.DEBUG)
+ log = logging.getLogger("SuperVdsm.Server")
+ log.warn("Could not init proper logging", exc_info=True)
+
+ log = logging.getLogger("SuperVdsm.Server")
+ return log
-def main():
+def startSvdsm(address, childProc):
+ def sigtermHandler(signum, frame):
+ if childProc.is_alive():
+ childProc.terminate()
+ childProc.join()
+
def bind(func):
def wrapper(_SuperVdsm, *args, **kwargs):
return func(*args, **kwargs)
@@ -365,6 +374,7 @@
log.warn("Could not init proper logging", exc_info=True)
log = logging.getLogger("SuperVdsm.Server")
+ signal.signal(signal.SIGTERM, sigtermHandler)
try:
log.debug("Making sure I'm root")
@@ -388,13 +398,6 @@
zombieReaper.registerSignalHandler()
- log.debug("Setting up keep alive thread")
-
- monThread = threading.Thread(target=__pokeParent,
- args=[int(parentPid), address, log])
- monThread.setDaemon(True)
- monThread.start()
-
try:
log.debug("Creating remote object manager")
manager = _SuperVdsmManager(address=address, authkey=authkey)
@@ -414,11 +417,17 @@
# http://bugs.python.org/issue1167930
while servThread.isAlive():
servThread.join(5)
+ if not childProc.is_alive():
+ childProc.join()
+ raise Exception('Supervdsm died unexpectedly!')
finally:
if os.path.exists(address):
utils.rmFile(address)
except Exception:
+ if childProc.is_alive():
+ childProc.terminate()
+ childProc.join()
log.error("Could not start Super Vdsm", exc_info=True)
sys.exit(1)
@@ -426,4 +435,4 @@
vdsmProc = Process(target=startVdsm)
vdsmProc.start()
sleep(2)
- main()
+ startSvdsm(ADDRESS, vdsmProc)
--
To view, visit http://gerrit.ovirt.org/11192
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Id2067cbd317cebfb7e0ad5aee64788adef591cf6
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
10 years, 7 months