Commit 21c2612d authored by Guido Trotter's avatar Guido Trotter
Browse files

Merge branch 'stable-2.9'



* stable-2.9:
  Update NEWS and version for Ganeti 2.7.1
  Add hvparam to disable VNET_HDR on tap devices
  daemon-util: pass --oknodo at rotate_logs
  Fix another missing renaming
  Add logrotate example
  daemon-util: provide rotate_logs and rotate_all_logs actions
  Fix usage of mapping from disk templates to storage types
  Rename VALID_STORAGE_TYPES to STORAGE_TYPES
  Unit tests for constants consistency
  Rename disk_template/storage_type map + cleanup
  Move space reporting constant to constants.py
  Update hroller manpage
  Update NEWS file wrt to file storage dir
  Update man page of gnt-cluster regarding file-storage-dir
  gnt-cluster {init, modify} --file-storage-dir
  Always return tuples in Expand*Name
  Prepare QA for shared file storage
  Fix permission errors for split users
  Make RAPI export device names and UUIDs
Signed-off-by: default avatarGuido Trotter <ultrotter@google.com>
Reviewed-by: default avatarThomas Thrainer <thomasth@google.com>
parents e408eb8a 17cda747
......@@ -68,6 +68,7 @@
/doc/examples/bash_completion-debug
/doc/examples/ganeti.cron
/doc/examples/ganeti.initd
/doc/examples/ganeti.logrotate
/doc/examples/ganeti-kvm-poweroff.initd
/doc/examples/ganeti-master-role.ocf
/doc/examples/ganeti-node-role.ocf
......
......@@ -255,6 +255,7 @@ BUILT_EXAMPLES = \
doc/examples/ganeti-kvm-poweroff.initd \
doc/examples/ganeti.cron \
doc/examples/ganeti.initd \
doc/examples/ganeti.logrotate \
doc/examples/ganeti-master-role.ocf \
doc/examples/ganeti-node-role.ocf \
doc/examples/gnt-config-backup \
......@@ -1231,6 +1232,8 @@ python_tests = \
test/py/ganeti.client.gnt_instance_unittest.py \
test/py/ganeti.client.gnt_job_unittest.py \
test/py/ganeti.cmdlib_unittest.py \
test/py/ganeti.cmdlib.cluster_unittest.py \
test/py/ganeti.cmdlib.instance_storage_unittest.py \
test/py/ganeti.compat_unittest.py \
test/py/ganeti.confd.client_unittest.py \
test/py/ganeti.config_unittest.py \
......
......@@ -37,7 +37,7 @@ Version 2.9.0 beta1
modification.
- The default directory for file storage is not anymore specified at
configure time, but taken from the cluster's configuration. It can be
set at cluster initialization with '--file-storage-dir'.
set at cluster initialization and modification with '--file-storage-dir'.
- Cluster verification now includes stricter checks regarding the
default file storage dir. It now checks that the file storage
directory is explicitely allowed in the 'file-storage-paths' file and
......@@ -116,6 +116,20 @@ For Python:
- ``yaml`` library (only for running the QA).
Version 2.7.1
-------------
*(Released Thu, 25 Jul 2013)*
- Add logrotate functionality in daemon-util
- Add logrotate example file
- Add missing fields to network queries over rapi
- Fix network object timestamps
- Add support for querying network timestamps
- Fix a typo in the example crontab
- Fix a documentation typo
Version 2.7.0
-------------
......
......@@ -324,6 +324,34 @@ stop_all() {
done
}
# SIGHUP a process to force re-opening its logfiles
rotate_logs() {
if [[ "$#" -lt 1 ]]; then
echo 'Missing daemon name.' >&2
return 1
fi
local name="$1"; shift
local pidfile=$(_daemon_pidfile $name)
local daemonexec=$(_daemon_executable $name)
if type -p start-stop-daemon >/dev/null; then
start-stop-daemon --stop --signal HUP --quiet \
--oknodo --pidfile $pidfile
else
_ignore_error killproc \
-p $pidfile \
$daemonexec -HUP
fi
}
# SIGHUP all processes
rotate_all_logs() {
for i in $(list_stop_daemons); do
rotate_logs $i
done
}
# Reloads the SSH keys
reload_ssh_keys() {
@RPL_SSH_INITD_SCRIPT@ restart
......
......@@ -100,6 +100,10 @@ PKGLIBDIR="$(echo @PKGLIBDIR@ | $SED)"
install -D --mode=0755 doc/examples/ganeti.initd \
"$TXD/$SYSCONFDIR/init.d/ganeti"
[ -f doc/examples/ganeti.logrotate ] && \
install -D --mode=0755 doc/examples/ganeti.logrotate \
"$TXD/$SYSCONFDIR/logrotate.d/ganeti"
[ -f doc/examples/ganeti-master-role.ocf ] && \
install -D --mode=0755 doc/examples/ganeti-master-role.ocf \
"$TXD/$LIBDIR/ocf/resource.d/ganeti/ganeti-master-role"
......
/var/log/ganeti/*.log {
weekly
missingok
rotate 52
notifempty
compress
delaycompress
create 640 root root
sharedscripts
postrotate
@PKGLIBDIR@/daemon-util rotate-all-logs
endscript
}
......@@ -582,7 +582,10 @@ distribution's startup scripts, for example in Debian::
In order to automatically restart failed instances, you need to setup a
cron job run the *ganeti-watcher* command. A sample cron file is
provided in the source at ``doc/examples/ganeti.cron`` and you can copy
that (eventually altering the path) to ``/etc/cron.d/ganeti``.
that (eventually altering the path) to ``/etc/cron.d/ganeti``. Finally,
a sample logrotate snippet is provided in the source at
``doc/examples/ganeti.logrotate`` and you can copy it to
``/etc/logrotate.d/ganeti`` to have Ganeti's logs rotated automatically.
What gets installed
~~~~~~~~~~~~~~~~~~~
......
......@@ -2112,9 +2112,9 @@ Manages storage units on the node.
FIXME: enable ".. pyassert::" again when all storage types are
implemented::
constants.VALID_STORAGE_TYPES == set([constants.ST_FILE,
constants.ST_LVM_PV,
constants.ST_LVM_VG])
constants.STORAGE_TYPES == set([constants.ST_FILE,
constants.ST_LVM_PV,
constants.ST_LVM_VG])
Requests a list of storage units on a node. Requires the parameters
``storage_type`` (one of :pyeval:`constants.ST_FILE`,
......
......@@ -30,6 +30,7 @@ import logging
import time
import tempfile
from ganeti.cmdlib import cluster
from ganeti import rpc
from ganeti import ssh
from ganeti import utils
......@@ -41,6 +42,7 @@ from ganeti import ssconf
from ganeti import serializer
from ganeti import hypervisor
from ganeti.storage import drbd
from ganeti.storage import filestorage
from ganeti import netutils
from ganeti import luxi
from ganeti import jstore
......@@ -334,17 +336,6 @@ def RunNodeSetupCmd(cluster_name, node, basecmd, debug, verbose,
_WaitForSshDaemon(node, netutils.GetDaemonPort(constants.SSH), family)
def _PrepareFileStorage(enabled_disk_templates, file_storage_dir):
"""Checks if file storage is enabled and inits the dir.
"""
if utils.storage.IsFileStorageEnabled(enabled_disk_templates):
file_storage_dir = _InitFileStorageDir(file_storage_dir)
else:
file_storage_dir = ""
return file_storage_dir
def _InitFileStorageDir(file_storage_dir):
"""Initialize if needed the file storage.
......@@ -372,10 +363,37 @@ def _InitFileStorageDir(file_storage_dir):
" a directory." % file_storage_dir,
errors.ECODE_ENVIRON)
# FIXME: check here if the file_storage_dir is in the set of allowed dirs
return file_storage_dir
def _PrepareFileStorage(
enabled_disk_templates, file_storage_dir, init_fn=_InitFileStorageDir,
acceptance_fn=None):
"""Checks if file storage is enabled and inits the dir.
"""
if file_storage_dir is None:
file_storage_dir = pathutils.DEFAULT_FILE_STORAGE_DIR
if not acceptance_fn:
acceptance_fn = \
lambda path: filestorage.CheckFileStoragePathAcceptance(
path, exact_match_ok=True)
cluster.CheckFileStoragePathVsEnabledDiskTemplates(
logging.warning, file_storage_dir, enabled_disk_templates)
file_storage_enabled = constants.DT_FILE in enabled_disk_templates
if file_storage_enabled:
try:
acceptance_fn(file_storage_dir)
except errors.FileStoragePathError as e:
raise errors.OpPrereqError(str(e))
result_file_storage_dir = init_fn(file_storage_dir)
else:
result_file_storage_dir = file_storage_dir
return result_file_storage_dir
def _InitCheckEnabledDiskTemplates(enabled_disk_templates):
"""Checks the sanity of the enabled disk templates.
......
......@@ -1300,7 +1300,7 @@ GLOBAL_FILEDIR_OPT = cli_option("--file-storage-dir", dest="file_storage_dir",
"wide) for storing the file-based disks [%s]" %
pathutils.DEFAULT_FILE_STORAGE_DIR,
metavar="DIR",
default=pathutils.DEFAULT_FILE_STORAGE_DIR)
default=None)
GLOBAL_SHARED_FILEDIR_OPT = cli_option(
"--shared-file-storage-dir",
......
......@@ -1003,7 +1003,8 @@ def SetClusterParams(opts, args):
opts.ipolicy_disk_templates is not None or
opts.ipolicy_vcpu_ratio is not None or
opts.ipolicy_spindle_ratio is not None or
opts.modify_etc_hosts is not None):
opts.modify_etc_hosts is not None or
opts.file_storage_dir is not None):
ToStderr("Please give at least one of the parameters.")
return 1
......@@ -1127,6 +1128,7 @@ def SetClusterParams(opts, args):
disk_state=disk_state,
enabled_disk_templates=enabled_disk_templates,
force=opts.force,
file_storage_dir=opts.file_storage_dir,
)
SubmitOrSend(op, opts)
return 0
......@@ -1633,7 +1635,7 @@ commands = {
NODE_PARAMS_OPT, USE_EXTERNAL_MIP_SCRIPT, DISK_PARAMS_OPT, HV_STATE_OPT,
DISK_STATE_OPT] + SUBMIT_OPTS +
[ENABLED_DISK_TEMPLATES_OPT, IPOLICY_STD_SPECS_OPT, MODIFY_ETCHOSTS_OPT] +
INSTANCE_POLICY_OPTS,
INSTANCE_POLICY_OPTS + [GLOBAL_FILEDIR_OPT],
"[opts...]",
"Alters the parameters of the cluster"),
"renew-crypto": (
......
......@@ -609,6 +609,35 @@ def _ValidateNetmask(cfg, netmask):
(netmask), errors.ECODE_INVAL)
def CheckFileStoragePathVsEnabledDiskTemplates(
logging_warn_fn, file_storage_dir, enabled_disk_templates):
"""Checks whether the given file storage directory is acceptable.
@type logging_warn_fn: function
@param logging_warn_fn: function which accepts a string and logs it
@type file_storage_dir: string
@param file_storage_dir: the directory to be used for file-based instances
@type enabled_disk_templates: list of string
@param enabled_disk_templates: the list of enabled disk templates
Note: This function is public, because it is also used in bootstrap.py.
"""
file_storage_enabled = constants.DT_FILE in enabled_disk_templates
if file_storage_dir is not None:
if file_storage_dir == "":
if file_storage_enabled:
raise errors.OpPrereqError("Unsetting the file storage directory"
" while having file storage enabled"
" is not permitted.")
else:
if not file_storage_enabled:
logging_warn_fn("Specified a file storage directory, although file"
" storage is not enabled.")
else:
raise errors.ProgrammerError("Received file storage dir with value"
" 'None'.")
class LUClusterSetParams(LogicalUnit):
"""Change the parameters of the cluster.
......@@ -752,6 +781,10 @@ class LUClusterSetParams(LogicalUnit):
self._CheckVgName(vm_capable_node_uuids, enabled_disk_templates,
new_enabled_disk_templates)
if self.op.file_storage_dir is not None:
CheckFileStoragePathVsEnabledDiskTemplates(
self.LogWarning, self.op.file_storage_dir, enabled_disk_templates)
if self.op.drbd_helper:
# checks given drbd helper on all nodes
helpers = self.rpc.call_drbd_helper(node_uuids)
......@@ -998,6 +1031,17 @@ class LUClusterSetParams(LogicalUnit):
raise errors.OpPrereqError("Please specify a volume group when"
" enabling lvm-based disk-templates.")
def _SetFileStorageDir(self, feedback_fn):
"""Set the file storage directory.
"""
if self.op.file_storage_dir is not None:
if self.cluster.file_storage_dir == self.op.file_storage_dir:
feedback_fn("Global file storage dir already set to value '%s'"
% self.cluster.file_storage_dir)
else:
self.cluster.file_storage_dir = self.op.file_storage_dir
def Exec(self, feedback_fn):
"""Change the parameters of the cluster.
......@@ -1007,6 +1051,7 @@ class LUClusterSetParams(LogicalUnit):
list(set(self.op.enabled_disk_templates))
self._SetVgName(feedback_fn)
self._SetFileStorageDir(feedback_fn)
if self.op.drbd_helper is not None:
if not constants.DT_DRBD8 in self.cluster.enabled_disk_templates:
......
......@@ -58,11 +58,11 @@ def _ExpandItemName(expand_fn, name, kind):
@raise errors.OpPrereqError: if the item is not found
"""
full_name = expand_fn(name)
if full_name is None:
(uuid, full_name) = expand_fn(name)
if uuid is None or full_name is None:
raise errors.OpPrereqError("%s '%s' not known" % (kind, name),
errors.ECODE_NOENT)
return full_name
return (uuid, full_name)
def ExpandInstanceUuidAndName(cfg, expected_uuid, name):
......@@ -1101,7 +1101,7 @@ def CheckStorageTypeEnabled(cluster, storage_type):
"""
assert storage_type is not None
assert storage_type in constants.VALID_STORAGE_TYPES
assert storage_type in constants.STORAGE_TYPES
# special case for lvm-pv, because it cannot be enabled
# via disk templates
if storage_type == constants.ST_LVM_PV:
......
......@@ -1617,7 +1617,7 @@ class ConfigWriter:
inst = (filter(lambda n: n.name == expanded_name, all_insts)[0])
return (inst.uuid, inst.name)
else:
return None
return (None, None)
def _UnlockedGetInstanceInfo(self, inst_uuid):
"""Returns information about an instance.
......@@ -1843,7 +1843,7 @@ class ConfigWriter:
node = (filter(lambda n: n.name == expanded_name, all_nodes)[0])
return (node.uuid, node.name)
else:
return None
return (None, None)
def _UnlockedGetNodeInfo(self, node_uuid):
"""Get the configuration of a node, as stored in the config.
......
......@@ -191,7 +191,7 @@ LAST_DRBD_PORT = 14999
DAEMONS_LOGBASE = {
NODED: "node-daemon",
CONFD: "conf-daemon",
LUXID: "query-daemon",
LUXID: "luxi-daemon",
RAPI: "rapi-daemon",
MASTERD: "master-daemon",
MOND: "monitoring-daemon",
......@@ -386,7 +386,7 @@ ST_LVM_PV = "lvm-pv"
ST_LVM_VG = "lvm-vg"
ST_RADOS = "rados"
VALID_STORAGE_TYPES = compat.UniqueFrozenset([
STORAGE_TYPES = compat.UniqueFrozenset([
ST_BLOCK,
ST_DISKLESS,
ST_EXT,
......@@ -396,6 +396,10 @@ VALID_STORAGE_TYPES = compat.UniqueFrozenset([
ST_RADOS,
])
# the set of storage types for which storage reporting is available
# FIXME: Remove this, once storage reporting is available for all types.
STS_REPORT = compat.UniqueFrozenset([ST_FILE, ST_LVM_PV, ST_LVM_VG])
# Storage fields
# first two are valid in LU context only, not passed to backend
SF_NODE = "node"
......@@ -455,14 +459,14 @@ DT_SHARED_FILE = "sharedfile"
# This only happens on an upgrade from a version of Ganeti that did not
# support the 'enabled_disk_templates' so far.
DISK_TEMPLATE_PREFERENCE = [
DT_BLOCK,
DT_DISKLESS,
DT_DRBD8,
DT_PLAIN,
DT_EXT,
DT_FILE,
DT_SHARED_FILE,
DT_PLAIN,
DT_RBD,
DT_BLOCK,
DT_DISKLESS,
DT_EXT
DT_SHARED_FILE,
]
DISK_TEMPLATES = compat.UniqueFrozenset([
......@@ -483,7 +487,7 @@ DEFAULT_ENABLED_DISK_TEMPLATES = [
]
# mapping of disk templates to storage types
DISK_TEMPLATES_STORAGE_TYPE = {
MAP_DISK_TEMPLATE_STORAGE_TYPE = {
DT_BLOCK: ST_BLOCK,
DT_DISKLESS: ST_DISKLESS,
DT_DRBD8: ST_LVM_VG,
......@@ -958,6 +962,7 @@ HV_KVM_PATH = "kvm_path"
HV_VIF_TYPE = "vif_type"
HV_VIF_SCRIPT = "vif_script"
HV_XEN_CMD = "xen_cmd"
HV_VNET_HDR = "vnet_hdr"
HVS_PARAMETER_TYPES = {
......@@ -1030,6 +1035,7 @@ HVS_PARAMETER_TYPES = {
HV_VIF_TYPE: VTYPE_STRING,
HV_VIF_SCRIPT: VTYPE_STRING,
HV_XEN_CMD: VTYPE_STRING,
HV_VNET_HDR: VTYPE_BOOL,
}
HVS_PARAMETERS = frozenset(HVS_PARAMETER_TYPES.keys())
......@@ -2159,6 +2165,7 @@ HVC_DEFAULTS = {
HV_VGA: "",
HV_KVM_EXTRA: "",
HV_KVM_MACHINE_VERSION: "",
HV_VNET_HDR: True,
},
HT_FAKE: {
HV_MIGRATION_MODE: HT_MIGRATION_LIVE,
......
......@@ -529,6 +529,7 @@ class KVMHypervisor(hv_base.BaseHypervisor):
constants.HV_VGA: hv_base.NO_CHECK,
constants.HV_KVM_EXTRA: hv_base.NO_CHECK,
constants.HV_KVM_MACHINE_VERSION: hv_base.NO_CHECK,
constants.HV_VNET_HDR: hv_base.NO_CHECK,
}
_VIRTIO = "virtio"
......@@ -1533,7 +1534,7 @@ class KVMHypervisor(hv_base.BaseHypervisor):
devlist = self._GetKVMOutput(kvm_path, self._KVMOPT_DEVICELIST)
if self._NEW_VIRTIO_RE.search(devlist):
nic_model = self._VIRTIO_NET_PCI
vnet_hdr = True
vnet_hdr = up_hvp[constants.HV_VNET_HDR]
except errors.HypervisorError, _:
# Older versions of kvm don't support DEVICE_LIST, but they don't
# have new virtio syntax either.
......
......@@ -360,7 +360,7 @@ def _CheckStorageType(storage_type):
"""Ensure a given storage type is valid.
"""
if storage_type not in constants.VALID_STORAGE_TYPES:
if storage_type not in constants.STORAGE_TYPES:
raise errors.OpPrereqError("Unknown storage type: %s" % storage_type,
errors.ECODE_INVAL)
return True
......@@ -963,6 +963,8 @@ class OpClusterSetParams(OpCode):
"List of enabled disk templates"),
("modify_etc_hosts", None, ht.TMaybeBool,
"Whether the cluster can modify and keep in sync the /etc/hosts files"),
("file_storage_dir", None, ht.TMaybeString,
"Default directory for storing file-backed disks"),
]
OP_RESULT = ht.TNone
......
......@@ -71,10 +71,11 @@ _COMMON_FIELDS = ["ctime", "mtime", "uuid", "serial_no", "tags"]
I_FIELDS = ["name", "admin_state", "os",
"pnode", "snodes",
"disk_template",
"nic.ips", "nic.macs", "nic.modes",
"nic.ips", "nic.macs", "nic.modes", "nic.uuids", "nic.names",
"nic.links", "nic.networks", "nic.networks.names", "nic.bridges",
"network_port",
"disk.sizes", "disk.spindles", "disk_usage",
"disk.sizes", "disk.spindles", "disk_usage", "disk.uuids",
"disk.names",
"beparams", "hvparams",
"oper_state", "oper_ram", "oper_vcpus", "status",
"custom_hvparams", "custom_beparams", "custom_nicparams",
......
......@@ -104,6 +104,9 @@ class GetentResolver:
self.noded_uid = GetUid(constants.NODED_USER, _getpwnam)
self.noded_gid = GetGid(constants.NODED_GROUP, _getgrnam)
self.mond_uid = GetUid(constants.MOND_USER, _getpwnam)
self.mond_gid = GetGid(constants.MOND_GROUP, _getgrnam)
# Misc Ganeti groups
self.daemons_gid = GetGid(constants.DAEMONS_GROUP, _getgrnam)
self.admin_gid = GetGid(constants.ADMIN_GROUP, _getgrnam)
......@@ -114,6 +117,7 @@ class GetentResolver:
self.luxid_uid: constants.LUXID_USER,
self.rapi_uid: constants.RAPI_USER,
self.noded_uid: constants.NODED_USER,
self.mond_uid: constants.MOND_USER,
}
self._gid2group = {
......@@ -122,6 +126,7 @@ class GetentResolver:
self.luxid_gid: constants.LUXID_GROUP,
self.rapi_gid: constants.RAPI_GROUP,
self.noded_gid: constants.NODED_GROUP,
self.mond_gid: constants.MOND_GROUP,
self.daemons_gid: constants.DAEMONS_GROUP,
self.admin_gid: constants.ADMIN_GROUP,
}
......
......@@ -122,7 +122,9 @@ def GetPaths():
masterd_log = constants.DAEMONS_LOGFILES[constants.MASTERD]
noded_log = constants.DAEMONS_LOGFILES[constants.NODED]
confd_log = constants.DAEMONS_LOGFILES[constants.CONFD]
luxid_log = constants.DAEMONS_LOGFILES[constants.LUXID]
rapi_log = constants.DAEMONS_LOGFILES[constants.RAPI]
mond_log = constants.DAEMONS_LOGFILES[constants.MOND]
rapi_dir = os.path.join(pathutils.DATA_DIR, "rapi")
cleaner_log_dir = os.path.join(pathutils.LOG_DIR, "cleaner")
......@@ -194,8 +196,10 @@ def GetPaths():
(pathutils.LOG_DIR, DIR, 0770, getent.masterd_uid, getent.daemons_gid),
(masterd_log, FILE, 0600, getent.masterd_uid, getent.masterd_gid, False),
(confd_log, FILE, 0600, getent.confd_uid, getent.masterd_gid, False),
(luxid_log, FILE, 0600, getent.luxid_uid, getent.masterd_gid, False),
(noded_log, FILE, 0600, getent.noded_uid, getent.masterd_gid, False),
(rapi_log, FILE, 0600, getent.rapi_uid, getent.masterd_gid, False),
(mond_log, FILE, 0600, getent.mond_uid, getent.masterd_gid, False),
(pathutils.LOG_OS_DIR, DIR, 0750, getent.noded_uid, getent.daemons_gid),
(pathutils.LOG_XEN_DIR, DIR, 0750, getent.noded_uid, getent.daemons_gid),
(cleaner_log_dir, DIR, 0750, getent.noded_uid, getent.noded_gid),
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment