[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH] [RFC] Add lock on domain start
Jim Fehlig wrote: > This patch adds a simple lock mechanism when starting domains by placing > a lock file in xend-domains-path/<dom_uuid>. The lock file is removed > when domain is stopped. The motivation for such a mechanism is to > prevent starting the same domain from multiple hosts. > > If xend-domains-path is set to shared mount point, a domain will fail to > start on host B if it is already running on host A. I've added an > option to XendOptions to control the behavior with default of no lock. > > The patch certainly needs some testing (and probably adjustment) to > ensure the lock is handled properly on save, restore, migrate, domain > crash, etc. but wanted to get folks' thought on this approach before > continuing this endeavor. Some simple improvements could include adding > info (domain name/id, start time, vmm hostname) to the lock file, > allowing such messages as "domain foo seems to be already running on > host bar" and a --force option to create/start to override the lock. A > per-domain config option could also be added to allow more fine-grained > control. > > Comments, suggestions, alternative approaches, ... are welcome and > appreciated :-). > this patch xen-running-lock.patch add a external lock facility to get the same result. file-lock.c is a simple implement of the external lock utility. the external locking facility can leverage the dlm if you are in a cluster environment. cheers, zhigang > Regards, > Jim > > > ------------------------------------------------------------------------ > > _______________________________________________ > Xen-devel mailing list > Xen-devel@xxxxxxxxxxxxxxxxxxx > http://lists.xensource.com/xen-devel diff -Nura xen-unstable.orig/tools/examples/xend-config.sxp xen-unstable/tools/examples/xend-config.sxp --- xen-unstable.orig/tools/examples/xend-config.sxp 2008-08-06 17:26:37.000000000 +0800 +++ xen-unstable/tools/examples/xend-config.sxp 2008-08-06 17:28:45.000000000 +0800 @@ -63,6 +63,12 @@ #(xend-unix-path /var/lib/xend/xend-socket) +# External locking utility for get/release domain running lock. By default, +# no utility is specified. Thus there will be no lock as VM running. +# The locking utility should accept: +# <--lock | --unlock> --name <name> --uuid <uuid> +# command line options, and returns zero on success, others on error. +#(xend-domains-lock-path '') # Address and port xend should use for the legacy TCP XMLRPC interface, # if xend-tcp-xmlrpc-server is set. diff -Nura xen-unstable.orig/tools/python/xen/xend/XendDomainInfo.py xen-unstable/tools/python/xen/xend/XendDomainInfo.py --- xen-unstable.orig/tools/python/xen/xend/XendDomainInfo.py 2008-08-06 17:26:39.000000000 +0800 +++ xen-unstable/tools/python/xen/xend/XendDomainInfo.py 2008-08-06 17:31:27.000000000 +0800 @@ -328,6 +328,8 @@ @type state_updated: threading.Condition @ivar refresh_shutdown_lock: lock for polling shutdown state @type refresh_shutdown_lock: threading.Condition + @ivar running_lock: lock for running VM + @type running_lock: bool or None @ivar _deviceControllers: device controller cache for this domain @type _deviceControllers: dict 'string' to DevControllers """ @@ -395,6 +397,8 @@ self.refresh_shutdown_lock = threading.Condition() self._stateSet(DOM_STATE_HALTED) + self.running_lock = None + self._deviceControllers = {} for state in DOM_STATES_OLD: @@ -421,6 +425,7 @@ 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) @@ -453,6 +458,7 @@ state = self._stateGet() if state in (DOM_STATE_SUSPENDED, DOM_STATE_HALTED): try: + self.acquire_running_lock(); self._constructDomain() self._storeVmDetails() self._createDevices() @@ -2292,6 +2298,11 @@ self._stateSet(DOM_STATE_HALTED) self.domid = None # Do not push into _stateSet()! + + try: + self.release_running_lock() + except: + log.exception("Release running lock failed: %s" % status) finally: self.refresh_shutdown_lock.release() @@ -3520,6 +3531,28 @@ def has_device(self, dev_class, dev_uuid): return (dev_uuid in self.info['%s_refs' % dev_class.lower()]) + def acquire_running_lock(self): + if not self.running_lock: + lock_path = xoptions.get_xend_domains_lock_path() + if lock_path: + status = os.system('%s --lock --name %s --uuid %s' % \ + (lock_path, self.info['name_label'], self.info['uuid'])) + if status == 0: + self.running_lock = True + else: + raise XendError('Acquire running lock failed: %s' % status) + + def release_running_lock(self): + if self.running_lock: + lock_path = xoptions.get_xend_domains_lock_path() + if lock_path: + status = os.system('%s --unlock --name %s --uuid %s' % \ + (lock_path, self.info['name_label'], self.info['uuid'])) + if status == 0: + self.running_lock = False + else: + raise XendError('Release running lock failed: %s' % status) + def __str__(self): return '<domain id=%s name=%s memory=%s state=%s>' % \ (str(self.domid), self.info['name_label'], diff -Nura xen-unstable.orig/tools/python/xen/xend/XendDomain.py xen-unstable/tools/python/xen/xend/XendDomain.py --- xen-unstable.orig/tools/python/xen/xend/XendDomain.py 2008-08-06 17:26:39.000000000 +0800 +++ xen-unstable/tools/python/xen/xend/XendDomain.py 2008-08-06 17:30:23.000000000 +0800 @@ -1295,6 +1295,7 @@ POWER_STATE_NAMES[dominfo._stateGet()]) """ The following call may raise a XendError exception """ + dominfo.release_running_lock(); dominfo.testMigrateDevices(True, dst) if live: diff -Nura xen-unstable.orig/tools/python/xen/xend/XendOptions.py xen-unstable/tools/python/xen/xend/XendOptions.py --- xen-unstable.orig/tools/python/xen/xend/XendOptions.py 2008-08-06 17:26:39.000000000 +0800 +++ xen-unstable/tools/python/xen/xend/XendOptions.py 2008-08-06 17:28:45.000000000 +0800 @@ -271,6 +271,11 @@ """ return self.get_config_string("xend-domains-path", self.xend_domains_path_default) + def get_xend_domains_lock_path(self): + """ Get the path of the lock utility for running domains. + """ + return self.get_config_string("xend-domains-lock-path") + def get_xend_state_path(self): """ Get the path for persistent domain configuration storage """ /* * file-lock.c * * Copyright (C) 2008 Oracle Inc. * Copyright (C) 2008 Zhigang Wang <zhigang.x.wang@xxxxxxxxxx> * * 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 3 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, see <http://www.gnu.org/licenses/>. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <getopt.h> const char version[] = "0.0.1"; static char short_opts[] = "lup:d:n:hvV"; static struct option long_opts[] = { { "lock", no_argument, NULL, 'l' }, { "unlock", no_argument, NULL, 'u' }, { "path", required_argument, NULL, 'p' }, { "name", required_argument, NULL, 'n' }, { "uuid", required_argument, NULL, 'd' }, { "help", no_argument, NULL, 'h' }, { "verbose", no_argument, NULL, 'v' }, { "version", no_argument, NULL, 'V' }, { NULL, 0, NULL, 0 } }; static void usage(char *prog, FILE *fp, int n) { fprintf(fp, "usage: %s [options]\n", prog); fprintf(fp, "\n"); fprintf(fp, "options:\n"); fprintf(fp, " -l, --lock Acquire the lock.\n"); fprintf(fp, " -u, --unlock Release the lock.\n"); fprintf(fp, " -p, --path Set the path for the locks.\n"); fprintf(fp, " -n, --name Set the name of the VM.\n"); fprintf(fp, " -d, --uuid Set the uuid of the VM.\n"); fprintf(fp, " -v, --verbose Show more infomation.\n"); fprintf(fp, " -V, --version Show version number and exit.\n"); fprintf(fp, " -h, --help Show this help information.\n"); fprintf(fp, "\n"); exit(n); } static int do_lock(char *path, char *name, char *uuid) { char *fn; int fd; if (asprintf(&fn, "%s/%s-%s.lock", path, name, uuid) == -1) return -1; fd = open(fn, O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); if (fd == -1) { free(fn); return errno; } free(fn); close(fd); return 0; } static int do_unlock(char *path, char *name, char *uuid) { char *fn; if (asprintf(&fn, "%s/%s-%s.lock", path, name, uuid) == -1) return -1; if (unlink(fn) == -1) { free(fn); return errno; } free(fn); return 0; } int main(int argc, char *argv[]) { char *prog, *p; char *name = NULL; char *uuid = NULL; char *path = "."; /* create lock file on current working directory by default*/ int verbose = 0; /* turn off verbose output by default */ int status = 0; /* returned value */ int lock = 0, unlock = 0; int c; prog = argv[0]; p = strrchr(prog, '/'); if (p) prog = p+1; while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) { switch (c) { case 'l': /* acquire the lock */ lock = 1; break; case 'u': /* release the lock */ unlock = 1; break; case 'p': /* path for lock file */ path = optarg; break; case 'n': /* name of vm */ name = optarg; break; case 'd': /* uuid of vm */ uuid = optarg; break; case 'h': /* help */ usage(prog, stdout, 0); break; case 'v': /* be chatty */ ++verbose; break; case 'V': /* version */ fprintf(stdout, "%s: %s\n", prog, version); exit(0); case 0: break; case '?': default: usage(prog, stderr, 1); } } if (optind < argc) usage(prog, stderr, 1); if (name==NULL || uuid==NULL) { fprintf(stderr, "you should specify the name and uuid of vm.\n\n"); usage(prog, stderr, 1); } if (lock && unlock) { fprintf(stderr, "cannot execute lock and unlock at the same time.\n\n"); usage(prog, stderr, 1); } if (lock) { if (verbose) fprintf(stdout, "creating lock file %s/%s-%s.lock\n", path, name, uuid); status = do_lock(path, name, uuid); if (verbose) if (status == 0) fprintf(stdout, "lock sucess.\n"); else fprintf(stdout, "lock failed.\n"); } else if (unlock) { if (verbose) fprintf(stdout, "removing lock file %s/%s-%s.lock\n", path, name, uuid); status = do_unlock(path, name, uuid); if (verbose) if (status == 0) fprintf(stdout, "unlock sucess.\n"); else fprintf(stdout, "unlock failed.\n"); } else { fprintf(stderr, "you should specify lock or unlock.\n\n"); usage(prog, stderr, 1); } return status; } _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |