329 lines
11 KiB
Diff
329 lines
11 KiB
Diff
Index: xen-3.3.1-testing/tools/examples/domain-lock
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ xen-3.3.1-testing/tools/examples/domain-lock
|
|
@@ -0,0 +1,86 @@
|
|
+#!/bin/bash
|
|
+
|
|
+set +x
|
|
+
|
|
+usage() {
|
|
+ echo "usage: domain-lock [-l|-u|-s] -p <vm-config-path> [-n <vm-name>] [-i <vm-uuid>] [-h <vm-host>]"
|
|
+ echo ""
|
|
+ echo "-l lock"
|
|
+ echo "-u unlock"
|
|
+ echo "-s status (default)"
|
|
+ echo "-p Required argument indicating path for lock file"
|
|
+ echo "-n Virtual Machine name"
|
|
+ echo "-i Virtual Machine Id or UUID"
|
|
+ echo "-h Virtual Machine Server (Host) name"
|
|
+ exit 1
|
|
+}
|
|
+
|
|
+create_lock() {
|
|
+ local path=$1
|
|
+ local name=$2
|
|
+ local uuid=$3
|
|
+ local host=$4
|
|
+
|
|
+ path=$path/lock
|
|
+ cat > $path <<EOF
|
|
+$name $uuid $host
|
|
+EOF
|
|
+}
|
|
+
|
|
+remove_lock(){
|
|
+ local path=$1/lock
|
|
+
|
|
+ rm -f $path
|
|
+}
|
|
+
|
|
+get_status() {
|
|
+ local path=$1/lock
|
|
+
|
|
+ [ -f $path ] || exit 1
|
|
+ echo `cat $path`
|
|
+}
|
|
+
|
|
+mode="status"
|
|
+
|
|
+while getopts ":lusp:n:i:h:" opt; do
|
|
+ case $opt in
|
|
+ l )
|
|
+ mode="lock"
|
|
+ ;;
|
|
+ u )
|
|
+ mode="unlock"
|
|
+ ;;
|
|
+ s )
|
|
+ mode="status"
|
|
+ ;;
|
|
+ p )
|
|
+ vm_path=$OPTARG
|
|
+ ;;
|
|
+ n )
|
|
+ vm_name=$OPTARG
|
|
+ ;;
|
|
+ i )
|
|
+ vm_uuid=$OPTARG
|
|
+ ;;
|
|
+ h )
|
|
+ vm_host=$OPTARG
|
|
+ ;;
|
|
+ \? )
|
|
+ usage
|
|
+ ;;
|
|
+ esac
|
|
+done
|
|
+
|
|
+[ -z $vm_path ] && usage
|
|
+
|
|
+case $mode in
|
|
+ lock )
|
|
+ create_lock $vm_path $vm_name $vm_uuid $vm_host
|
|
+ ;;
|
|
+ unlock )
|
|
+ remove_lock $vm_path
|
|
+ ;;
|
|
+ status )
|
|
+ get_status $vm_path
|
|
+ ;;
|
|
+esac
|
|
Index: xen-3.3.1-testing/tools/examples/xend-config.sxp
|
|
===================================================================
|
|
--- xen-3.3.1-testing.orig/tools/examples/xend-config.sxp
|
|
+++ xen-3.3.1-testing/tools/examples/xend-config.sxp
|
|
@@ -255,4 +255,44 @@
|
|
|
|
# Path where persistent domain configuration is stored.
|
|
# Default is /var/lib/xend/domains/
|
|
+#
|
|
#(xend-domains-path /var/lib/xend/domains)
|
|
+
|
|
+# Create a lock file when domains are started. Lock file is
|
|
+# placed in xend-domains-path/<domain_uuid> on domain startup
|
|
+# and removed when domain is stopped. By default, a lock file
|
|
+# is not created. Set to yes to enable lock file creation.
|
|
+#
|
|
+#(xend-domain-lock no)
|
|
+
|
|
+# Path where domain lock is stored if xend-domain-lock is enabled.
|
|
+# Note: This path must be accessible to all VM Servers participating
|
|
+# in domain locking, e.g. by specifying a shared mount point.
|
|
+# Lock is placed in <xend-domain-lock-path>/<domain-uuid>.
|
|
+# Default is /var/lib/xend/domains/
|
|
+#
|
|
+#(xend-domain-lock-path /var/lib/xend/domains)
|
|
+
|
|
+# External locking utility for acquiring/releasing domain lock.
|
|
+# By default /etc/xen/scripts/domain-lock will be used if
|
|
+# xend-domain-lock is set to yes. Set to path of custom
|
|
+# locking utility to override the default. Locking utility
|
|
+# should accept
|
|
+# <-l | -u | -s> -p <vm-config-path> [-n <vm-name>] [-i <vm-id>]
|
|
+# [-h <vm-host>]
|
|
+# command line options. Utility should return zero on success,
|
|
+# non-zero on error.
|
|
+# -l lock Acquire (create) lock file
|
|
+# -u unlock Remove lock file
|
|
+# -s status Default action. If lock file exists, print contents on
|
|
+# stdout and return 0)
|
|
+# -p path Required. Path where lock file should be written.
|
|
+# -n vm-name Name of domain
|
|
+# -i vm-id Id or UUID of domain
|
|
+# -h vm-host Name of host machine (dom0)
|
|
+#
|
|
+# The /etc/xen/scripts/domain-lock default utility will create
|
|
+# <xend-domain-lock-path>/<vm-uuid>/lock and write <vm-name>, <vm-id>,
|
|
+# and <vm-host> (if supplied) to the lock file in that order.
|
|
+#
|
|
+#(xend-domain-lock-utility domain-lock)
|
|
Index: xen-3.3.1-testing/tools/python/xen/xend/XendDomainInfo.py
|
|
===================================================================
|
|
--- xen-3.3.1-testing.orig/tools/python/xen/xend/XendDomainInfo.py
|
|
+++ xen-3.3.1-testing/tools/python/xen/xend/XendDomainInfo.py
|
|
@@ -30,11 +30,13 @@ import threading
|
|
import re
|
|
import copy
|
|
import os
|
|
+import stat
|
|
+import shutil
|
|
import traceback
|
|
from types import StringTypes
|
|
|
|
import xen.lowlevel.xc
|
|
-from xen.util import asserts
|
|
+from xen.util import asserts, mkdir
|
|
from xen.util.blkif import parse_uname
|
|
import xen.util.xsm.xsm as security
|
|
from xen.util import xsconstants
|
|
@@ -443,6 +445,7 @@ class XendDomainInfo:
|
|
|
|
if self._stateGet() in (XEN_API_VM_POWER_STATE_HALTED, XEN_API_VM_POWER_STATE_SUSPENDED, XEN_API_VM_POWER_STATE_CRASHED):
|
|
try:
|
|
+ self.acquire_running_lock();
|
|
XendTask.log_progress(0, 30, self._constructDomain)
|
|
XendTask.log_progress(31, 60, self._initDomain)
|
|
|
|
@@ -475,6 +478,7 @@ class XendDomainInfo:
|
|
state = self._stateGet()
|
|
if state in (DOM_STATE_SUSPENDED, DOM_STATE_HALTED):
|
|
try:
|
|
+ self.acquire_running_lock();
|
|
self._constructDomain()
|
|
self._storeVmDetails()
|
|
self._createChannels()
|
|
@@ -2316,6 +2320,11 @@ class XendDomainInfo:
|
|
|
|
self._stateSet(DOM_STATE_HALTED)
|
|
self.domid = None # Do not push into _stateSet()!
|
|
+
|
|
+ try:
|
|
+ self.release_running_lock()
|
|
+ except:
|
|
+ log.exception("Failed to release domain lock.")
|
|
finally:
|
|
self.refresh_shutdown_lock.release()
|
|
|
|
@@ -3537,6 +3546,74 @@ class XendDomainInfo:
|
|
def has_device(self, dev_class, dev_uuid):
|
|
return (dev_uuid in self.info['%s_refs' % dev_class.lower()])
|
|
|
|
+ # Check if domain has a lock file present
|
|
+ def is_dom_locked(self, path):
|
|
+ status = os.system('%s -s -p %s' % \
|
|
+ (xoptions.get_xend_domain_lock_utility(), \
|
|
+ path))
|
|
+
|
|
+ return status == 0
|
|
+
|
|
+ # Return name of host contained in lock file. Host should be last
|
|
+ # entry in the lock file.
|
|
+ def get_lock_host(self, path):
|
|
+ fin = os.popen(xoptions.get_xend_domain_lock_utility() + \
|
|
+ ' -s -p ' + path, 'r')
|
|
+ hostname = "unknown"
|
|
+
|
|
+ try:
|
|
+ line = fin.readline()
|
|
+ hostname = line.split()[-1]
|
|
+ finally:
|
|
+ fin.close()
|
|
+ return hostname
|
|
+
|
|
+ # Acquire a lock for the domain. No-op if domain locking is turned off.
|
|
+ def acquire_running_lock(self):
|
|
+ if not xoptions.get_xend_domain_lock():
|
|
+ return
|
|
+
|
|
+ path = xoptions.get_xend_domain_lock_path()
|
|
+ path = os.path.join(path, self.get_uuid())
|
|
+
|
|
+ if self.is_dom_locked(path):
|
|
+ raise XendError("The VM is locked and appears to be running on host %s." % self.get_lock_host(path))
|
|
+
|
|
+ try:
|
|
+ if not os.path.exists(path):
|
|
+ mkdir.parents(path, stat.S_IRWXU)
|
|
+ except:
|
|
+ log.exception("%s could not be created." % path)
|
|
+ raise XendError("%s could not be created." % path)
|
|
+
|
|
+ status = os.system('%s -l -p %s -n %s -i %s -h %s' % \
|
|
+ (xoptions.get_xend_domain_lock_utility(), \
|
|
+ path, \
|
|
+ self.info['name_label'], \
|
|
+ self.info['uuid'], \
|
|
+ XendNode.instance().get_name()))
|
|
+ if status != 0:
|
|
+ raise XendError('Acquire running lock failed: %s' % status)
|
|
+
|
|
+ # Release lock for domain. Should be called at end of domain cleanup
|
|
+ def release_running_lock(self):
|
|
+ if not xoptions.get_xend_domain_lock():
|
|
+ return
|
|
+
|
|
+ path = xoptions.get_xend_domain_lock_path()
|
|
+ path = os.path.join(path, self.get_uuid())
|
|
+ status = os.system('%s -u -p %s' % \
|
|
+ (xoptions.get_xend_domain_lock_utility(), \
|
|
+ path))
|
|
+ if status != 0:
|
|
+ log.exception("Release running lock failed: %s" % status)
|
|
+ try:
|
|
+ if len(os.listdir(path)) == 0:
|
|
+ shutil.rmtree(path)
|
|
+ except:
|
|
+ log.exception("Failed to remove unmanaged directory %s." % path)
|
|
+
|
|
+
|
|
def __str__(self):
|
|
return '<domain id=%s name=%s memory=%s state=%s>' % \
|
|
(str(self.domid), self.info['name_label'],
|
|
Index: xen-3.3.1-testing/tools/python/xen/xend/XendDomain.py
|
|
===================================================================
|
|
--- xen-3.3.1-testing.orig/tools/python/xen/xend/XendDomain.py
|
|
+++ xen-3.3.1-testing/tools/python/xen/xend/XendDomain.py
|
|
@@ -1299,6 +1299,7 @@ class XendDomain:
|
|
POWER_STATE_NAMES[DOM_STATE_RUNNING],
|
|
POWER_STATE_NAMES[dominfo._stateGet()])
|
|
|
|
+ dominfo.release_running_lock();
|
|
""" The following call may raise a XendError exception """
|
|
dominfo.testMigrateDevices(True, dst)
|
|
|
|
Index: xen-3.3.1-testing/tools/python/xen/xend/XendOptions.py
|
|
===================================================================
|
|
--- xen-3.3.1-testing.orig/tools/python/xen/xend/XendOptions.py
|
|
+++ xen-3.3.1-testing/tools/python/xen/xend/XendOptions.py
|
|
@@ -135,6 +135,17 @@ class XendOptions:
|
|
"""Default rotation count of qemu-dm log file."""
|
|
qemu_dm_logrotate_count = 10
|
|
|
|
+ """Default for the flag indicating whether xend should create
|
|
+ a lock file for domains when they are started."""
|
|
+ xend_domain_lock = 'no'
|
|
+
|
|
+ """Default domain lock storage path."""
|
|
+ xend_domain_lock_path_default = '/var/lib/xend/domains'
|
|
+
|
|
+ """Default script to acquire/release domain lock"""
|
|
+ xend_domain_lock_utility = osdep.scripts_dir + "/domain-lock"
|
|
+
|
|
+
|
|
def __init__(self):
|
|
self.configure()
|
|
|
|
@@ -358,6 +369,19 @@ class XendOptions:
|
|
return self.get_config_int("qemu-dm-logrotate-count",
|
|
self.qemu_dm_logrotate_count)
|
|
|
|
+ def get_xend_domain_lock(self):
|
|
+ """Get the flag indicating whether xend should create a lock file
|
|
+ for domains when they are started."""
|
|
+ return self.get_config_bool("xend-domain-lock", self.xend_domain_lock)
|
|
+
|
|
+ def get_xend_domain_lock_path(self):
|
|
+ """ Get the path for domain lock storage
|
|
+ """
|
|
+ return self.get_config_string("xend-domain-lock-path", self.xend_domain_lock_path_default)
|
|
+
|
|
+ def get_xend_domain_lock_utility(self):
|
|
+ return self.get_config_string('xend-domain-lock-utility', self.xend_domain_lock_utility)
|
|
+
|
|
|
|
class XendOptionsFile(XendOptions):
|
|
|
|
Index: xen-3.3.1-testing/tools/examples/Makefile
|
|
===================================================================
|
|
--- xen-3.3.1-testing.orig/tools/examples/Makefile
|
|
+++ xen-3.3.1-testing/tools/examples/Makefile
|
|
@@ -35,6 +35,7 @@ XEN_SCRIPTS += vtpm vtpm-delete
|
|
XEN_SCRIPTS += xen-hotplug-cleanup
|
|
XEN_SCRIPTS += external-device-migrate
|
|
XEN_SCRIPTS += vscsi
|
|
+XEN_SCRIPTS += domain-lock
|
|
XEN_SCRIPT_DATA = xen-script-common.sh locking.sh logging.sh
|
|
XEN_SCRIPT_DATA += xen-hotplug-common.sh xen-network-common.sh vif-common.sh
|
|
XEN_SCRIPT_DATA += block-common.sh vtpm-common.sh vtpm-hotplug-common.sh
|