Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
index 48f74fdbe..5e2889513 100644
--- a/doc/man/Makefile.am
+++ b/doc/man/Makefile.am
@@ -1,173 +1,174 @@
#
# doc: Linux-HA resource agents
#
# Copyright (C) 2009 Florian Haas
#
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
MAINTAINERCLEANFILES = Makefile.in
EXTRA_DIST = $(doc_DATA) $(REFENTRY_STYLESHEET) \
mkappendix.sh ralist.sh
CLEANFILES = $(man_MANS) $(xmlfiles) metadata-*.xml
STYLESHEET_PREFIX ?= http://docbook.sourceforge.net/release/xsl/current
MANPAGES_STYLESHEET ?= $(STYLESHEET_PREFIX)/manpages/docbook.xsl
HTML_STYLESHEET ?= $(STYLESHEET_PREFIX)/xhtml/docbook.xsl
FO_STYLESHEET ?= $(STYLESHEET_PREFIX)/fo/docbook.xsl
REFENTRY_STYLESHEET ?= ra2refentry.xsl
XSLTPROC_OPTIONS ?= --xinclude
XSLTPROC_MANPAGES_OPTIONS ?= $(XSLTPROC_OPTIONS)
XSLTPROC_HTML_OPTIONS ?= $(XSLTPROC_OPTIONS)
XSLTPROC_FO_OPTIONS ?= $(XSLTPROC_OPTIONS)
radir = $(top_srcdir)/heartbeat
# OCF_ROOT=. is necessary due to a sanity check in ocf-shellfuncs
# (which tests whether $OCF_ROOT points to a directory
metadata-%.xml: $(radir)/%
OCF_ROOT=. OCF_FUNCTIONS_DIR=$(radir) $< meta-data > $@
metadata-IPv6addr.xml: ../../heartbeat/IPv6addr
OCF_ROOT=. OCF_FUNCTIONS_DIR=$(radir) $< meta-data > $@
# Please note: we can't name the man pages
# ocf:heartbeat:<name>. Believe me, I've tried. It looks like it
# works, but then it doesn't. While make can deal correctly with
# colons in target names (when properly escaped), it royally messes up
# when it is deals with _dependencies_ that contain colons. See Bug
# 12126 on savannah.gnu.org. But, maybe it gets fixed soon, it was
# first reported in 1995 and added to Savannah in in 2005...
if BUILD_DOC
man_MANS = ocf_heartbeat_AoEtarget.7 \
ocf_heartbeat_AudibleAlarm.7 \
ocf_heartbeat_ClusterMon.7 \
ocf_heartbeat_CTDB.7 \
ocf_heartbeat_Delay.7 \
ocf_heartbeat_Dummy.7 \
ocf_heartbeat_EvmsSCC.7 \
ocf_heartbeat_Evmsd.7 \
ocf_heartbeat_Filesystem.7 \
ocf_heartbeat_ICP.7 \
ocf_heartbeat_IPaddr.7 \
ocf_heartbeat_IPaddr2.7 \
ocf_heartbeat_IPsrcaddr.7 \
ocf_heartbeat_LVM.7 \
ocf_heartbeat_LinuxSCSI.7 \
ocf_heartbeat_MailTo.7 \
ocf_heartbeat_ManageRAID.7 \
ocf_heartbeat_ManageVE.7 \
ocf_heartbeat_Pure-FTPd.7 \
ocf_heartbeat_Raid1.7 \
ocf_heartbeat_Route.7 \
ocf_heartbeat_SAPDatabase.7 \
ocf_heartbeat_SAPInstance.7 \
ocf_heartbeat_SendArp.7 \
ocf_heartbeat_ServeRAID.7 \
ocf_heartbeat_SphinxSearchDaemon.7 \
ocf_heartbeat_Squid.7 \
ocf_heartbeat_Stateful.7 \
ocf_heartbeat_SysInfo.7 \
ocf_heartbeat_VIPArip.7 \
ocf_heartbeat_VirtualDomain.7 \
ocf_heartbeat_WAS.7 \
ocf_heartbeat_WAS6.7 \
ocf_heartbeat_WinPopup.7 \
ocf_heartbeat_Xen.7 \
ocf_heartbeat_Xinetd.7 \
ocf_heartbeat_anything.7 \
ocf_heartbeat_apache.7 \
ocf_heartbeat_asterisk.7 \
ocf_heartbeat_clvm.7 \
ocf_heartbeat_conntrackd.7 \
ocf_heartbeat_db2.7 \
ocf_heartbeat_dhcpd.7 \
ocf_heartbeat_docker.7 \
ocf_heartbeat_dnsupdate.7 \
ocf_heartbeat_eDir88.7 \
ocf_heartbeat_ethmonitor.7 \
ocf_heartbeat_exportfs.7 \
ocf_heartbeat_fio.7 \
ocf_heartbeat_galera.7 \
ocf_heartbeat_iSCSILogicalUnit.7 \
ocf_heartbeat_iSCSITarget.7 \
ocf_heartbeat_iface-bridge.7 \
ocf_heartbeat_iface-vlan.7 \
ocf_heartbeat_ids.7 \
ocf_heartbeat_iscsi.7 \
ocf_heartbeat_jboss.7 \
ocf_heartbeat_kamailio.7 \
ocf_heartbeat_lxc.7 \
ocf_heartbeat_mysql.7 \
ocf_heartbeat_mysql-proxy.7 \
ocf_heartbeat_named.7 \
ocf_heartbeat_nfsnotify.7 \
ocf_heartbeat_nfsserver.7 \
ocf_heartbeat_nginx.7 \
ocf_heartbeat_oracle.7 \
ocf_heartbeat_oralsnr.7 \
ocf_heartbeat_pgsql.7 \
ocf_heartbeat_pingd.7 \
ocf_heartbeat_portblock.7 \
ocf_heartbeat_postfix.7 \
ocf_heartbeat_pound.7 \
ocf_heartbeat_proftpd.7 \
+ ocf_heartbeat_rabbitmq-cluster.7 \
ocf_heartbeat_redis.7 \
ocf_heartbeat_rsyncd.7 \
ocf_heartbeat_rsyslog.7 \
ocf_heartbeat_scsi2reservation.7 \
ocf_heartbeat_sfex.7 \
ocf_heartbeat_slapd.7 \
ocf_heartbeat_sg_persist.7 \
ocf_heartbeat_symlink.7 \
ocf_heartbeat_syslog-ng.7 \
ocf_heartbeat_tomcat.7 \
ocf_heartbeat_varnish.7 \
ocf_heartbeat_vmware.7 \
ocf_heartbeat_zabbixserver.7
if USE_IPV6ADDR_AGENT
man_MANS += ocf_heartbeat_IPv6addr.7
endif
xmlfiles = $(man_MANS:.7=.xml)
%.1 %.5 %.7 %.8: %.xml
$(XSLTPROC) \
$(XSLTPROC_MANPAGES_OPTIONS) \
$(MANPAGES_STYLESHEET) $<
ocf_heartbeat_%.xml: metadata-%.xml $(srcdir)/$(REFENTRY_STYLESHEET)
$(XSLTPROC) --novalid \
--stringparam package $(PACKAGE_NAME) \
--stringparam version $(VERSION) \
--output $@ \
$(srcdir)/$(REFENTRY_STYLESHEET) $<
ocf_resource_agents.xml: $(xmlfiles) mkappendix.sh
./mkappendix.sh $(xmlfiles) > $@
%.html: %.xml
$(XSLTPROC) \
$(XSLTPROC_HTML_OPTIONS) \
--output $@ \
$(HTML_STYLESHEET) $<
xml: ocf_resource_agents.xml
endif
diff --git a/heartbeat/Makefile.am b/heartbeat/Makefile.am
index 9edf0a1ab..73ce6b6d0 100644
--- a/heartbeat/Makefile.am
+++ b/heartbeat/Makefile.am
@@ -1,156 +1,157 @@
# Makefile.am for OCF RAs
#
# Author: Sun Jing Dong
# Copyright (C) 2004 IBM
#
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
MAINTAINERCLEANFILES = Makefile.in
EXTRA_DIST = $(ocf_SCRIPTS) $(ocfcommon_DATA) \
$(common_DATA) $(hb_DATA) $(dtd_DATA) \
README
AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/linux-ha
halibdir = $(libexecdir)/heartbeat
ocfdir = $(OCF_RA_DIR_PREFIX)/heartbeat
dtddir = $(datadir)/$(PACKAGE_NAME)
dtd_DATA = ra-api-1.dtd
if USE_IPV6ADDR_AGENT
ocf_PROGRAMS = IPv6addr
else
ocf_PROGRAMS =
endif
if IPV6ADDR_COMPATIBLE
halib_PROGRAMS = send_ua
else
halib_PROGRAMS =
endif
IPv6addr_SOURCES = IPv6addr.c IPv6addr_utils.c
send_ua_SOURCES = send_ua.c IPv6addr_utils.c
IPv6addr_LDADD = -lplumb $(LIBNETLIBS)
send_ua_LDADD = $(LIBNETLIBS)
ocf_SCRIPTS = ClusterMon \
CTDB \
Dummy \
IPaddr \
IPaddr2 \
anything \
AoEtarget \
apache \
asterisk \
nginx \
AudibleAlarm \
clvm \
conntrackd \
db2 \
dhcpd \
Delay \
dnsupdate \
docker \
eDir88 \
EvmsSCC \
Evmsd \
ethmonitor \
exportfs \
Filesystem \
fio \
galera \
ids \
iscsi \
ICP \
IPsrcaddr \
iSCSITarget \
iSCSILogicalUnit \
iface-bridge \
iface-vlan \
jboss \
kamailio \
LinuxSCSI \
LVM \
lxc \
MailTo \
ManageRAID \
ManageVE \
mysql \
mysql-proxy \
named \
nfsnotify \
nfsserver \
oracle \
oralsnr \
pingd \
portblock \
postfix \
pound \
pgsql \
proftpd \
Pure-FTPd \
+ rabbitmq-cluster \
Raid1 \
redis \
Route \
rsyncd \
rsyslog \
SAPDatabase \
SAPInstance \
SendArp \
ServeRAID \
slapd \
SphinxSearchDaemon \
Squid \
Stateful \
SysInfo \
scsi2reservation \
sfex \
sg_persist \
symlink \
syslog-ng \
tomcat \
VIPArip \
VirtualDomain \
varnish \
vmware \
WAS \
WAS6 \
WinPopup \
Xen \
Xinetd \
zabbixserver
ocfcommondir = $(OCF_LIB_DIR_PREFIX)/heartbeat
ocfcommon_DATA = ocf-shellfuncs \
ocf-binaries \
ocf-directories \
ocf-returncodes \
ocf-rarun \
apache-conf.sh \
http-mon.sh \
sapdb-nosha.sh \
sapdb.sh \
ora-common.sh \
mysql-common.sh \
findif.sh
# Legacy locations
hbdir = $(sysconfdir)/ha.d
hb_DATA = shellfuncs
diff --git a/heartbeat/rabbitmq-cluster b/heartbeat/rabbitmq-cluster
new file mode 100755
index 000000000..b9dcfc350
--- /dev/null
+++ b/heartbeat/rabbitmq-cluster
@@ -0,0 +1,370 @@
+#!/bin/sh
+#
+# Copyright (c) 2014 David Vossel <dvossel@redhat.com>
+# All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like. Any license provided herein, whether implied or
+# otherwise, applies only to this software file. Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+RMQ_SERVER=/usr/sbin/rabbitmq-server
+RMQ_CTL=/usr/sbin/rabbitmqctl
+RMQ_DATA_DIR="/var/lib/rabbitmq/mnesia"
+RMQ_PID_DIR="/var/run/rabbitmq"
+RMQ_PID_FILE="/var/run/rabbitmq/rmq.pid"
+RMQ_LOG_DIR="/var/log/rabbitmq"
+NODENAME=$(ocf_local_nodename)
+
+RMQ_CRM_ATTR_COOKIE="rmq-node-attr-${OCF_RESOURCE_INSTANCE}"
+
+meta_data() {
+ cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="rabbitmq-cluster" version="0.9">
+<version>1.0</version>
+
+<longdesc lang="en">
+Starts cloned rabbitmq cluster instance
+</longdesc>
+<shortdesc lang="en">rabbitmq clustered</shortdesc>
+
+<parameters>
+<parameter name="set_policy" unique="1">
+<longdesc lang="en">
+Policy string to pass to 'rabbitmqctl set_policy' right after bootstrapping the first rabbitmq instance.
+</longdesc>
+<shortdesc lang="en">rabbitmqctl set_policy args</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start" timeout="100" />
+<action name="stop" timeout="90" />
+<action name="monitor" timeout="40" interval="10" depth="0" />
+<action name="meta-data" timeout="10" />
+<action name="validate-all" timeout="20" />
+</actions>
+</resource-agent>
+END
+}
+
+#######################################################################
+
+rmq_usage() {
+ cat <<END
+usage: $0 {start|stop|monitor|migrate_to|migrate_from|validate-all|meta-data}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+rmq_wipe_data()
+{
+ rm -rf $RMQ_DATA_DIR > /dev/null 2>&1
+}
+
+rmq_local_node()
+{
+
+ local node_name=$(rabbitmqctl status 2>&1 | sed -n -e "s/^.*[S|s]tatus of node \(.*\)\s.*$/\1/p" | tr -d "'")
+
+ if [ -z "$node_name" ]; then
+ node_name=$(cat /etc/rabbitmq/rabbitmq-env.conf 2>/dev/null | grep "\s*RABBITMQ_NODENAME=" | awk -F= '{print $2}')
+ fi
+
+ echo "$node_name"
+}
+
+rmq_join_list()
+{
+ cibadmin -Q 2>/dev/null | grep "$RMQ_CRM_ATTR_COOKIE" | sed -n -e "s/^.*value=.\(.*\)\".*$/\1/p"
+}
+
+rmq_write_nodename()
+{
+ local node_name=$(rmq_local_node)
+
+ if [ -z "$node_name" ]; then
+ ocf_log err "Failed to determine rabbitmq node name, exiting"
+ exit $OCF_ERR_GENERIC
+ fi
+
+ # store the pcmknode to rmq node mapping as an attribute
+ ${HA_SBIN_DIR}/crm_attribute -N $NODENAME -l reboot --name "$RMQ_CRM_ATTR_COOKIE" -v "$node_name"
+}
+
+rmq_delete_nodename()
+{
+ # remove node-name
+ ${HA_SBIN_DIR}/crm_attribute -N $NODENAME -l reboot --name "$RMQ_CRM_ATTR_COOKIE" -D
+}
+
+prepare_dir () {
+ if [ ! -d ${1} ] ; then
+ mkdir -p ${1}
+ chown -R rabbitmq:rabbitmq ${1}
+ chmod 755 ${1}
+ fi
+}
+
+remove_pid () {
+ rm -f ${RMQ_PID_FILE} > /dev/null 2>&1
+}
+
+rmq_monitor() {
+ local rc
+
+ $RMQ_CTL cluster_status > /dev/null 2>&1
+ rc=$?
+ case "$rc" in
+ 0)
+ ocf_log debug "RabbitMQ server is running normally"
+ rmq_write_nodename
+
+ return $OCF_SUCCESS
+ ;;
+ 2)
+ ocf_log info "RabbitMQ server is not running"
+ rmq_delete_nodename
+ return $OCF_NOT_RUNNING
+ ;;
+ *)
+ ocf_log err "Unexpected return code from '$RMQ_CTL cluster status' exit code: $rc"
+ rmq_delete_nodename
+ return $OCF_ERR_GENERIC
+ ;;
+ esac
+}
+
+rmq_init_and_wait()
+{
+ local rc
+
+ prepare_dir $RMQ_PID_DIR
+ prepare_dir $RMQ_LOG_DIR
+ remove_pid
+
+ # the server startup script uses this environment variable
+ export RABBITMQ_PID_FILE="$RMQ_PID_FILE"
+
+ setsid sh -c "$RMQ_SERVER > ${RMQ_LOG_DIR}/startup_log 2> ${RMQ_LOG_DIR}/startup_err" &
+
+ ocf_log info "Waiting for server to start"
+ $RMQ_CTL wait $RMQ_PID_FILE
+ rc=$?
+ if [ $rc -ne $OCF_SUCCESS ]; then
+ remove_pid
+ ocf_log info "rabbitmq-server start failed: $rc"
+ return $OCF_ERR_GENERIC
+ fi
+
+ rmq_monitor
+ return $?
+}
+
+rmq_set_policy()
+{
+ $RMQ_CTL set_policy $@ > /dev/null 2>&1
+}
+
+rmq_start_first()
+{
+ local rc
+
+ ocf_log info "Bootstrapping rabbitmq cluster"
+ rmq_wipe_data
+ rmq_init_and_wait
+ rc=$?
+
+ if [ $rc -eq 0 ]; then
+ rc=$OCF_SUCCESS
+ ocf_log info "cluster bootstrapped"
+
+ if [ -n "$OCF_RESKEY_set_policy" ]; then
+ # do not quote set_policy, we are passing in arguments
+ rmq_set_policy $OCF_RESKEY_set_policy > /dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ ocf_log err "Failed to set policy: $OCF_RESKEY_set_policy"
+ rc=$OCF_ERR_GENERIC
+ else
+ ocf_log info "Policy set: $OCF_RESKEY_set_policy"
+ fi
+ fi
+
+ else
+ ocf_log info "failed to bootstrap cluster. Check SELINUX policy"
+ rc=$OCF_ERR_GENERIC
+ fi
+
+ return $rc
+}
+
+rmq_join_existing()
+{
+ local join_list="$1"
+ local rc=$OCF_ERR_GENERIC
+
+ ocf_log info "Joining existing cluster with [ $(echo $join_list | tr '\n' ' ') ] nodes."
+ rmq_init_and_wait
+ if [ $? -ne 0 ]; then
+ return $OCF_ERR_GENERIC
+ fi
+
+ # unconditionally join the cluster
+ $RMQ_CTL stop_app > /dev/null 2>&1
+ for node in $(echo "$join_list"); do
+ ocf_log info "Attempting to join cluster with target node $node"
+ $RMQ_CTL join_cluster $node
+ if [ $? -eq 0 ]; then
+ ocf_log info "Joined cluster by connecting to node $node, starting app"
+ $RMQ_CTL start_app
+ rc=$?
+ if [ $rc -ne 0 ]; then
+ ocf_log err "'$RMQ_CTL start_app' failed"
+ fi
+ break;
+ fi
+ done
+
+ if [ "$rc" -ne 0 ]; then
+ ocf_log info "Join process incomplete, shutting down."
+ return $OCF_ERR_GENERIC
+ fi
+
+ ocf_log info "Successfully joined existing rabbitmq cluster"
+ return $OCF_SUCCESS
+}
+
+rmq_start() {
+ local join_list=""
+ local rc
+
+ rmq_monitor
+ if [ $? -eq $OCF_SUCCESS ]; then
+ return $OCF_SUCCESS
+ fi
+
+ join_list=$(rmq_join_list)
+
+ # No join list means no active instances are up. This instance
+ # is the first, so it needs to bootstrap the rest
+ if [ -z "$join_list" ]; then
+ rmq_start_first
+ rc=$?
+ return $rc
+ fi
+
+ # first try to join without wiping mnesia data
+ rmq_join_existing "$join_list"
+ if [ $? -ne 0 ]; then
+ ocf_log info "node failed to join, wiping data directory and trying again"
+ # if the graceful join fails, use the hammer and reset all the data.
+ rmq_stop
+ rmq_wipe_data
+ rmq_join_existing "$join_list"
+ if [ $? -ne 0 ]; then
+ ocf_log info "node failed to join even after reseting local data. Check SELINUX policy"
+ return $OCF_ERR_GENERIC
+ fi
+ fi
+
+ return $OCF_SUCCESS
+}
+
+rmq_stop() {
+ rmq_monitor
+ if [ $? -eq $OCF_NOT_RUNNING ]; then
+ return $OCF_SUCCESS
+ fi
+
+ $RMQ_CTL stop
+ rc=$?
+
+ if [ $rc -ne 0 ]; then
+ ocf_log err "rabbitmq-server stop command failed: $RMQ_CTL stop, $rc"
+ return $rc
+ fi
+
+ #TODO add kill logic
+ stop_wait=1
+ while [ $stop_wait = 1 ]; do
+ rmq_monitor
+ rc=$?
+ if [ "$rc" -eq $OCF_NOT_RUNNING ]; then
+ stop_wait=0
+ break
+ elif [ "$rc" -ne $OCF_SUCCESS ]; then
+ ocf_log info "rabbitmq-server stop failed: $rc"
+ exit $OCF_ERR_GENERIC
+ fi
+ sleep 1
+ done
+
+ remove_pid
+ return $OCF_SUCCESS
+}
+
+rmq_validate() {
+ check_binary $RMQ_SERVER
+ check_binary $RMQ_CTL
+
+ # This resource only makes sense as a clone right now. at some point
+ # we may want to verify the following.
+ #TODO verify cloned
+ #TODO verify ordered=true
+
+ # Given that this resource does the cluster join explicitly,
+ # having a cluster_nodes list in the static config file will
+ # likely conflict with this agent.
+ #TODO verify no cluster list in rabbitmq conf
+ #cat /etc/rabbitmq/rabbitmq.config | grep "cluster_nodes"
+
+ return $OCF_SUCCESS
+}
+
+case $__OCF_ACTION in
+meta-data) meta_data
+ exit $OCF_SUCCESS
+ ;;
+start) rmq_start;;
+stop) rmq_stop;;
+monitor) rmq_monitor;;
+validate-all) rmq_validate;;
+usage|help) rmq_usage
+ exit $OCF_SUCCESS
+ ;;
+*) rmq_usage
+ exit $OCF_ERR_UNIMPLEMENTED
+ ;;
+esac
+rc=$?
+ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
+exit $rc
+

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jul 8, 6:15 PM (21 h, 54 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2002053
Default Alt Text
(20 KB)

Event Timeline