- pathutils: Prepend node-specific prefix path
- RPC: Use virtual paths (see vcluster.py)
- SSH: Pass environment variables, use destination's node directory when
copying files using scp, use GANETI_HOSTNAME to determine hostname
---
lib/backend.py | 8 ++++++++
lib/hypervisor/hv_xen.py | 7 ++++---
lib/jqueue.py | 15 ++++++++++++---
lib/pathutils.py | 20 ++++++++++++--------
lib/rpc.py | 5 ++++-
lib/ssh.py | 22 +++++++++++++++++++---
6 files changed, 59 insertions(+), 18 deletions(-)
diff --git a/lib/backend.py b/lib/backend.py
index 1e76c99..0f102dd 100644
--- a/lib/backend.py
+++ b/lib/backend.py
@@ -63,6 +63,7 @@ from ganeti import runtime
from ganeti import mcpu
from ganeti import compat
from ganeti import pathutils
+from ganeti import vcluster
_BOOT_ID_PATH = "/proc/sys/kernel/random/boot_id"
@@ -2072,6 +2073,8 @@ def UploadFile(file_name, data, mode, uid, gid, atime,
mtime):
@rtype: None
"""
+ file_name = vcluster.LocalizeVirtualPath(file_name)
+
if not os.path.isabs(file_name):
_Fail("Filename passed to UploadFile is not absolute: '%s'", file_name)
@@ -2821,6 +2824,8 @@ def JobQueueUpdate(file_name, content):
@return: the success of the operation
"""
+ file_name = vcluster.LocalizeVirtualPath(file_name)
+
_EnsureJobQueueFile(file_name)
getents = runtime.GetEnts()
@@ -2842,6 +2847,9 @@ def JobQueueRename(old, new):
@return: the success of the operation and payload
"""
+ old = vcluster.LocalizeVirtualPath(old)
+ new = vcluster.LocalizeVirtualPath(new)
+
_EnsureJobQueueFile(old)
_EnsureJobQueueFile(new)
diff --git a/lib/hypervisor/hv_xen.py b/lib/hypervisor/hv_xen.py
index 7274240..2ed84f3 100644
--- a/lib/hypervisor/hv_xen.py
+++ b/lib/hypervisor/hv_xen.py
@@ -33,11 +33,12 @@ from ganeti.hypervisor import hv_base
from ganeti import netutils
from ganeti import objects
from ganeti import pathutils
+from ganeti import vcluster
-XEND_CONFIG_FILE = "/etc/xen/xend-config.sxp"
-XL_CONFIG_FILE = "/etc/xen/xl.conf"
-VIF_BRIDGE_SCRIPT = "/etc/xen/scripts/vif-bridge"
+XEND_CONFIG_FILE = vcluster.AddNodePrefix("/etc/xen/xend-config.sxp")
+XL_CONFIG_FILE = vcluster.AddNodePrefix("/etc/xen/xl.conf")
+VIF_BRIDGE_SCRIPT = vcluster.AddNodePrefix("/etc/xen/scripts/vif-bridge")
_DOM0_NAME = "Domain-0"
diff --git a/lib/jqueue.py b/lib/jqueue.py
index f4d58f4..96c29a1 100644
--- a/lib/jqueue.py
+++ b/lib/jqueue.py
@@ -60,6 +60,7 @@ from ganeti import ht
from ganeti import query
from ganeti import qlang
from ganeti import pathutils
+from ganeti import vcluster
JOBQUEUE_THREADS = 25
@@ -85,6 +86,14 @@ def TimeStampNow():
return utils.SplitTime(time.time())
+def _CallJqUpdate(runner, names, file_name, content):
+ """Updates job queue file after virtualizing filename.
+
+ """
+ virt_file_name = vcluster.MakeVirtualPath(file_name)
+ return runner.call_jobqueue_update(names, virt_file_name, content)
+
+
class _SimpleJobQuery:
"""Wrapper for job queries.
@@ -1690,8 +1699,8 @@ class JobQueue(object):
# Read file content
content = utils.ReadFile(file_name)
- result = self._GetRpc(addrs).call_jobqueue_update([node_name], file_name,
- content)
+ result = _CallJqUpdate(self._GetRpc(addrs), [node_name],
+ file_name, content)
msg = result[node_name].fail_msg
if msg:
logging.error("Failed to upload file %s to node %s: %s",
@@ -1775,7 +1784,7 @@ class JobQueue(object):
if replicate:
names, addrs = self._GetNodeIp()
- result = self._GetRpc(addrs).call_jobqueue_update(names, file_name, data)
+ result = _CallJqUpdate(self._GetRpc(addrs), names, file_name, data)
self._CheckRpcResult(result, self._nodes, "Updating %s" % file_name)
def _RenameFilesUnlocked(self, rename):
diff --git a/lib/pathutils.py b/lib/pathutils.py
index 738c661..e60a7a4 100644
--- a/lib/pathutils.py
+++ b/lib/pathutils.py
@@ -24,15 +24,19 @@
"""
from ganeti import _autoconf
+from ganeti import vcluster
+
# Build-time constants
-DEFAULT_FILE_STORAGE_DIR = _autoconf.FILE_STORAGE_DIR
-DEFAULT_SHARED_FILE_STORAGE_DIR = _autoconf.SHARED_FILE_STORAGE_DIR
-EXPORT_DIR = _autoconf.EXPORT_DIR
+DEFAULT_FILE_STORAGE_DIR = vcluster.AddNodePrefix(_autoconf.FILE_STORAGE_DIR)
+DEFAULT_SHARED_FILE_STORAGE_DIR = \
+ vcluster.AddNodePrefix(_autoconf.SHARED_FILE_STORAGE_DIR)
+EXPORT_DIR = vcluster.AddNodePrefix(_autoconf.EXPORT_DIR)
OS_SEARCH_PATH = _autoconf.OS_SEARCH_PATH
SSH_CONFIG_DIR = _autoconf.SSH_CONFIG_DIR
-SYSCONFDIR = _autoconf.SYSCONFDIR
+SYSCONFDIR = vcluster.AddNodePrefix(_autoconf.SYSCONFDIR)
TOOLSDIR = _autoconf.TOOLSDIR
+LOCALSTATEDIR = vcluster.AddNodePrefix(_autoconf.LOCALSTATEDIR)
# Paths which don't change for a virtual cluster
DAEMON_UTIL = _autoconf.PKGLIBDIR + "/daemon-util"
@@ -43,10 +47,10 @@ SETUP_SSH = _autoconf.TOOLSDIR + "/setup-ssh"
XM_CONSOLE_WRAPPER = _autoconf.PKGLIBDIR + "/tools/xm-console-wrapper"
# Top-level paths
-DATA_DIR = _autoconf.LOCALSTATEDIR + "/lib/ganeti"
-LOCK_DIR = _autoconf.LOCALSTATEDIR + "/lock"
-LOG_DIR = _autoconf.LOCALSTATEDIR + "/log/ganeti"
-RUN_DIR = _autoconf.LOCALSTATEDIR + "/run/ganeti"
+DATA_DIR = LOCALSTATEDIR + "/lib/ganeti"
+LOCK_DIR = LOCALSTATEDIR + "/lock"
+LOG_DIR = LOCALSTATEDIR + "/log/ganeti"
+RUN_DIR = LOCALSTATEDIR + "/run/ganeti"
#: Script to configure master IP address
DEFAULT_MASTER_SETUP_SCRIPT = TOOLSDIR + "/master-ip-setup"
diff --git a/lib/rpc.py b/lib/rpc.py
index 2d7d28b..7959b8c 100644
--- a/lib/rpc.py
+++ b/lib/rpc.py
@@ -48,6 +48,7 @@ from ganeti import runtime
from ganeti import compat
from ganeti import rpc_defs
from ganeti import pathutils
+from ganeti import vcluster
# Special module generated at build time
from ganeti import _generated_rpc
@@ -524,7 +525,9 @@ def _PrepareFileUpload(getents_fn, filename):
getents = getents_fn()
- return [filename, data, st.st_mode, getents.LookupUid(st.st_uid),
+ virt_filename = vcluster.MakeVirtualPath(filename)
+
+ return [virt_filename, data, st.st_mode, getents.LookupUid(st.st_uid),
getents.LookupGid(st.st_gid), st.st_atime, st.st_mtime]
diff --git a/lib/ssh.py b/lib/ssh.py
index ad42f95..1ecff45 100644
--- a/lib/ssh.py
+++ b/lib/ssh.py
@@ -33,6 +33,7 @@ from ganeti import errors
from ganeti import constants
from ganeti import netutils
from ganeti import pathutils
+from ganeti import vcluster
def FormatParamikoFingerprint(fingerprint):
@@ -184,7 +185,17 @@ class SshRunner:
quiet=quiet))
if tty:
argv.extend(["-t", "-t"])
- argv.extend(["%s@%s" % (user, hostname), command])
+
+ argv.append("%s@%s" % (user, hostname))
+
+ # Insert variables for virtual nodes
+ argv.extend("export %s=%s;" %
+ (utils.ShellQuote(name), utils.ShellQuote(value))
+ for (name, value) in
+ vcluster.EnvironmentForHost(hostname).items())
+
+ argv.append(command)
+
return argv
def Run(self, *args, **kwargs):
@@ -225,7 +236,7 @@ class SshRunner:
if netutils.IP6Address.IsValid(node):
node = netutils.FormatAddress((node, None))
- command.append("%s:%s" % (node, filename))
+ command.append("%s:%s" % (node, vcluster.ExchangeNodeRoot(node, filename)))
result = utils.RunCmd(command)
@@ -255,7 +266,12 @@ class SshRunner:
- detail: string with details
"""
- retval = self.Run(node, "root", "hostname --fqdn", quiet=False)
+ cmd = ("if test -z \"$GANETI_HOSTNAME\"; then"
+ " hostname --fqdn;"
+ "else"
+ " echo \"$GANETI_HOSTNAME\";"
+ "fi")
+ retval = self.Run(node, "root", cmd, quiet=False)
if retval.failed:
msg = "ssh problem"
--
1.7.6